blob: c443d56746dd5f342e39b9a982a126b3ddb8462b [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +05302/**
3 * core.c - DesignWare USB3 DRD Controller Core file
4 *
Nishanth Menoneaa39c62023-11-01 15:56:03 -05005 * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +05306 *
7 * Authors: Felipe Balbi <balbi@ti.com>,
8 * Sebastian Andrzej Siewior <bigeasy@linutronix.de>
9 *
Kishon Vijay Abraham Id1e431a2015-02-23 18:39:52 +053010 * Taken from Linux Kernel v3.19-rc1 (drivers/usb/dwc3/core.c) and ported
11 * to uboot.
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053012 *
Kishon Vijay Abraham Id1e431a2015-02-23 18:39:52 +053013 * commit cd72f890d2 : usb: dwc3: core: enable phy suspend quirk on non-FPGA
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053014 */
15
Sean Andersonf6785a82022-11-27 15:31:54 +010016#include <clk.h>
Simon Glass63334482019-11-14 12:57:39 -070017#include <cpu_func.h>
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +053018#include <malloc.h>
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +053019#include <dwc3-uboot.h>
Simon Glass9bc15642020-02-03 07:36:16 -070020#include <dm/device_compat.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070021#include <dm/devres.h>
Simon Glassc06c1be2020-05-10 11:40:08 -060022#include <linux/bug.h>
Simon Glassdbd79542020-05-10 11:40:11 -060023#include <linux/delay.h>
Masahiro Yamada6373a172020-02-14 16:40:19 +090024#include <linux/dma-mapping.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070025#include <linux/err.h>
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053026#include <linux/ioport.h>
Mugunthan V N121f93c2018-05-18 13:10:27 +020027#include <dm.h>
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +010028#include <generic-phy.h>
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053029#include <linux/usb/ch9.h>
30#include <linux/usb/gadget.h>
Balaji Prakash J840d2192022-11-27 15:31:53 +010031#include <linux/bitfield.h>
Sean Anderson27ef4e62022-11-27 15:31:55 +010032#include <linux/math64.h>
Igor Prusovc3421ea2023-11-09 20:10:04 +030033#include <linux/time.h>
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053034
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053035#include "core.h"
36#include "gadget.h"
37#include "io.h"
38
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +053039#include "linux-compat.h"
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053040
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +053041static LIST_HEAD(dwc3_list);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053042/* -------------------------------------------------------------------------- */
43
Joonyoung Shimbf35c602015-03-03 17:32:09 +010044static void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053045{
46 u32 reg;
47
48 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
49 reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
50 reg |= DWC3_GCTL_PRTCAPDIR(mode);
51 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
52}
53
54/**
55 * dwc3_core_soft_reset - Issues core soft reset and PHY reset
56 * @dwc: pointer to our context structure
57 */
58static int dwc3_core_soft_reset(struct dwc3 *dwc)
59{
60 u32 reg;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053061
62 /* Before Resetting PHY, put Core in Reset */
63 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
64 reg |= DWC3_GCTL_CORESOFTRESET;
65 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
66
67 /* Assert USB3 PHY reset */
68 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
69 reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
70 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
71
72 /* Assert USB2 PHY reset */
73 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
74 reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
75 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
76
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053077 mdelay(100);
78
79 /* Clear USB3 PHY reset */
80 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
81 reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
82 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
83
84 /* Clear USB2 PHY reset */
85 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
86 reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
87 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
88
89 mdelay(100);
90
91 /* After PHYs are stable we can take Core out of reset state */
92 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
93 reg &= ~DWC3_GCTL_CORESOFTRESET;
94 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
95
96 return 0;
97}
98
Michael Walle679f13c2021-10-15 15:15:21 +020099/*
100 * dwc3_frame_length_adjustment - Adjusts frame length if required
101 * @dwc3: Pointer to our controller context structure
102 * @fladj: Value of GFLADJ_30MHZ to adjust frame length
103 */
104static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj)
105{
106 u32 reg;
107
108 if (dwc->revision < DWC3_REVISION_250A)
109 return;
110
111 if (fladj == 0)
112 return;
113
114 reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
115 reg &= ~DWC3_GFLADJ_30MHZ_MASK;
116 reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj;
117 dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
118}
119
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530120/**
Balaji Prakash J840d2192022-11-27 15:31:53 +0100121 * dwc3_ref_clk_period - Reference clock period configuration
122 * Default reference clock period depends on hardware
123 * configuration. For systems with reference clock that differs
124 * from the default, this will set clock period in DWC3_GUCTL
125 * register.
126 * @dwc: Pointer to our controller context structure
127 * @ref_clk_per: reference clock period in ns
128 */
129static void dwc3_ref_clk_period(struct dwc3 *dwc)
130{
Sean Andersonf6785a82022-11-27 15:31:54 +0100131 unsigned long period;
Sean Anderson27ef4e62022-11-27 15:31:55 +0100132 unsigned long fladj;
133 unsigned long decr;
Sean Andersonf6785a82022-11-27 15:31:54 +0100134 unsigned long rate;
Balaji Prakash J840d2192022-11-27 15:31:53 +0100135 u32 reg;
136
Sean Andersonf6785a82022-11-27 15:31:54 +0100137 if (dwc->ref_clk) {
138 rate = clk_get_rate(dwc->ref_clk);
139 if (!rate)
140 return;
141 period = NSEC_PER_SEC / rate;
Sean Andersonf6785a82022-11-27 15:31:54 +0100142 } else {
Balaji Prakash J840d2192022-11-27 15:31:53 +0100143 return;
Sean Andersonf6785a82022-11-27 15:31:54 +0100144 }
Balaji Prakash J840d2192022-11-27 15:31:53 +0100145
146 reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
147 reg &= ~DWC3_GUCTL_REFCLKPER_MASK;
Sean Andersonf6785a82022-11-27 15:31:54 +0100148 reg |= FIELD_PREP(DWC3_GUCTL_REFCLKPER_MASK, period);
Balaji Prakash J840d2192022-11-27 15:31:53 +0100149 dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
Sean Anderson27ef4e62022-11-27 15:31:55 +0100150
151 if (dwc->revision <= DWC3_REVISION_250A)
152 return;
153
154 /*
155 * The calculation below is
156 *
157 * 125000 * (NSEC_PER_SEC / (rate * period) - 1)
158 *
159 * but rearranged for fixed-point arithmetic. The division must be
160 * 64-bit because 125000 * NSEC_PER_SEC doesn't fit in 32 bits (and
161 * neither does rate * period).
162 *
163 * Note that rate * period ~= NSEC_PER_SECOND, minus the number of
164 * nanoseconds of error caused by the truncation which happened during
165 * the division when calculating rate or period (whichever one was
166 * derived from the other). We first calculate the relative error, then
167 * scale it to units of 8 ppm.
168 */
169 fladj = div64_u64(125000ULL * NSEC_PER_SEC, (u64)rate * period);
170 fladj -= 125000;
171
172 /*
173 * The documented 240MHz constant is scaled by 2 to get PLS1 as well.
174 */
175 decr = 480000000 / rate;
176
177 reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
178 reg &= ~DWC3_GFLADJ_REFCLK_FLADJ_MASK
179 & ~DWC3_GFLADJ_240MHZDECR
180 & ~DWC3_GFLADJ_240MHZDECR_PLS1;
181 reg |= FIELD_PREP(DWC3_GFLADJ_REFCLK_FLADJ_MASK, fladj)
182 | FIELD_PREP(DWC3_GFLADJ_240MHZDECR, decr >> 1)
183 | FIELD_PREP(DWC3_GFLADJ_240MHZDECR_PLS1, decr & 1);
184 dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
Balaji Prakash J840d2192022-11-27 15:31:53 +0100185}
186
187/**
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530188 * dwc3_free_one_event_buffer - Frees one event buffer
189 * @dwc: Pointer to our controller context structure
190 * @evt: Pointer to event buffer to be freed
191 */
192static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
193 struct dwc3_event_buffer *evt)
194{
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530195 dma_free_coherent(evt->buf);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530196}
197
198/**
199 * dwc3_alloc_one_event_buffer - Allocates one event buffer structure
200 * @dwc: Pointer to our controller context structure
201 * @length: size of the event buffer
202 *
203 * Returns a pointer to the allocated event buffer structure on success
204 * otherwise ERR_PTR(errno).
205 */
206static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
207 unsigned length)
208{
209 struct dwc3_event_buffer *evt;
210
Mugunthan V N121f93c2018-05-18 13:10:27 +0200211 evt = devm_kzalloc((struct udevice *)dwc->dev, sizeof(*evt),
212 GFP_KERNEL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530213 if (!evt)
214 return ERR_PTR(-ENOMEM);
215
216 evt->dwc = dwc;
217 evt->length = length;
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530218 evt->buf = dma_alloc_coherent(length,
219 (unsigned long *)&evt->dma);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530220 if (!evt->buf)
221 return ERR_PTR(-ENOMEM);
222
Philipp Tomsich8e17c162017-04-06 16:58:53 +0200223 dwc3_flush_cache((uintptr_t)evt->buf, evt->length);
224
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530225 return evt;
226}
227
228/**
229 * dwc3_free_event_buffers - frees all allocated event buffers
230 * @dwc: Pointer to our controller context structure
231 */
232static void dwc3_free_event_buffers(struct dwc3 *dwc)
233{
234 struct dwc3_event_buffer *evt;
235 int i;
236
237 for (i = 0; i < dwc->num_event_buffers; i++) {
238 evt = dwc->ev_buffs[i];
239 if (evt)
240 dwc3_free_one_event_buffer(dwc, evt);
241 }
242}
243
244/**
245 * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length
246 * @dwc: pointer to our controller context structure
247 * @length: size of event buffer
248 *
249 * Returns 0 on success otherwise negative errno. In the error case, dwc
250 * may contain some buffers allocated but not all which were requested.
251 */
252static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
253{
254 int num;
255 int i;
256
257 num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
258 dwc->num_event_buffers = num;
259
Kishon Vijay Abraham Ic7bdfe32015-02-23 18:40:13 +0530260 dwc->ev_buffs = memalign(CONFIG_SYS_CACHELINE_SIZE,
261 sizeof(*dwc->ev_buffs) * num);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530262 if (!dwc->ev_buffs)
263 return -ENOMEM;
264
265 for (i = 0; i < num; i++) {
266 struct dwc3_event_buffer *evt;
267
268 evt = dwc3_alloc_one_event_buffer(dwc, length);
269 if (IS_ERR(evt)) {
270 dev_err(dwc->dev, "can't allocate event buffer\n");
271 return PTR_ERR(evt);
272 }
273 dwc->ev_buffs[i] = evt;
274 }
275
276 return 0;
277}
278
279/**
280 * dwc3_event_buffers_setup - setup our allocated event buffers
281 * @dwc: pointer to our controller context structure
282 *
283 * Returns 0 on success otherwise negative errno.
284 */
285static int dwc3_event_buffers_setup(struct dwc3 *dwc)
286{
287 struct dwc3_event_buffer *evt;
288 int n;
289
290 for (n = 0; n < dwc->num_event_buffers; n++) {
291 evt = dwc->ev_buffs[n];
292 dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n",
293 evt->buf, (unsigned long long) evt->dma,
294 evt->length);
295
296 evt->lpos = 0;
297
298 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
299 lower_32_bits(evt->dma));
300 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
301 upper_32_bits(evt->dma));
302 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
303 DWC3_GEVNTSIZ_SIZE(evt->length));
304 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
305 }
306
307 return 0;
308}
309
310static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
311{
312 struct dwc3_event_buffer *evt;
313 int n;
314
315 for (n = 0; n < dwc->num_event_buffers; n++) {
316 evt = dwc->ev_buffs[n];
317
318 evt->lpos = 0;
319
320 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
321 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
322 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK
323 | DWC3_GEVNTSIZ_SIZE(0));
324 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
325 }
326}
327
328static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
329{
330 if (!dwc->has_hibernation)
331 return 0;
332
333 if (!dwc->nr_scratch)
334 return 0;
335
336 dwc->scratchbuf = kmalloc_array(dwc->nr_scratch,
337 DWC3_SCRATCHBUF_SIZE, GFP_KERNEL);
338 if (!dwc->scratchbuf)
339 return -ENOMEM;
340
341 return 0;
342}
343
344static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
345{
346 dma_addr_t scratch_addr;
347 u32 param;
348 int ret;
349
350 if (!dwc->has_hibernation)
351 return 0;
352
353 if (!dwc->nr_scratch)
354 return 0;
355
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530356 scratch_addr = dma_map_single(dwc->scratchbuf,
357 dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
358 DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530359 if (dma_mapping_error(dwc->dev, scratch_addr)) {
360 dev_err(dwc->dev, "failed to map scratch buffer\n");
361 ret = -EFAULT;
362 goto err0;
363 }
364
365 dwc->scratch_addr = scratch_addr;
366
367 param = lower_32_bits(scratch_addr);
368
369 ret = dwc3_send_gadget_generic_command(dwc,
370 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param);
371 if (ret < 0)
372 goto err1;
373
374 param = upper_32_bits(scratch_addr);
375
376 ret = dwc3_send_gadget_generic_command(dwc,
377 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param);
378 if (ret < 0)
379 goto err1;
380
381 return 0;
382
383err1:
Masahiro Yamada05a5dba2020-02-14 16:40:18 +0900384 dma_unmap_single(scratch_addr, dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
385 DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530386
387err0:
388 return ret;
389}
390
391static void dwc3_free_scratch_buffers(struct dwc3 *dwc)
392{
393 if (!dwc->has_hibernation)
394 return;
395
396 if (!dwc->nr_scratch)
397 return;
398
Masahiro Yamada05a5dba2020-02-14 16:40:18 +0900399 dma_unmap_single(dwc->scratch_addr, dwc->nr_scratch *
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530400 DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530401 kfree(dwc->scratchbuf);
402}
403
404static void dwc3_core_num_eps(struct dwc3 *dwc)
405{
406 struct dwc3_hwparams *parms = &dwc->hwparams;
407
408 dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
409 dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
410
411 dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
412 dwc->num_in_eps, dwc->num_out_eps);
413}
414
415static void dwc3_cache_hwparams(struct dwc3 *dwc)
416{
417 struct dwc3_hwparams *parms = &dwc->hwparams;
418
419 parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
420 parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
421 parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
422 parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
423 parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
424 parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
425 parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
426 parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
427 parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
428}
429
Frank Wanga4a29122020-05-26 11:34:30 +0800430static void dwc3_hsphy_mode_setup(struct dwc3 *dwc)
431{
432 enum usb_phy_interface hsphy_mode = dwc->hsphy_mode;
433 u32 reg;
434
435 /* Set dwc3 usb2 phy config */
436 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
437
438 switch (hsphy_mode) {
439 case USBPHY_INTERFACE_MODE_UTMI:
440 reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
441 DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
442 reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) |
443 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT);
444 break;
445 case USBPHY_INTERFACE_MODE_UTMIW:
446 reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
447 DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
448 reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) |
449 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT);
450 break;
451 default:
452 break;
453 }
454
455 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
456}
457
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530458/**
459 * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
460 * @dwc: Pointer to our controller context structure
461 */
462static void dwc3_phy_setup(struct dwc3 *dwc)
463{
464 u32 reg;
465
466 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
467
468 /*
469 * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
470 * to '0' during coreConsultant configuration. So default value
471 * will be '0' when the core is reset. Application needs to set it
472 * to '1' after the core initialization is completed.
473 */
474 if (dwc->revision > DWC3_REVISION_194A)
475 reg |= DWC3_GUSB3PIPECTL_SUSPHY;
476
477 if (dwc->u2ss_inp3_quirk)
478 reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
479
480 if (dwc->req_p1p2p3_quirk)
481 reg |= DWC3_GUSB3PIPECTL_REQP1P2P3;
482
483 if (dwc->del_p1p2p3_quirk)
484 reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN;
485
486 if (dwc->del_phy_power_chg_quirk)
487 reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE;
488
489 if (dwc->lfps_filter_quirk)
490 reg |= DWC3_GUSB3PIPECTL_LFPSFILT;
491
492 if (dwc->rx_detect_poll_quirk)
493 reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL;
494
495 if (dwc->tx_de_emphasis_quirk)
496 reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
497
498 if (dwc->dis_u3_susphy_quirk)
499 reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
500
Jagan Tekic1157dc2020-05-06 13:20:25 +0530501 if (dwc->dis_del_phy_power_chg_quirk)
502 reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
503
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530504 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
505
Frank Wanga4a29122020-05-26 11:34:30 +0800506 dwc3_hsphy_mode_setup(dwc);
507
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530508 mdelay(100);
509
510 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
511
512 /*
513 * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
514 * '0' during coreConsultant configuration. So default value will
515 * be '0' when the core is reset. Application needs to set it to
516 * '1' after the core initialization is completed.
517 */
518 if (dwc->revision > DWC3_REVISION_194A)
519 reg |= DWC3_GUSB2PHYCFG_SUSPHY;
520
521 if (dwc->dis_u2_susphy_quirk)
522 reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
523
Frank Wang0c3b6f52020-05-26 11:33:46 +0800524 if (dwc->dis_enblslpm_quirk)
525 reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
526
Frank Wangb29bcd72020-05-26 11:33:47 +0800527 if (dwc->dis_u2_freeclk_exists_quirk)
528 reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS;
529
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530530 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
531
532 mdelay(100);
533}
534
Michael Walle668bdf62021-10-15 15:15:22 +0200535/* set global incr burst type configuration registers */
536static void dwc3_set_incr_burst_type(struct dwc3 *dwc)
537{
538 struct udevice *dev = dwc->dev;
539 u32 cfg;
540
541 if (!dwc->incrx_size)
542 return;
543
544 cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0);
545
546 /* Enable Undefined Length INCR Burst and Enable INCRx Burst */
547 cfg &= ~DWC3_GSBUSCFG0_INCRBRST_MASK;
548 if (dwc->incrx_mode)
549 cfg |= DWC3_GSBUSCFG0_INCRBRSTENA;
550 switch (dwc->incrx_size) {
551 case 256:
552 cfg |= DWC3_GSBUSCFG0_INCR256BRSTENA;
553 break;
554 case 128:
555 cfg |= DWC3_GSBUSCFG0_INCR128BRSTENA;
556 break;
557 case 64:
558 cfg |= DWC3_GSBUSCFG0_INCR64BRSTENA;
559 break;
560 case 32:
561 cfg |= DWC3_GSBUSCFG0_INCR32BRSTENA;
562 break;
563 case 16:
564 cfg |= DWC3_GSBUSCFG0_INCR16BRSTENA;
565 break;
566 case 8:
567 cfg |= DWC3_GSBUSCFG0_INCR8BRSTENA;
568 break;
569 case 4:
570 cfg |= DWC3_GSBUSCFG0_INCR4BRSTENA;
571 break;
572 case 1:
573 break;
574 default:
575 dev_err(dev, "Invalid property\n");
576 break;
577 }
578
579 dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg);
580}
581
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530582/**
583 * dwc3_core_init - Low-level initialization of DWC3 Core
584 * @dwc: Pointer to our controller context structure
585 *
586 * Returns 0 on success otherwise negative errno.
587 */
588static int dwc3_core_init(struct dwc3 *dwc)
589{
590 unsigned long timeout;
591 u32 hwparams4 = dwc->hwparams.hwparams4;
592 u32 reg;
593 int ret;
594
595 reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
596 /* This should read as U3 followed by revision number */
597 if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
598 dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
599 ret = -ENODEV;
600 goto err0;
601 }
602 dwc->revision = reg;
603
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530604 /* Handle USB2.0-only core configuration */
605 if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
606 DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
607 if (dwc->maximum_speed == USB_SPEED_SUPER)
608 dwc->maximum_speed = USB_SPEED_HIGH;
609 }
610
611 /* issue device SoftReset too */
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530612 timeout = 5000;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530613 dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530614 while (timeout--) {
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530615 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
616 if (!(reg & DWC3_DCTL_CSFTRST))
617 break;
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530618 };
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530619
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530620 if (!timeout) {
621 dev_err(dwc->dev, "Reset Timed Out\n");
622 ret = -ETIMEDOUT;
623 goto err0;
624 }
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530625
T Karthik Reddy7bb245a2019-05-01 10:14:49 +0530626 dwc3_phy_setup(dwc);
627
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530628 ret = dwc3_core_soft_reset(dwc);
629 if (ret)
630 goto err0;
631
632 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
633 reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
634
635 switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
636 case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
637 /**
638 * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
639 * issue which would cause xHCI compliance tests to fail.
640 *
641 * Because of that we cannot enable clock gating on such
642 * configurations.
643 *
644 * Refers to:
645 *
646 * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based
647 * SOF/ITP Mode Used
648 */
649 if ((dwc->dr_mode == USB_DR_MODE_HOST ||
650 dwc->dr_mode == USB_DR_MODE_OTG) &&
651 (dwc->revision >= DWC3_REVISION_210A &&
652 dwc->revision <= DWC3_REVISION_250A))
653 reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
654 else
655 reg &= ~DWC3_GCTL_DSBLCLKGTNG;
656 break;
657 case DWC3_GHWPARAMS1_EN_PWROPT_HIB:
658 /* enable hibernation here */
659 dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4);
660
661 /*
662 * REVISIT Enabling this bit so that host-mode hibernation
663 * will work. Device-mode hibernation is not yet implemented.
664 */
665 reg |= DWC3_GCTL_GBLHIBERNATIONEN;
666 break;
667 default:
668 dev_dbg(dwc->dev, "No power optimization available\n");
669 }
670
671 /* check if current dwc3 is on simulation board */
672 if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
673 dev_dbg(dwc->dev, "it is on FPGA board\n");
674 dwc->is_fpga = true;
675 }
676
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530677 if(dwc->disable_scramble_quirk && !dwc->is_fpga)
678 WARN(true,
679 "disable_scramble cannot be used on non-FPGA builds\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530680
681 if (dwc->disable_scramble_quirk && dwc->is_fpga)
682 reg |= DWC3_GCTL_DISSCRAMBLE;
683 else
684 reg &= ~DWC3_GCTL_DISSCRAMBLE;
685
686 if (dwc->u2exit_lfps_quirk)
687 reg |= DWC3_GCTL_U2EXIT_LFPS;
688
689 /*
690 * WORKAROUND: DWC3 revisions <1.90a have a bug
691 * where the device can fail to connect at SuperSpeed
692 * and falls back to high-speed mode which causes
693 * the device to enter a Connect/Disconnect loop
694 */
695 if (dwc->revision < DWC3_REVISION_190A)
696 reg |= DWC3_GCTL_U2RSTECN;
697
698 dwc3_core_num_eps(dwc);
699
700 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
701
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530702 ret = dwc3_alloc_scratch_buffers(dwc);
703 if (ret)
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530704 goto err0;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530705
706 ret = dwc3_setup_scratch_buffers(dwc);
707 if (ret)
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530708 goto err1;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530709
Michael Walle679f13c2021-10-15 15:15:21 +0200710 /* Adjust Frame Length */
711 dwc3_frame_length_adjustment(dwc, dwc->fladj);
712
Balaji Prakash J840d2192022-11-27 15:31:53 +0100713 /* Adjust Reference Clock Period */
714 dwc3_ref_clk_period(dwc);
715
Michael Walle668bdf62021-10-15 15:15:22 +0200716 dwc3_set_incr_burst_type(dwc);
717
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530718 return 0;
719
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530720err1:
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530721 dwc3_free_scratch_buffers(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530722
723err0:
724 return ret;
725}
726
727static void dwc3_core_exit(struct dwc3 *dwc)
728{
729 dwc3_free_scratch_buffers(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530730}
731
732static int dwc3_core_init_mode(struct dwc3 *dwc)
733{
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530734 int ret;
735
736 switch (dwc->dr_mode) {
737 case USB_DR_MODE_PERIPHERAL:
738 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
739 ret = dwc3_gadget_init(dwc);
740 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400741 dev_err(dwc->dev, "failed to initialize gadget\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530742 return ret;
743 }
744 break;
745 case USB_DR_MODE_HOST:
746 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
747 ret = dwc3_host_init(dwc);
748 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400749 dev_err(dwc->dev, "failed to initialize host\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530750 return ret;
751 }
752 break;
753 case USB_DR_MODE_OTG:
754 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
755 ret = dwc3_host_init(dwc);
756 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400757 dev_err(dwc->dev, "failed to initialize host\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530758 return ret;
759 }
760
761 ret = dwc3_gadget_init(dwc);
762 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400763 dev_err(dwc->dev, "failed to initialize gadget\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530764 return ret;
765 }
766 break;
767 default:
Sean Anderson2789ce82020-09-15 10:45:16 -0400768 dev_err(dwc->dev,
769 "Unsupported mode of operation %d\n", dwc->dr_mode);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530770 return -EINVAL;
771 }
772
773 return 0;
774}
775
Jean-Jacques Hiblot73a1b8b2019-09-11 11:33:45 +0200776static void dwc3_gadget_run(struct dwc3 *dwc)
777{
778 dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_RUN_STOP);
779 mdelay(100);
780}
781
Angus Ainslieeefabee2022-02-02 15:08:55 -0800782static void dwc3_core_stop(struct dwc3 *dwc)
783{
784 u32 reg;
785
786 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
787 dwc3_writel(dwc->regs, DWC3_DCTL, reg & ~(DWC3_DCTL_RUN_STOP));
788}
789
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530790static void dwc3_core_exit_mode(struct dwc3 *dwc)
791{
792 switch (dwc->dr_mode) {
793 case USB_DR_MODE_PERIPHERAL:
794 dwc3_gadget_exit(dwc);
795 break;
796 case USB_DR_MODE_HOST:
797 dwc3_host_exit(dwc);
798 break;
799 case USB_DR_MODE_OTG:
800 dwc3_host_exit(dwc);
801 dwc3_gadget_exit(dwc);
802 break;
803 default:
804 /* do nothing */
805 break;
806 }
Jean-Jacques Hiblot73a1b8b2019-09-11 11:33:45 +0200807
808 /*
809 * switch back to peripheral mode
810 * This enables the phy to enter idle and then, if enabled, suspend.
811 */
812 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
813 dwc3_gadget_run(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530814}
815
816#define DWC3_ALIGN_MASK (16 - 1)
817
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530818/**
819 * dwc3_uboot_init - dwc3 core uboot initialization code
820 * @dwc3_dev: struct dwc3_device containing initialization data
821 *
822 * Entry point for dwc3 driver (equivalent to dwc3_probe in linux
823 * kernel driver). Pointer to dwc3_device should be passed containing
824 * base address and other initialization data. Returns '0' on success and
825 * a negative value on failure.
826 *
827 * Generally called from board_usb_init() implemented in board file.
828 */
829int dwc3_uboot_init(struct dwc3_device *dwc3_dev)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530830{
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530831 struct dwc3 *dwc;
Felipe Balbi424305f2015-10-01 14:22:18 -0500832 struct device *dev = NULL;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530833 u8 lpm_nyet_threshold;
834 u8 tx_de_emphasis;
835 u8 hird_threshold;
836
837 int ret;
838
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530839 void *mem;
840
Mugunthan V N121f93c2018-05-18 13:10:27 +0200841 mem = devm_kzalloc((struct udevice *)dev,
842 sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530843 if (!mem)
844 return -ENOMEM;
845
846 dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
847 dwc->mem = mem;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530848
Michal Simek698cd6f2015-10-30 16:24:06 +0100849 dwc->regs = (void *)(uintptr_t)(dwc3_dev->base +
850 DWC3_GLOBALS_REGS_START);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530851
852 /* default to highest possible threshold */
853 lpm_nyet_threshold = 0xff;
854
855 /* default to -3.5dB de-emphasis */
856 tx_de_emphasis = 1;
857
858 /*
859 * default to assert utmi_sleep_n and use maximum allowed HIRD
860 * threshold value of 0b1100
861 */
862 hird_threshold = 12;
863
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530864 dwc->maximum_speed = dwc3_dev->maximum_speed;
865 dwc->has_lpm_erratum = dwc3_dev->has_lpm_erratum;
866 if (dwc3_dev->lpm_nyet_threshold)
867 lpm_nyet_threshold = dwc3_dev->lpm_nyet_threshold;
868 dwc->is_utmi_l1_suspend = dwc3_dev->is_utmi_l1_suspend;
869 if (dwc3_dev->hird_threshold)
870 hird_threshold = dwc3_dev->hird_threshold;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530871
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530872 dwc->needs_fifo_resize = dwc3_dev->tx_fifo_resize;
873 dwc->dr_mode = dwc3_dev->dr_mode;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530874
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530875 dwc->disable_scramble_quirk = dwc3_dev->disable_scramble_quirk;
876 dwc->u2exit_lfps_quirk = dwc3_dev->u2exit_lfps_quirk;
877 dwc->u2ss_inp3_quirk = dwc3_dev->u2ss_inp3_quirk;
878 dwc->req_p1p2p3_quirk = dwc3_dev->req_p1p2p3_quirk;
879 dwc->del_p1p2p3_quirk = dwc3_dev->del_p1p2p3_quirk;
880 dwc->del_phy_power_chg_quirk = dwc3_dev->del_phy_power_chg_quirk;
881 dwc->lfps_filter_quirk = dwc3_dev->lfps_filter_quirk;
882 dwc->rx_detect_poll_quirk = dwc3_dev->rx_detect_poll_quirk;
883 dwc->dis_u3_susphy_quirk = dwc3_dev->dis_u3_susphy_quirk;
884 dwc->dis_u2_susphy_quirk = dwc3_dev->dis_u2_susphy_quirk;
Jagan Tekic1157dc2020-05-06 13:20:25 +0530885 dwc->dis_del_phy_power_chg_quirk = dwc3_dev->dis_del_phy_power_chg_quirk;
Jagan Teki0ece2f72020-05-26 11:33:48 +0800886 dwc->dis_tx_ipgap_linecheck_quirk = dwc3_dev->dis_tx_ipgap_linecheck_quirk;
Frank Wang0c3b6f52020-05-26 11:33:46 +0800887 dwc->dis_enblslpm_quirk = dwc3_dev->dis_enblslpm_quirk;
Frank Wangb29bcd72020-05-26 11:33:47 +0800888 dwc->dis_u2_freeclk_exists_quirk = dwc3_dev->dis_u2_freeclk_exists_quirk;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530889
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530890 dwc->tx_de_emphasis_quirk = dwc3_dev->tx_de_emphasis_quirk;
891 if (dwc3_dev->tx_de_emphasis)
892 tx_de_emphasis = dwc3_dev->tx_de_emphasis;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530893
894 /* default to superspeed if no maximum_speed passed */
895 if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
896 dwc->maximum_speed = USB_SPEED_SUPER;
897
898 dwc->lpm_nyet_threshold = lpm_nyet_threshold;
899 dwc->tx_de_emphasis = tx_de_emphasis;
900
901 dwc->hird_threshold = hird_threshold
902 | (dwc->is_utmi_l1_suspend << 4);
903
Frank Wanga4a29122020-05-26 11:34:30 +0800904 dwc->hsphy_mode = dwc3_dev->hsphy_mode;
905
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530906 dwc->index = dwc3_dev->index;
907
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530908 dwc3_cache_hwparams(dwc);
909
910 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
911 if (ret) {
912 dev_err(dwc->dev, "failed to allocate event buffers\n");
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530913 return -ENOMEM;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530914 }
915
Jean-Jacques Hiblot731a2a32019-09-11 11:33:53 +0200916 if (!IS_ENABLED(CONFIG_USB_DWC3_GADGET))
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530917 dwc->dr_mode = USB_DR_MODE_HOST;
Jean-Jacques Hiblot731a2a32019-09-11 11:33:53 +0200918 else if (!IS_ENABLED(CONFIG_USB_HOST))
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530919 dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
920
921 if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
922 dwc->dr_mode = USB_DR_MODE_OTG;
923
924 ret = dwc3_core_init(dwc);
925 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400926 dev_err(dwc->dev, "failed to initialize core\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530927 goto err0;
928 }
929
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530930 ret = dwc3_event_buffers_setup(dwc);
931 if (ret) {
932 dev_err(dwc->dev, "failed to setup event buffers\n");
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530933 goto err1;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530934 }
935
936 ret = dwc3_core_init_mode(dwc);
937 if (ret)
938 goto err2;
939
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530940 list_add_tail(&dwc->list, &dwc3_list);
941
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530942 return 0;
943
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530944err2:
945 dwc3_event_buffers_cleanup(dwc);
946
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530947err1:
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530948 dwc3_core_exit(dwc);
949
950err0:
951 dwc3_free_event_buffers(dwc);
952
953 return ret;
954}
955
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530956/**
957 * dwc3_uboot_exit - dwc3 core uboot cleanup code
958 * @index: index of this controller
959 *
960 * Performs cleanup of memory allocated in dwc3_uboot_init and other misc
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530961 * cleanups (equivalent to dwc3_remove in linux). index of _this_ controller
962 * should be passed and should match with the index passed in
963 * dwc3_device during init.
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530964 *
965 * Generally called from board file.
966 */
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530967void dwc3_uboot_exit(int index)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530968{
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530969 struct dwc3 *dwc;
970
971 list_for_each_entry(dwc, &dwc3_list, list) {
972 if (dwc->index != index)
973 continue;
974
975 dwc3_core_exit_mode(dwc);
976 dwc3_event_buffers_cleanup(dwc);
977 dwc3_free_event_buffers(dwc);
978 dwc3_core_exit(dwc);
979 list_del(&dwc->list);
980 kfree(dwc->mem);
981 break;
982 }
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530983}
984
Marek Vasut26ec65b2024-03-17 05:42:52 +0100985MODULE_ALIAS("platform:dwc3");
986MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
987MODULE_LICENSE("GPL v2");
988MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
989
Marek Vasute7f13152024-03-17 05:42:53 +0100990#if !CONFIG_IS_ENABLED(DM_USB_GADGET)
991__weak int dwc3_uboot_interrupt_status(struct udevice *dev)
992{
993 return 1;
994}
995
Kishon Vijay Abraham I1cee7b12015-02-23 18:40:06 +0530996/**
Marek Vasute7f13152024-03-17 05:42:53 +0100997 * dm_usb_gadget_handle_interrupts - handle dwc3 core interrupt
Marek Vasut283bbec2023-09-01 11:50:03 +0200998 * @dev: device of this controller
Kishon Vijay Abraham I1cee7b12015-02-23 18:40:06 +0530999 *
1000 * Invokes dwc3 gadget interrupts.
1001 *
1002 * Generally called from board file.
1003 */
Marek Vasute7f13152024-03-17 05:42:53 +01001004int dm_usb_gadget_handle_interrupts(struct udevice *dev)
Kishon Vijay Abraham I1cee7b12015-02-23 18:40:06 +05301005{
1006 struct dwc3 *dwc = NULL;
1007
Marek Vasute7f13152024-03-17 05:42:53 +01001008 if (!dwc3_uboot_interrupt_status(dev))
1009 return 0;
1010
Kishon Vijay Abraham I1cee7b12015-02-23 18:40:06 +05301011 list_for_each_entry(dwc, &dwc3_list, list) {
Marek Vasut283bbec2023-09-01 11:50:03 +02001012 if (dwc->dev != dev)
Kishon Vijay Abraham I1cee7b12015-02-23 18:40:06 +05301013 continue;
1014
1015 dwc3_gadget_uboot_handle_interrupt(dwc);
1016 break;
1017 }
Marek Vasut26ec65b2024-03-17 05:42:52 +01001018
1019 return 0;
1020}
1021#endif
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001022
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001023#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB)
developerf8bced12020-05-02 11:35:13 +02001024int dwc3_setup_phy(struct udevice *dev, struct phy_bulk *phys)
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001025{
developerf8bced12020-05-02 11:35:13 +02001026 int ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001027
developerf8bced12020-05-02 11:35:13 +02001028 ret = generic_phy_get_bulk(dev, phys);
1029 if (ret)
1030 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001031
developerf8bced12020-05-02 11:35:13 +02001032 ret = generic_phy_init_bulk(phys);
1033 if (ret)
1034 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001035
developerf8bced12020-05-02 11:35:13 +02001036 ret = generic_phy_power_on_bulk(phys);
1037 if (ret)
1038 generic_phy_exit_bulk(phys);
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001039
1040 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001041}
1042
developerf8bced12020-05-02 11:35:13 +02001043int dwc3_shutdown_phy(struct udevice *dev, struct phy_bulk *phys)
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001044{
developerf8bced12020-05-02 11:35:13 +02001045 int ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001046
developerf8bced12020-05-02 11:35:13 +02001047 ret = generic_phy_power_off_bulk(phys);
1048 ret |= generic_phy_exit_bulk(phys);
1049 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001050}
1051#endif
1052
Jean-Jacques Hiblot175cd7c2019-09-11 11:33:50 +02001053#if CONFIG_IS_ENABLED(DM_USB)
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001054void dwc3_of_parse(struct dwc3 *dwc)
1055{
1056 const u8 *tmp;
1057 struct udevice *dev = dwc->dev;
1058 u8 lpm_nyet_threshold;
1059 u8 tx_de_emphasis;
1060 u8 hird_threshold;
Michael Walle668bdf62021-10-15 15:15:22 +02001061 u32 val;
1062 int i;
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001063
1064 /* default to highest possible threshold */
1065 lpm_nyet_threshold = 0xff;
1066
1067 /* default to -3.5dB de-emphasis */
1068 tx_de_emphasis = 1;
1069
1070 /*
1071 * default to assert utmi_sleep_n and use maximum allowed HIRD
1072 * threshold value of 0b1100
1073 */
1074 hird_threshold = 12;
1075
Simon Glassa7ece582020-12-19 10:40:14 -07001076 dwc->hsphy_mode = usb_get_phy_mode(dev_ofnode(dev));
Frank Wanga4a29122020-05-26 11:34:30 +08001077
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001078 dwc->has_lpm_erratum = dev_read_bool(dev,
1079 "snps,has-lpm-erratum");
1080 tmp = dev_read_u8_array_ptr(dev, "snps,lpm-nyet-threshold", 1);
1081 if (tmp)
1082 lpm_nyet_threshold = *tmp;
1083
1084 dwc->is_utmi_l1_suspend = dev_read_bool(dev,
1085 "snps,is-utmi-l1-suspend");
1086 tmp = dev_read_u8_array_ptr(dev, "snps,hird-threshold", 1);
1087 if (tmp)
1088 hird_threshold = *tmp;
1089
1090 dwc->disable_scramble_quirk = dev_read_bool(dev,
1091 "snps,disable_scramble_quirk");
1092 dwc->u2exit_lfps_quirk = dev_read_bool(dev,
1093 "snps,u2exit_lfps_quirk");
1094 dwc->u2ss_inp3_quirk = dev_read_bool(dev,
1095 "snps,u2ss_inp3_quirk");
1096 dwc->req_p1p2p3_quirk = dev_read_bool(dev,
1097 "snps,req_p1p2p3_quirk");
1098 dwc->del_p1p2p3_quirk = dev_read_bool(dev,
1099 "snps,del_p1p2p3_quirk");
1100 dwc->del_phy_power_chg_quirk = dev_read_bool(dev,
1101 "snps,del_phy_power_chg_quirk");
1102 dwc->lfps_filter_quirk = dev_read_bool(dev,
1103 "snps,lfps_filter_quirk");
1104 dwc->rx_detect_poll_quirk = dev_read_bool(dev,
1105 "snps,rx_detect_poll_quirk");
1106 dwc->dis_u3_susphy_quirk = dev_read_bool(dev,
1107 "snps,dis_u3_susphy_quirk");
1108 dwc->dis_u2_susphy_quirk = dev_read_bool(dev,
1109 "snps,dis_u2_susphy_quirk");
Jagan Tekic1157dc2020-05-06 13:20:25 +05301110 dwc->dis_del_phy_power_chg_quirk = dev_read_bool(dev,
1111 "snps,dis-del-phy-power-chg-quirk");
Jagan Teki0ece2f72020-05-26 11:33:48 +08001112 dwc->dis_tx_ipgap_linecheck_quirk = dev_read_bool(dev,
1113 "snps,dis-tx-ipgap-linecheck-quirk");
Frank Wang0c3b6f52020-05-26 11:33:46 +08001114 dwc->dis_enblslpm_quirk = dev_read_bool(dev,
1115 "snps,dis_enblslpm_quirk");
Frank Wangb29bcd72020-05-26 11:33:47 +08001116 dwc->dis_u2_freeclk_exists_quirk = dev_read_bool(dev,
1117 "snps,dis-u2-freeclk-exists-quirk");
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001118 dwc->tx_de_emphasis_quirk = dev_read_bool(dev,
1119 "snps,tx_de_emphasis_quirk");
1120 tmp = dev_read_u8_array_ptr(dev, "snps,tx_de_emphasis", 1);
1121 if (tmp)
1122 tx_de_emphasis = *tmp;
1123
1124 dwc->lpm_nyet_threshold = lpm_nyet_threshold;
1125 dwc->tx_de_emphasis = tx_de_emphasis;
1126
1127 dwc->hird_threshold = hird_threshold
1128 | (dwc->is_utmi_l1_suspend << 4);
Michael Walle679f13c2021-10-15 15:15:21 +02001129
1130 dev_read_u32(dev, "snps,quirk-frame-length-adjustment", &dwc->fladj);
Michael Walle668bdf62021-10-15 15:15:22 +02001131
1132 /*
1133 * Handle property "snps,incr-burst-type-adjustment".
1134 * Get the number of value from this property:
1135 * result <= 0, means this property is not supported.
1136 * result = 1, means INCRx burst mode supported.
1137 * result > 1, means undefined length burst mode supported.
1138 */
1139 dwc->incrx_mode = INCRX_BURST_MODE;
1140 dwc->incrx_size = 0;
1141 for (i = 0; i < 8; i++) {
1142 if (dev_read_u32_index(dev, "snps,incr-burst-type-adjustment",
1143 i, &val))
1144 break;
1145
1146 dwc->incrx_mode = INCRX_UNDEF_LENGTH_BURST_MODE;
1147 dwc->incrx_size = max(dwc->incrx_size, val);
1148 }
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001149}
1150
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001151int dwc3_init(struct dwc3 *dwc)
1152{
1153 int ret;
Jagan Teki0ece2f72020-05-26 11:33:48 +08001154 u32 reg;
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001155
1156 dwc3_cache_hwparams(dwc);
1157
1158 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
1159 if (ret) {
1160 dev_err(dwc->dev, "failed to allocate event buffers\n");
1161 return -ENOMEM;
1162 }
1163
1164 ret = dwc3_core_init(dwc);
1165 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -04001166 dev_err(dwc->dev, "failed to initialize core\n");
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001167 goto core_fail;
1168 }
1169
1170 ret = dwc3_event_buffers_setup(dwc);
1171 if (ret) {
1172 dev_err(dwc->dev, "failed to setup event buffers\n");
1173 goto event_fail;
1174 }
1175
Jagan Teki0ece2f72020-05-26 11:33:48 +08001176 if (dwc->revision >= DWC3_REVISION_250A) {
1177 reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
1178
1179 /*
1180 * Enable hardware control of sending remote wakeup
1181 * in HS when the device is in the L1 state.
1182 */
1183 if (dwc->revision >= DWC3_REVISION_290A)
1184 reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
1185
1186 if (dwc->dis_tx_ipgap_linecheck_quirk)
1187 reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
1188
1189 dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
1190 }
1191
Jagan Teki461409b2020-05-26 11:34:29 +08001192 if (dwc->dr_mode == USB_DR_MODE_HOST ||
1193 dwc->dr_mode == USB_DR_MODE_OTG) {
1194 reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
1195
1196 reg |= DWC3_GUCTL_HSTINAUTORETRY;
1197
1198 dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
1199 }
1200
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001201 ret = dwc3_core_init_mode(dwc);
1202 if (ret)
1203 goto mode_fail;
1204
1205 return 0;
1206
1207mode_fail:
1208 dwc3_event_buffers_cleanup(dwc);
1209
1210event_fail:
1211 dwc3_core_exit(dwc);
1212
1213core_fail:
1214 dwc3_free_event_buffers(dwc);
1215
1216 return ret;
1217}
1218
1219void dwc3_remove(struct dwc3 *dwc)
1220{
1221 dwc3_core_exit_mode(dwc);
1222 dwc3_event_buffers_cleanup(dwc);
1223 dwc3_free_event_buffers(dwc);
Angus Ainslieeefabee2022-02-02 15:08:55 -08001224 dwc3_core_stop(dwc);
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001225 dwc3_core_exit(dwc);
1226 kfree(dwc->mem);
1227}
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001228#endif