]>
Commit | Line | Data |
---|---|---|
85d5e707 KVA |
1 | /** |
2 | * core.c - DesignWare USB3 DRD Controller Core file | |
3 | * | |
30c31d58 | 4 | * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com |
85d5e707 KVA |
5 | * |
6 | * Authors: Felipe Balbi <balbi@ti.com>, | |
7 | * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | |
8 | * | |
30c31d58 KVA |
9 | * Taken from Linux Kernel v3.19-rc1 (drivers/usb/dwc3/core.c) and ported |
10 | * to uboot. | |
85d5e707 | 11 | * |
30c31d58 | 12 | * commit cd72f890d2 : usb: dwc3: core: enable phy suspend quirk on non-FPGA |
85d5e707 | 13 | * |
30c31d58 | 14 | * SPDX-License-Identifier: GPL-2.0 |
85d5e707 KVA |
15 | */ |
16 | ||
17 | #include <linux/version.h> | |
18 | #include <linux/module.h> | |
19 | #include <linux/kernel.h> | |
20 | #include <linux/slab.h> | |
21 | #include <linux/spinlock.h> | |
22 | #include <linux/platform_device.h> | |
85d5e707 KVA |
23 | #include <linux/interrupt.h> |
24 | #include <linux/ioport.h> | |
25 | #include <linux/io.h> | |
26 | #include <linux/list.h> | |
27 | #include <linux/delay.h> | |
28 | #include <linux/dma-mapping.h> | |
29 | #include <linux/of.h> | |
30 | #include <linux/acpi.h> | |
31 | ||
32 | #include <linux/usb/ch9.h> | |
33 | #include <linux/usb/gadget.h> | |
34 | #include <linux/usb/of.h> | |
35 | #include <linux/usb/otg.h> | |
36 | ||
37 | #include "platform_data.h" | |
38 | #include "core.h" | |
39 | #include "gadget.h" | |
40 | #include "io.h" | |
41 | ||
42 | #include "debug.h" | |
43 | ||
44 | /* -------------------------------------------------------------------------- */ | |
45 | ||
46 | void dwc3_set_mode(struct dwc3 *dwc, u32 mode) | |
47 | { | |
48 | u32 reg; | |
49 | ||
50 | reg = dwc3_readl(dwc->regs, DWC3_GCTL); | |
51 | reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); | |
52 | reg |= DWC3_GCTL_PRTCAPDIR(mode); | |
53 | dwc3_writel(dwc->regs, DWC3_GCTL, reg); | |
54 | } | |
55 | ||
56 | /** | |
57 | * dwc3_core_soft_reset - Issues core soft reset and PHY reset | |
58 | * @dwc: pointer to our context structure | |
59 | */ | |
60 | static int dwc3_core_soft_reset(struct dwc3 *dwc) | |
61 | { | |
62 | u32 reg; | |
63 | int ret; | |
64 | ||
65 | /* Before Resetting PHY, put Core in Reset */ | |
66 | reg = dwc3_readl(dwc->regs, DWC3_GCTL); | |
67 | reg |= DWC3_GCTL_CORESOFTRESET; | |
68 | dwc3_writel(dwc->regs, DWC3_GCTL, reg); | |
69 | ||
70 | /* Assert USB3 PHY reset */ | |
71 | reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); | |
72 | reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; | |
73 | dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); | |
74 | ||
75 | /* Assert USB2 PHY reset */ | |
76 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | |
77 | reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; | |
78 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | |
79 | ||
80 | usb_phy_init(dwc->usb2_phy); | |
81 | usb_phy_init(dwc->usb3_phy); | |
82 | ret = phy_init(dwc->usb2_generic_phy); | |
83 | if (ret < 0) | |
84 | return ret; | |
85 | ||
86 | ret = phy_init(dwc->usb3_generic_phy); | |
87 | if (ret < 0) { | |
88 | phy_exit(dwc->usb2_generic_phy); | |
89 | return ret; | |
90 | } | |
91 | mdelay(100); | |
92 | ||
93 | /* Clear USB3 PHY reset */ | |
94 | reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); | |
95 | reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; | |
96 | dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); | |
97 | ||
98 | /* Clear USB2 PHY reset */ | |
99 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | |
100 | reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; | |
101 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | |
102 | ||
103 | mdelay(100); | |
104 | ||
105 | /* After PHYs are stable we can take Core out of reset state */ | |
106 | reg = dwc3_readl(dwc->regs, DWC3_GCTL); | |
107 | reg &= ~DWC3_GCTL_CORESOFTRESET; | |
108 | dwc3_writel(dwc->regs, DWC3_GCTL, reg); | |
109 | ||
110 | return 0; | |
111 | } | |
112 | ||
113 | /** | |
114 | * dwc3_free_one_event_buffer - Frees one event buffer | |
115 | * @dwc: Pointer to our controller context structure | |
116 | * @evt: Pointer to event buffer to be freed | |
117 | */ | |
118 | static void dwc3_free_one_event_buffer(struct dwc3 *dwc, | |
119 | struct dwc3_event_buffer *evt) | |
120 | { | |
121 | dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); | |
122 | } | |
123 | ||
124 | /** | |
125 | * dwc3_alloc_one_event_buffer - Allocates one event buffer structure | |
126 | * @dwc: Pointer to our controller context structure | |
127 | * @length: size of the event buffer | |
128 | * | |
129 | * Returns a pointer to the allocated event buffer structure on success | |
130 | * otherwise ERR_PTR(errno). | |
131 | */ | |
132 | static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, | |
133 | unsigned length) | |
134 | { | |
135 | struct dwc3_event_buffer *evt; | |
136 | ||
137 | evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); | |
138 | if (!evt) | |
139 | return ERR_PTR(-ENOMEM); | |
140 | ||
141 | evt->dwc = dwc; | |
142 | evt->length = length; | |
143 | evt->buf = dma_alloc_coherent(dwc->dev, length, | |
144 | &evt->dma, GFP_KERNEL); | |
145 | if (!evt->buf) | |
146 | return ERR_PTR(-ENOMEM); | |
147 | ||
148 | return evt; | |
149 | } | |
150 | ||
151 | /** | |
152 | * dwc3_free_event_buffers - frees all allocated event buffers | |
153 | * @dwc: Pointer to our controller context structure | |
154 | */ | |
155 | static void dwc3_free_event_buffers(struct dwc3 *dwc) | |
156 | { | |
157 | struct dwc3_event_buffer *evt; | |
158 | int i; | |
159 | ||
160 | for (i = 0; i < dwc->num_event_buffers; i++) { | |
161 | evt = dwc->ev_buffs[i]; | |
162 | if (evt) | |
163 | dwc3_free_one_event_buffer(dwc, evt); | |
164 | } | |
165 | } | |
166 | ||
167 | /** | |
168 | * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length | |
169 | * @dwc: pointer to our controller context structure | |
170 | * @length: size of event buffer | |
171 | * | |
172 | * Returns 0 on success otherwise negative errno. In the error case, dwc | |
173 | * may contain some buffers allocated but not all which were requested. | |
174 | */ | |
175 | static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) | |
176 | { | |
177 | int num; | |
178 | int i; | |
179 | ||
180 | num = DWC3_NUM_INT(dwc->hwparams.hwparams1); | |
181 | dwc->num_event_buffers = num; | |
182 | ||
183 | dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num, | |
184 | GFP_KERNEL); | |
185 | if (!dwc->ev_buffs) | |
186 | return -ENOMEM; | |
187 | ||
188 | for (i = 0; i < num; i++) { | |
189 | struct dwc3_event_buffer *evt; | |
190 | ||
191 | evt = dwc3_alloc_one_event_buffer(dwc, length); | |
192 | if (IS_ERR(evt)) { | |
193 | dev_err(dwc->dev, "can't allocate event buffer\n"); | |
194 | return PTR_ERR(evt); | |
195 | } | |
196 | dwc->ev_buffs[i] = evt; | |
197 | } | |
198 | ||
199 | return 0; | |
200 | } | |
201 | ||
202 | /** | |
203 | * dwc3_event_buffers_setup - setup our allocated event buffers | |
204 | * @dwc: pointer to our controller context structure | |
205 | * | |
206 | * Returns 0 on success otherwise negative errno. | |
207 | */ | |
208 | static int dwc3_event_buffers_setup(struct dwc3 *dwc) | |
209 | { | |
210 | struct dwc3_event_buffer *evt; | |
211 | int n; | |
212 | ||
213 | for (n = 0; n < dwc->num_event_buffers; n++) { | |
214 | evt = dwc->ev_buffs[n]; | |
215 | dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", | |
216 | evt->buf, (unsigned long long) evt->dma, | |
217 | evt->length); | |
218 | ||
219 | evt->lpos = 0; | |
220 | ||
221 | dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), | |
222 | lower_32_bits(evt->dma)); | |
223 | dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), | |
224 | upper_32_bits(evt->dma)); | |
225 | dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), | |
226 | DWC3_GEVNTSIZ_SIZE(evt->length)); | |
227 | dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); | |
228 | } | |
229 | ||
230 | return 0; | |
231 | } | |
232 | ||
233 | static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) | |
234 | { | |
235 | struct dwc3_event_buffer *evt; | |
236 | int n; | |
237 | ||
238 | for (n = 0; n < dwc->num_event_buffers; n++) { | |
239 | evt = dwc->ev_buffs[n]; | |
240 | ||
241 | evt->lpos = 0; | |
242 | ||
243 | dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); | |
244 | dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); | |
245 | dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK | |
246 | | DWC3_GEVNTSIZ_SIZE(0)); | |
247 | dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); | |
248 | } | |
249 | } | |
250 | ||
251 | static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) | |
252 | { | |
253 | if (!dwc->has_hibernation) | |
254 | return 0; | |
255 | ||
256 | if (!dwc->nr_scratch) | |
257 | return 0; | |
258 | ||
259 | dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, | |
260 | DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); | |
261 | if (!dwc->scratchbuf) | |
262 | return -ENOMEM; | |
263 | ||
264 | return 0; | |
265 | } | |
266 | ||
267 | static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) | |
268 | { | |
269 | dma_addr_t scratch_addr; | |
270 | u32 param; | |
271 | int ret; | |
272 | ||
273 | if (!dwc->has_hibernation) | |
274 | return 0; | |
275 | ||
276 | if (!dwc->nr_scratch) | |
277 | return 0; | |
278 | ||
279 | /* should never fall here */ | |
280 | if (!WARN_ON(dwc->scratchbuf)) | |
281 | return 0; | |
282 | ||
283 | scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf, | |
284 | dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, | |
285 | DMA_BIDIRECTIONAL); | |
286 | if (dma_mapping_error(dwc->dev, scratch_addr)) { | |
287 | dev_err(dwc->dev, "failed to map scratch buffer\n"); | |
288 | ret = -EFAULT; | |
289 | goto err0; | |
290 | } | |
291 | ||
292 | dwc->scratch_addr = scratch_addr; | |
293 | ||
294 | param = lower_32_bits(scratch_addr); | |
295 | ||
296 | ret = dwc3_send_gadget_generic_command(dwc, | |
297 | DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); | |
298 | if (ret < 0) | |
299 | goto err1; | |
300 | ||
301 | param = upper_32_bits(scratch_addr); | |
302 | ||
303 | ret = dwc3_send_gadget_generic_command(dwc, | |
304 | DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); | |
305 | if (ret < 0) | |
306 | goto err1; | |
307 | ||
308 | return 0; | |
309 | ||
310 | err1: | |
311 | dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * | |
312 | DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); | |
313 | ||
314 | err0: | |
315 | return ret; | |
316 | } | |
317 | ||
318 | static void dwc3_free_scratch_buffers(struct dwc3 *dwc) | |
319 | { | |
320 | if (!dwc->has_hibernation) | |
321 | return; | |
322 | ||
323 | if (!dwc->nr_scratch) | |
324 | return; | |
325 | ||
326 | /* should never fall here */ | |
327 | if (!WARN_ON(dwc->scratchbuf)) | |
328 | return; | |
329 | ||
330 | dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * | |
331 | DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); | |
332 | kfree(dwc->scratchbuf); | |
333 | } | |
334 | ||
335 | static void dwc3_core_num_eps(struct dwc3 *dwc) | |
336 | { | |
337 | struct dwc3_hwparams *parms = &dwc->hwparams; | |
338 | ||
339 | dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); | |
340 | dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; | |
341 | ||
342 | dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n", | |
343 | dwc->num_in_eps, dwc->num_out_eps); | |
344 | } | |
345 | ||
346 | static void dwc3_cache_hwparams(struct dwc3 *dwc) | |
347 | { | |
348 | struct dwc3_hwparams *parms = &dwc->hwparams; | |
349 | ||
350 | parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); | |
351 | parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); | |
352 | parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); | |
353 | parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); | |
354 | parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); | |
355 | parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); | |
356 | parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); | |
357 | parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); | |
358 | parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); | |
359 | } | |
360 | ||
361 | /** | |
362 | * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core | |
363 | * @dwc: Pointer to our controller context structure | |
364 | */ | |
365 | static void dwc3_phy_setup(struct dwc3 *dwc) | |
366 | { | |
367 | u32 reg; | |
368 | ||
369 | reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); | |
370 | ||
371 | /* | |
372 | * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY | |
373 | * to '0' during coreConsultant configuration. So default value | |
374 | * will be '0' when the core is reset. Application needs to set it | |
375 | * to '1' after the core initialization is completed. | |
376 | */ | |
377 | if (dwc->revision > DWC3_REVISION_194A) | |
378 | reg |= DWC3_GUSB3PIPECTL_SUSPHY; | |
379 | ||
380 | if (dwc->u2ss_inp3_quirk) | |
381 | reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; | |
382 | ||
383 | if (dwc->req_p1p2p3_quirk) | |
384 | reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; | |
385 | ||
386 | if (dwc->del_p1p2p3_quirk) | |
387 | reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; | |
388 | ||
389 | if (dwc->del_phy_power_chg_quirk) | |
390 | reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; | |
391 | ||
392 | if (dwc->lfps_filter_quirk) | |
393 | reg |= DWC3_GUSB3PIPECTL_LFPSFILT; | |
394 | ||
395 | if (dwc->rx_detect_poll_quirk) | |
396 | reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; | |
397 | ||
398 | if (dwc->tx_de_emphasis_quirk) | |
399 | reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); | |
400 | ||
401 | if (dwc->dis_u3_susphy_quirk) | |
402 | reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; | |
403 | ||
404 | dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); | |
405 | ||
406 | mdelay(100); | |
407 | ||
408 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | |
409 | ||
410 | /* | |
411 | * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to | |
412 | * '0' during coreConsultant configuration. So default value will | |
413 | * be '0' when the core is reset. Application needs to set it to | |
414 | * '1' after the core initialization is completed. | |
415 | */ | |
416 | if (dwc->revision > DWC3_REVISION_194A) | |
417 | reg |= DWC3_GUSB2PHYCFG_SUSPHY; | |
418 | ||
419 | if (dwc->dis_u2_susphy_quirk) | |
420 | reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; | |
421 | ||
422 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | |
423 | ||
424 | mdelay(100); | |
425 | } | |
426 | ||
427 | /** | |
428 | * dwc3_core_init - Low-level initialization of DWC3 Core | |
429 | * @dwc: Pointer to our controller context structure | |
430 | * | |
431 | * Returns 0 on success otherwise negative errno. | |
432 | */ | |
433 | static int dwc3_core_init(struct dwc3 *dwc) | |
434 | { | |
435 | unsigned long timeout; | |
436 | u32 hwparams4 = dwc->hwparams.hwparams4; | |
437 | u32 reg; | |
438 | int ret; | |
439 | ||
440 | reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); | |
441 | /* This should read as U3 followed by revision number */ | |
442 | if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { | |
443 | dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); | |
444 | ret = -ENODEV; | |
445 | goto err0; | |
446 | } | |
447 | dwc->revision = reg; | |
448 | ||
449 | /* | |
450 | * Write Linux Version Code to our GUID register so it's easy to figure | |
451 | * out which kernel version a bug was found. | |
452 | */ | |
453 | dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); | |
454 | ||
455 | /* Handle USB2.0-only core configuration */ | |
456 | if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == | |
457 | DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { | |
458 | if (dwc->maximum_speed == USB_SPEED_SUPER) | |
459 | dwc->maximum_speed = USB_SPEED_HIGH; | |
460 | } | |
461 | ||
462 | /* issue device SoftReset too */ | |
463 | timeout = jiffies + msecs_to_jiffies(500); | |
464 | dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); | |
465 | do { | |
466 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); | |
467 | if (!(reg & DWC3_DCTL_CSFTRST)) | |
468 | break; | |
469 | ||
470 | if (time_after(jiffies, timeout)) { | |
471 | dev_err(dwc->dev, "Reset Timed Out\n"); | |
472 | ret = -ETIMEDOUT; | |
473 | goto err0; | |
474 | } | |
475 | ||
476 | cpu_relax(); | |
477 | } while (true); | |
478 | ||
479 | ret = dwc3_core_soft_reset(dwc); | |
480 | if (ret) | |
481 | goto err0; | |
482 | ||
483 | reg = dwc3_readl(dwc->regs, DWC3_GCTL); | |
484 | reg &= ~DWC3_GCTL_SCALEDOWN_MASK; | |
485 | ||
486 | switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { | |
487 | case DWC3_GHWPARAMS1_EN_PWROPT_CLK: | |
488 | /** | |
489 | * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an | |
490 | * issue which would cause xHCI compliance tests to fail. | |
491 | * | |
492 | * Because of that we cannot enable clock gating on such | |
493 | * configurations. | |
494 | * | |
495 | * Refers to: | |
496 | * | |
497 | * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based | |
498 | * SOF/ITP Mode Used | |
499 | */ | |
500 | if ((dwc->dr_mode == USB_DR_MODE_HOST || | |
501 | dwc->dr_mode == USB_DR_MODE_OTG) && | |
502 | (dwc->revision >= DWC3_REVISION_210A && | |
503 | dwc->revision <= DWC3_REVISION_250A)) | |
504 | reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; | |
505 | else | |
506 | reg &= ~DWC3_GCTL_DSBLCLKGTNG; | |
507 | break; | |
508 | case DWC3_GHWPARAMS1_EN_PWROPT_HIB: | |
509 | /* enable hibernation here */ | |
510 | dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); | |
511 | ||
512 | /* | |
513 | * REVISIT Enabling this bit so that host-mode hibernation | |
514 | * will work. Device-mode hibernation is not yet implemented. | |
515 | */ | |
516 | reg |= DWC3_GCTL_GBLHIBERNATIONEN; | |
517 | break; | |
518 | default: | |
519 | dev_dbg(dwc->dev, "No power optimization available\n"); | |
520 | } | |
521 | ||
522 | /* check if current dwc3 is on simulation board */ | |
523 | if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { | |
524 | dev_dbg(dwc->dev, "it is on FPGA board\n"); | |
525 | dwc->is_fpga = true; | |
526 | } | |
527 | ||
528 | WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, | |
529 | "disable_scramble cannot be used on non-FPGA builds\n"); | |
530 | ||
531 | if (dwc->disable_scramble_quirk && dwc->is_fpga) | |
532 | reg |= DWC3_GCTL_DISSCRAMBLE; | |
533 | else | |
534 | reg &= ~DWC3_GCTL_DISSCRAMBLE; | |
535 | ||
536 | if (dwc->u2exit_lfps_quirk) | |
537 | reg |= DWC3_GCTL_U2EXIT_LFPS; | |
538 | ||
539 | /* | |
540 | * WORKAROUND: DWC3 revisions <1.90a have a bug | |
541 | * where the device can fail to connect at SuperSpeed | |
542 | * and falls back to high-speed mode which causes | |
543 | * the device to enter a Connect/Disconnect loop | |
544 | */ | |
545 | if (dwc->revision < DWC3_REVISION_190A) | |
546 | reg |= DWC3_GCTL_U2RSTECN; | |
547 | ||
548 | dwc3_core_num_eps(dwc); | |
549 | ||
550 | dwc3_writel(dwc->regs, DWC3_GCTL, reg); | |
551 | ||
552 | dwc3_phy_setup(dwc); | |
553 | ||
554 | ret = dwc3_alloc_scratch_buffers(dwc); | |
555 | if (ret) | |
556 | goto err1; | |
557 | ||
558 | ret = dwc3_setup_scratch_buffers(dwc); | |
559 | if (ret) | |
560 | goto err2; | |
561 | ||
562 | return 0; | |
563 | ||
564 | err2: | |
565 | dwc3_free_scratch_buffers(dwc); | |
566 | ||
567 | err1: | |
568 | usb_phy_shutdown(dwc->usb2_phy); | |
569 | usb_phy_shutdown(dwc->usb3_phy); | |
570 | phy_exit(dwc->usb2_generic_phy); | |
571 | phy_exit(dwc->usb3_generic_phy); | |
572 | ||
573 | err0: | |
574 | return ret; | |
575 | } | |
576 | ||
577 | static void dwc3_core_exit(struct dwc3 *dwc) | |
578 | { | |
579 | dwc3_free_scratch_buffers(dwc); | |
580 | usb_phy_shutdown(dwc->usb2_phy); | |
581 | usb_phy_shutdown(dwc->usb3_phy); | |
582 | phy_exit(dwc->usb2_generic_phy); | |
583 | phy_exit(dwc->usb3_generic_phy); | |
584 | } | |
585 | ||
586 | static int dwc3_core_get_phy(struct dwc3 *dwc) | |
587 | { | |
588 | struct device *dev = dwc->dev; | |
589 | struct device_node *node = dev->of_node; | |
590 | int ret; | |
591 | ||
592 | if (node) { | |
593 | dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); | |
594 | dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); | |
595 | } else { | |
596 | dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); | |
597 | dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); | |
598 | } | |
599 | ||
600 | if (IS_ERR(dwc->usb2_phy)) { | |
601 | ret = PTR_ERR(dwc->usb2_phy); | |
602 | if (ret == -ENXIO || ret == -ENODEV) { | |
603 | dwc->usb2_phy = NULL; | |
604 | } else if (ret == -EPROBE_DEFER) { | |
605 | return ret; | |
606 | } else { | |
607 | dev_err(dev, "no usb2 phy configured\n"); | |
608 | return ret; | |
609 | } | |
610 | } | |
611 | ||
612 | if (IS_ERR(dwc->usb3_phy)) { | |
613 | ret = PTR_ERR(dwc->usb3_phy); | |
614 | if (ret == -ENXIO || ret == -ENODEV) { | |
615 | dwc->usb3_phy = NULL; | |
616 | } else if (ret == -EPROBE_DEFER) { | |
617 | return ret; | |
618 | } else { | |
619 | dev_err(dev, "no usb3 phy configured\n"); | |
620 | return ret; | |
621 | } | |
622 | } | |
623 | ||
624 | dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); | |
625 | if (IS_ERR(dwc->usb2_generic_phy)) { | |
626 | ret = PTR_ERR(dwc->usb2_generic_phy); | |
627 | if (ret == -ENOSYS || ret == -ENODEV) { | |
628 | dwc->usb2_generic_phy = NULL; | |
629 | } else if (ret == -EPROBE_DEFER) { | |
630 | return ret; | |
631 | } else { | |
632 | dev_err(dev, "no usb2 phy configured\n"); | |
633 | return ret; | |
634 | } | |
635 | } | |
636 | ||
637 | dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); | |
638 | if (IS_ERR(dwc->usb3_generic_phy)) { | |
639 | ret = PTR_ERR(dwc->usb3_generic_phy); | |
640 | if (ret == -ENOSYS || ret == -ENODEV) { | |
641 | dwc->usb3_generic_phy = NULL; | |
642 | } else if (ret == -EPROBE_DEFER) { | |
643 | return ret; | |
644 | } else { | |
645 | dev_err(dev, "no usb3 phy configured\n"); | |
646 | return ret; | |
647 | } | |
648 | } | |
649 | ||
650 | return 0; | |
651 | } | |
652 | ||
653 | static int dwc3_core_init_mode(struct dwc3 *dwc) | |
654 | { | |
655 | struct device *dev = dwc->dev; | |
656 | int ret; | |
657 | ||
658 | switch (dwc->dr_mode) { | |
659 | case USB_DR_MODE_PERIPHERAL: | |
660 | dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); | |
661 | ret = dwc3_gadget_init(dwc); | |
662 | if (ret) { | |
663 | dev_err(dev, "failed to initialize gadget\n"); | |
664 | return ret; | |
665 | } | |
666 | break; | |
667 | case USB_DR_MODE_HOST: | |
668 | dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); | |
669 | ret = dwc3_host_init(dwc); | |
670 | if (ret) { | |
671 | dev_err(dev, "failed to initialize host\n"); | |
672 | return ret; | |
673 | } | |
674 | break; | |
675 | case USB_DR_MODE_OTG: | |
676 | dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); | |
677 | ret = dwc3_host_init(dwc); | |
678 | if (ret) { | |
679 | dev_err(dev, "failed to initialize host\n"); | |
680 | return ret; | |
681 | } | |
682 | ||
683 | ret = dwc3_gadget_init(dwc); | |
684 | if (ret) { | |
685 | dev_err(dev, "failed to initialize gadget\n"); | |
686 | return ret; | |
687 | } | |
688 | break; | |
689 | default: | |
690 | dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); | |
691 | return -EINVAL; | |
692 | } | |
693 | ||
694 | return 0; | |
695 | } | |
696 | ||
697 | static void dwc3_core_exit_mode(struct dwc3 *dwc) | |
698 | { | |
699 | switch (dwc->dr_mode) { | |
700 | case USB_DR_MODE_PERIPHERAL: | |
701 | dwc3_gadget_exit(dwc); | |
702 | break; | |
703 | case USB_DR_MODE_HOST: | |
704 | dwc3_host_exit(dwc); | |
705 | break; | |
706 | case USB_DR_MODE_OTG: | |
707 | dwc3_host_exit(dwc); | |
708 | dwc3_gadget_exit(dwc); | |
709 | break; | |
710 | default: | |
711 | /* do nothing */ | |
712 | break; | |
713 | } | |
714 | } | |
715 | ||
716 | #define DWC3_ALIGN_MASK (16 - 1) | |
717 | ||
718 | static int dwc3_probe(struct platform_device *pdev) | |
719 | { | |
720 | struct device *dev = &pdev->dev; | |
721 | struct dwc3_platform_data *pdata = dev_get_platdata(dev); | |
722 | struct device_node *node = dev->of_node; | |
723 | struct resource *res; | |
724 | struct dwc3 *dwc; | |
725 | u8 lpm_nyet_threshold; | |
726 | u8 tx_de_emphasis; | |
727 | u8 hird_threshold; | |
728 | ||
729 | int ret; | |
730 | ||
731 | void __iomem *regs; | |
732 | void *mem; | |
733 | ||
734 | mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); | |
735 | if (!mem) | |
736 | return -ENOMEM; | |
737 | ||
738 | dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); | |
739 | dwc->mem = mem; | |
740 | dwc->dev = dev; | |
741 | ||
742 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | |
743 | if (!res) { | |
744 | dev_err(dev, "missing IRQ\n"); | |
745 | return -ENODEV; | |
746 | } | |
747 | dwc->xhci_resources[1].start = res->start; | |
748 | dwc->xhci_resources[1].end = res->end; | |
749 | dwc->xhci_resources[1].flags = res->flags; | |
750 | dwc->xhci_resources[1].name = res->name; | |
751 | ||
752 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
753 | if (!res) { | |
754 | dev_err(dev, "missing memory resource\n"); | |
755 | return -ENODEV; | |
756 | } | |
757 | ||
758 | dwc->xhci_resources[0].start = res->start; | |
759 | dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + | |
760 | DWC3_XHCI_REGS_END; | |
761 | dwc->xhci_resources[0].flags = res->flags; | |
762 | dwc->xhci_resources[0].name = res->name; | |
763 | ||
764 | res->start += DWC3_GLOBALS_REGS_START; | |
765 | ||
766 | /* | |
767 | * Request memory region but exclude xHCI regs, | |
768 | * since it will be requested by the xhci-plat driver. | |
769 | */ | |
770 | regs = devm_ioremap_resource(dev, res); | |
771 | if (IS_ERR(regs)) | |
772 | return PTR_ERR(regs); | |
773 | ||
774 | dwc->regs = regs; | |
775 | dwc->regs_size = resource_size(res); | |
776 | /* | |
777 | * restore res->start back to its original value so that, | |
778 | * in case the probe is deferred, we don't end up getting error in | |
779 | * request the memory region the next time probe is called. | |
780 | */ | |
781 | res->start -= DWC3_GLOBALS_REGS_START; | |
782 | ||
783 | /* default to highest possible threshold */ | |
784 | lpm_nyet_threshold = 0xff; | |
785 | ||
786 | /* default to -3.5dB de-emphasis */ | |
787 | tx_de_emphasis = 1; | |
788 | ||
789 | /* | |
790 | * default to assert utmi_sleep_n and use maximum allowed HIRD | |
791 | * threshold value of 0b1100 | |
792 | */ | |
793 | hird_threshold = 12; | |
794 | ||
795 | if (node) { | |
796 | dwc->maximum_speed = of_usb_get_maximum_speed(node); | |
797 | dwc->has_lpm_erratum = of_property_read_bool(node, | |
798 | "snps,has-lpm-erratum"); | |
799 | of_property_read_u8(node, "snps,lpm-nyet-threshold", | |
800 | &lpm_nyet_threshold); | |
801 | dwc->is_utmi_l1_suspend = of_property_read_bool(node, | |
802 | "snps,is-utmi-l1-suspend"); | |
803 | of_property_read_u8(node, "snps,hird-threshold", | |
804 | &hird_threshold); | |
805 | ||
806 | dwc->needs_fifo_resize = of_property_read_bool(node, | |
807 | "tx-fifo-resize"); | |
808 | dwc->dr_mode = of_usb_get_dr_mode(node); | |
809 | ||
810 | dwc->disable_scramble_quirk = of_property_read_bool(node, | |
811 | "snps,disable_scramble_quirk"); | |
812 | dwc->u2exit_lfps_quirk = of_property_read_bool(node, | |
813 | "snps,u2exit_lfps_quirk"); | |
814 | dwc->u2ss_inp3_quirk = of_property_read_bool(node, | |
815 | "snps,u2ss_inp3_quirk"); | |
816 | dwc->req_p1p2p3_quirk = of_property_read_bool(node, | |
817 | "snps,req_p1p2p3_quirk"); | |
818 | dwc->del_p1p2p3_quirk = of_property_read_bool(node, | |
819 | "snps,del_p1p2p3_quirk"); | |
820 | dwc->del_phy_power_chg_quirk = of_property_read_bool(node, | |
821 | "snps,del_phy_power_chg_quirk"); | |
822 | dwc->lfps_filter_quirk = of_property_read_bool(node, | |
823 | "snps,lfps_filter_quirk"); | |
824 | dwc->rx_detect_poll_quirk = of_property_read_bool(node, | |
825 | "snps,rx_detect_poll_quirk"); | |
826 | dwc->dis_u3_susphy_quirk = of_property_read_bool(node, | |
827 | "snps,dis_u3_susphy_quirk"); | |
828 | dwc->dis_u2_susphy_quirk = of_property_read_bool(node, | |
829 | "snps,dis_u2_susphy_quirk"); | |
830 | ||
831 | dwc->tx_de_emphasis_quirk = of_property_read_bool(node, | |
832 | "snps,tx_de_emphasis_quirk"); | |
833 | of_property_read_u8(node, "snps,tx_de_emphasis", | |
834 | &tx_de_emphasis); | |
835 | } else if (pdata) { | |
836 | dwc->maximum_speed = pdata->maximum_speed; | |
837 | dwc->has_lpm_erratum = pdata->has_lpm_erratum; | |
838 | if (pdata->lpm_nyet_threshold) | |
839 | lpm_nyet_threshold = pdata->lpm_nyet_threshold; | |
840 | dwc->is_utmi_l1_suspend = pdata->is_utmi_l1_suspend; | |
841 | if (pdata->hird_threshold) | |
842 | hird_threshold = pdata->hird_threshold; | |
843 | ||
844 | dwc->needs_fifo_resize = pdata->tx_fifo_resize; | |
845 | dwc->dr_mode = pdata->dr_mode; | |
846 | ||
847 | dwc->disable_scramble_quirk = pdata->disable_scramble_quirk; | |
848 | dwc->u2exit_lfps_quirk = pdata->u2exit_lfps_quirk; | |
849 | dwc->u2ss_inp3_quirk = pdata->u2ss_inp3_quirk; | |
850 | dwc->req_p1p2p3_quirk = pdata->req_p1p2p3_quirk; | |
851 | dwc->del_p1p2p3_quirk = pdata->del_p1p2p3_quirk; | |
852 | dwc->del_phy_power_chg_quirk = pdata->del_phy_power_chg_quirk; | |
853 | dwc->lfps_filter_quirk = pdata->lfps_filter_quirk; | |
854 | dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk; | |
855 | dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk; | |
856 | dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk; | |
857 | ||
858 | dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk; | |
859 | if (pdata->tx_de_emphasis) | |
860 | tx_de_emphasis = pdata->tx_de_emphasis; | |
861 | } | |
862 | ||
863 | /* default to superspeed if no maximum_speed passed */ | |
864 | if (dwc->maximum_speed == USB_SPEED_UNKNOWN) | |
865 | dwc->maximum_speed = USB_SPEED_SUPER; | |
866 | ||
867 | dwc->lpm_nyet_threshold = lpm_nyet_threshold; | |
868 | dwc->tx_de_emphasis = tx_de_emphasis; | |
869 | ||
870 | dwc->hird_threshold = hird_threshold | |
871 | | (dwc->is_utmi_l1_suspend << 4); | |
872 | ||
873 | ret = dwc3_core_get_phy(dwc); | |
874 | if (ret) | |
875 | return ret; | |
876 | ||
877 | spin_lock_init(&dwc->lock); | |
878 | platform_set_drvdata(pdev, dwc); | |
879 | ||
880 | if (!dev->dma_mask) { | |
881 | dev->dma_mask = dev->parent->dma_mask; | |
882 | dev->dma_parms = dev->parent->dma_parms; | |
883 | dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); | |
884 | } | |
885 | ||
85d5e707 KVA |
886 | dwc3_cache_hwparams(dwc); |
887 | ||
888 | ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); | |
889 | if (ret) { | |
890 | dev_err(dwc->dev, "failed to allocate event buffers\n"); | |
891 | ret = -ENOMEM; | |
892 | goto err0; | |
893 | } | |
894 | ||
895 | if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) | |
896 | dwc->dr_mode = USB_DR_MODE_HOST; | |
897 | else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) | |
898 | dwc->dr_mode = USB_DR_MODE_PERIPHERAL; | |
899 | ||
900 | if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) | |
901 | dwc->dr_mode = USB_DR_MODE_OTG; | |
902 | ||
903 | ret = dwc3_core_init(dwc); | |
904 | if (ret) { | |
905 | dev_err(dev, "failed to initialize core\n"); | |
906 | goto err0; | |
907 | } | |
908 | ||
909 | usb_phy_set_suspend(dwc->usb2_phy, 0); | |
910 | usb_phy_set_suspend(dwc->usb3_phy, 0); | |
911 | ret = phy_power_on(dwc->usb2_generic_phy); | |
912 | if (ret < 0) | |
913 | goto err1; | |
914 | ||
915 | ret = phy_power_on(dwc->usb3_generic_phy); | |
916 | if (ret < 0) | |
917 | goto err_usb2phy_power; | |
918 | ||
919 | ret = dwc3_event_buffers_setup(dwc); | |
920 | if (ret) { | |
921 | dev_err(dwc->dev, "failed to setup event buffers\n"); | |
922 | goto err_usb3phy_power; | |
923 | } | |
924 | ||
925 | ret = dwc3_core_init_mode(dwc); | |
926 | if (ret) | |
927 | goto err2; | |
928 | ||
929 | ret = dwc3_debugfs_init(dwc); | |
930 | if (ret) { | |
931 | dev_err(dev, "failed to initialize debugfs\n"); | |
932 | goto err3; | |
933 | } | |
934 | ||
85d5e707 KVA |
935 | return 0; |
936 | ||
937 | err3: | |
938 | dwc3_core_exit_mode(dwc); | |
939 | ||
940 | err2: | |
941 | dwc3_event_buffers_cleanup(dwc); | |
942 | ||
943 | err_usb3phy_power: | |
944 | phy_power_off(dwc->usb3_generic_phy); | |
945 | ||
946 | err_usb2phy_power: | |
947 | phy_power_off(dwc->usb2_generic_phy); | |
948 | ||
949 | err1: | |
950 | usb_phy_set_suspend(dwc->usb2_phy, 1); | |
951 | usb_phy_set_suspend(dwc->usb3_phy, 1); | |
952 | dwc3_core_exit(dwc); | |
953 | ||
954 | err0: | |
955 | dwc3_free_event_buffers(dwc); | |
956 | ||
957 | return ret; | |
958 | } | |
959 | ||
960 | static int dwc3_remove(struct platform_device *pdev) | |
961 | { | |
962 | struct dwc3 *dwc = platform_get_drvdata(pdev); | |
963 | ||
964 | dwc3_debugfs_exit(dwc); | |
965 | dwc3_core_exit_mode(dwc); | |
966 | dwc3_event_buffers_cleanup(dwc); | |
967 | dwc3_free_event_buffers(dwc); | |
968 | ||
969 | usb_phy_set_suspend(dwc->usb2_phy, 1); | |
970 | usb_phy_set_suspend(dwc->usb3_phy, 1); | |
971 | phy_power_off(dwc->usb2_generic_phy); | |
972 | phy_power_off(dwc->usb3_generic_phy); | |
973 | ||
974 | dwc3_core_exit(dwc); | |
975 | ||
85d5e707 KVA |
976 | return 0; |
977 | } | |
978 | ||
85d5e707 KVA |
979 | #ifdef CONFIG_OF |
980 | static const struct of_device_id of_dwc3_match[] = { | |
981 | { | |
982 | .compatible = "snps,dwc3" | |
983 | }, | |
984 | { | |
985 | .compatible = "synopsys,dwc3" | |
986 | }, | |
987 | { }, | |
988 | }; | |
989 | MODULE_DEVICE_TABLE(of, of_dwc3_match); | |
990 | #endif | |
991 | ||
992 | #ifdef CONFIG_ACPI | |
993 | ||
994 | #define ACPI_ID_INTEL_BSW "808622B7" | |
995 | ||
996 | static const struct acpi_device_id dwc3_acpi_match[] = { | |
997 | { ACPI_ID_INTEL_BSW, 0 }, | |
998 | { }, | |
999 | }; | |
1000 | MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); | |
1001 | #endif | |
1002 | ||
1003 | static struct platform_driver dwc3_driver = { | |
1004 | .probe = dwc3_probe, | |
1005 | .remove = dwc3_remove, | |
1006 | .driver = { | |
1007 | .name = "dwc3", | |
1008 | .of_match_table = of_match_ptr(of_dwc3_match), | |
1009 | .acpi_match_table = ACPI_PTR(dwc3_acpi_match), | |
85d5e707 KVA |
1010 | }, |
1011 | }; | |
1012 | ||
1013 | module_platform_driver(dwc3_driver); | |
1014 | ||
1015 | MODULE_ALIAS("platform:dwc3"); | |
1016 | MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); | |
1017 | MODULE_LICENSE("GPL v2"); | |
1018 | MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); |