kernel: update kernel 4.1 to version 4.1.23
[openwrt.git] / target / linux / bcm53xx / patches-4.1 / 191-usb-xhci-add-Broadcom-specific-fake-doorbell.patch
1 From dd0e5f9a6a4aed849bdb80641c2a2350476cede7 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 v3 2/6] usb: 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
9 This fixes problem with controller seeing devices only in some small
10 percentage of cold boots.
11 This quirk is also added to the platform data so we can activate it
12 when we register our platform driver.
13
14 Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
15 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
16 ---
17  drivers/usb/host/xhci-plat.c     |  3 +++
18  drivers/usb/host/xhci.c          | 57 +++++++++++++++++++++++++++++++++++++---
19  drivers/usb/host/xhci.h          |  1 +
20  include/linux/usb/xhci_pdriver.h |  1 +
21  4 files changed, 59 insertions(+), 3 deletions(-)
22
23 --- a/drivers/usb/host/xhci-plat.c
24 +++ b/drivers/usb/host/xhci-plat.c
25 @@ -42,6 +42,9 @@ static void xhci_plat_quirks(struct devi
26         if ((node && of_property_read_bool(node, "usb3-lpm-capable")) ||
27                         (pdata && pdata->usb3_lpm_capable))
28                 xhci->quirks |= XHCI_LPM_SUPPORT;
29 +
30 +       if (pdata && pdata->usb3_fake_doorbell)
31 +               xhci->quirks |= XHCI_FAKE_DOORBELL;
32  }
33  
34  /* called during probe() after chip reset completes */
35 --- a/drivers/usb/host/xhci.c
36 +++ b/drivers/usb/host/xhci.c
37 @@ -121,6 +121,39 @@ int xhci_halt(struct xhci_hcd *xhci)
38         return ret;
39  }
40  
41 +static int xhci_fake_doorbell(struct xhci_hcd *xhci, int slot_id)
42 +{
43 +       u32 temp;
44 +
45 +       /* alloc a virt device for slot */
46 +       if (!xhci_alloc_virt_device(xhci, slot_id, NULL, GFP_NOIO)) {
47 +               xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
48 +               return -ENOMEM;
49 +       }
50 +
51 +       /* ring fake doorbell for slot_id ep 0 */
52 +       xhci_ring_ep_doorbell(xhci, slot_id, 0, 0);
53 +       usleep_range(1000, 1500);
54 +
55 +       /* read the status register to check if HSE is set or not? */
56 +       temp = readl(&xhci->op_regs->status);
57 +
58 +       /* clear HSE if set */
59 +       if (temp & STS_FATAL) {
60 +               xhci_dbg(xhci, "HSE problem detected, status: 0x%x\n", temp);
61 +               temp &= ~(0x1fff);
62 +               temp |= STS_FATAL;
63 +               writel(temp, &xhci->op_regs->status);
64 +               usleep_range(1000, 1500);
65 +               readl(&xhci->op_regs->status);
66 +       }
67 +
68 +       /* Free virt device */
69 +       xhci_free_virt_device(xhci, slot_id);
70 +
71 +       return 0;
72 +}
73 +
74  /*
75   * Set the run bit and wait for the host to be running.
76   */
77 @@ -568,10 +601,25 @@ int xhci_init(struct usb_hcd *hcd)
78  
79  static int xhci_run_finished(struct xhci_hcd *xhci)
80  {
81 -       if (xhci_start(xhci)) {
82 -               xhci_halt(xhci);
83 -               return -ENODEV;
84 +       int err;
85 +
86 +       err = xhci_start(xhci);
87 +       if (err) {
88 +               err = -ENODEV;
89 +               goto out_err;
90 +       }
91 +       if (xhci->quirks & XHCI_FAKE_DOORBELL) {
92 +               err = xhci_fake_doorbell(xhci, 1);
93 +               if (err)
94 +                       goto out_err;
95 +
96 +               err = xhci_start(xhci);
97 +               if (err) {
98 +                       err = -ENODEV;
99 +                       goto out_err;
100 +               }
101         }
102 +
103         xhci->shared_hcd->state = HC_STATE_RUNNING;
104         xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
105  
106 @@ -581,6 +629,9 @@ static int xhci_run_finished(struct xhci
107         xhci_dbg_trace(xhci, trace_xhci_dbg_init,
108                         "Finished xhci_run for USB3 roothub");
109         return 0;
110 +out_err:
111 +       xhci_halt(xhci);
112 +       return err;
113  }
114  
115  /*
116 --- a/drivers/usb/host/xhci.h
117 +++ b/drivers/usb/host/xhci.h
118 @@ -1573,6 +1573,7 @@ struct xhci_hcd {
119  #define XHCI_PME_STUCK_QUIRK   (1 << 20)
120  #define XHCI_SSIC_PORT_UNUSED  (1 << 22)
121  #define XHCI_NO_64BIT_SUPPORT  (1 << 23)
122 +#define XHCI_FAKE_DOORBELL     (1 << 24)
123         unsigned int            num_active_eps;
124         unsigned int            limit_active_eps;
125         /* There are two roothubs to keep track of bus suspend info for */
126 --- a/include/linux/usb/xhci_pdriver.h
127 +++ b/include/linux/usb/xhci_pdriver.h
128 @@ -22,6 +22,7 @@
129   */
130  struct usb_xhci_pdata {
131         unsigned        usb3_lpm_capable:1;
132 +       unsigned        usb3_fake_doorbell:1;
133  };
134  
135  #endif /* __USB_CORE_XHCI_PDRIVER_H */