blob: a35b8c2f646134f042fff2c2537517880b50eed7 [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 */
Caleb Connollydcd0ab92024-04-23 16:15:06 +0200597 if ((reg & DWC3_GSNPSID_MASK) != 0x55330000 &&
598 (reg & DWC3_GSNPSID_MASK) != 0x33310000) {
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530599 dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
600 ret = -ENODEV;
601 goto err0;
602 }
603 dwc->revision = reg;
604
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530605 /* Handle USB2.0-only core configuration */
606 if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
607 DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
608 if (dwc->maximum_speed == USB_SPEED_SUPER)
609 dwc->maximum_speed = USB_SPEED_HIGH;
610 }
611
612 /* issue device SoftReset too */
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530613 timeout = 5000;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530614 dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530615 while (timeout--) {
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530616 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
617 if (!(reg & DWC3_DCTL_CSFTRST))
618 break;
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530619 };
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530620
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530621 if (!timeout) {
622 dev_err(dwc->dev, "Reset Timed Out\n");
623 ret = -ETIMEDOUT;
624 goto err0;
625 }
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530626
T Karthik Reddy7bb245a2019-05-01 10:14:49 +0530627 dwc3_phy_setup(dwc);
628
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530629 ret = dwc3_core_soft_reset(dwc);
630 if (ret)
631 goto err0;
632
633 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
634 reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
635
636 switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
637 case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
638 /**
639 * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
640 * issue which would cause xHCI compliance tests to fail.
641 *
642 * Because of that we cannot enable clock gating on such
643 * configurations.
644 *
645 * Refers to:
646 *
647 * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based
648 * SOF/ITP Mode Used
649 */
650 if ((dwc->dr_mode == USB_DR_MODE_HOST ||
651 dwc->dr_mode == USB_DR_MODE_OTG) &&
652 (dwc->revision >= DWC3_REVISION_210A &&
653 dwc->revision <= DWC3_REVISION_250A))
654 reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
655 else
656 reg &= ~DWC3_GCTL_DSBLCLKGTNG;
657 break;
658 case DWC3_GHWPARAMS1_EN_PWROPT_HIB:
659 /* enable hibernation here */
660 dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4);
661
662 /*
663 * REVISIT Enabling this bit so that host-mode hibernation
664 * will work. Device-mode hibernation is not yet implemented.
665 */
666 reg |= DWC3_GCTL_GBLHIBERNATIONEN;
667 break;
668 default:
669 dev_dbg(dwc->dev, "No power optimization available\n");
670 }
671
672 /* check if current dwc3 is on simulation board */
673 if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
674 dev_dbg(dwc->dev, "it is on FPGA board\n");
675 dwc->is_fpga = true;
676 }
677
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530678 if(dwc->disable_scramble_quirk && !dwc->is_fpga)
679 WARN(true,
680 "disable_scramble cannot be used on non-FPGA builds\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530681
682 if (dwc->disable_scramble_quirk && dwc->is_fpga)
683 reg |= DWC3_GCTL_DISSCRAMBLE;
684 else
685 reg &= ~DWC3_GCTL_DISSCRAMBLE;
686
687 if (dwc->u2exit_lfps_quirk)
688 reg |= DWC3_GCTL_U2EXIT_LFPS;
689
690 /*
691 * WORKAROUND: DWC3 revisions <1.90a have a bug
692 * where the device can fail to connect at SuperSpeed
693 * and falls back to high-speed mode which causes
694 * the device to enter a Connect/Disconnect loop
695 */
696 if (dwc->revision < DWC3_REVISION_190A)
697 reg |= DWC3_GCTL_U2RSTECN;
698
699 dwc3_core_num_eps(dwc);
700
701 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
702
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530703 ret = dwc3_alloc_scratch_buffers(dwc);
704 if (ret)
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530705 goto err0;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530706
707 ret = dwc3_setup_scratch_buffers(dwc);
708 if (ret)
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530709 goto err1;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530710
Michael Walle679f13c2021-10-15 15:15:21 +0200711 /* Adjust Frame Length */
712 dwc3_frame_length_adjustment(dwc, dwc->fladj);
713
Balaji Prakash J840d2192022-11-27 15:31:53 +0100714 /* Adjust Reference Clock Period */
715 dwc3_ref_clk_period(dwc);
716
Michael Walle668bdf62021-10-15 15:15:22 +0200717 dwc3_set_incr_burst_type(dwc);
718
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530719 return 0;
720
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530721err1:
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530722 dwc3_free_scratch_buffers(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530723
724err0:
725 return ret;
726}
727
728static void dwc3_core_exit(struct dwc3 *dwc)
729{
730 dwc3_free_scratch_buffers(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530731}
732
733static int dwc3_core_init_mode(struct dwc3 *dwc)
734{
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530735 int ret;
736
737 switch (dwc->dr_mode) {
738 case USB_DR_MODE_PERIPHERAL:
739 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
740 ret = dwc3_gadget_init(dwc);
741 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400742 dev_err(dwc->dev, "failed to initialize gadget\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530743 return ret;
744 }
745 break;
746 case USB_DR_MODE_HOST:
747 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
748 ret = dwc3_host_init(dwc);
749 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400750 dev_err(dwc->dev, "failed to initialize host\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530751 return ret;
752 }
753 break;
754 case USB_DR_MODE_OTG:
755 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
756 ret = dwc3_host_init(dwc);
757 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400758 dev_err(dwc->dev, "failed to initialize host\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530759 return ret;
760 }
761
762 ret = dwc3_gadget_init(dwc);
763 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400764 dev_err(dwc->dev, "failed to initialize gadget\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530765 return ret;
766 }
767 break;
768 default:
Sean Anderson2789ce82020-09-15 10:45:16 -0400769 dev_err(dwc->dev,
770 "Unsupported mode of operation %d\n", dwc->dr_mode);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530771 return -EINVAL;
772 }
773
774 return 0;
775}
776
Jean-Jacques Hiblot73a1b8b2019-09-11 11:33:45 +0200777static void dwc3_gadget_run(struct dwc3 *dwc)
778{
779 dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_RUN_STOP);
780 mdelay(100);
781}
782
Angus Ainslieeefabee2022-02-02 15:08:55 -0800783static void dwc3_core_stop(struct dwc3 *dwc)
784{
785 u32 reg;
786
787 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
788 dwc3_writel(dwc->regs, DWC3_DCTL, reg & ~(DWC3_DCTL_RUN_STOP));
789}
790
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530791static void dwc3_core_exit_mode(struct dwc3 *dwc)
792{
793 switch (dwc->dr_mode) {
794 case USB_DR_MODE_PERIPHERAL:
795 dwc3_gadget_exit(dwc);
796 break;
797 case USB_DR_MODE_HOST:
798 dwc3_host_exit(dwc);
799 break;
800 case USB_DR_MODE_OTG:
801 dwc3_host_exit(dwc);
802 dwc3_gadget_exit(dwc);
803 break;
804 default:
805 /* do nothing */
806 break;
807 }
Jean-Jacques Hiblot73a1b8b2019-09-11 11:33:45 +0200808
809 /*
810 * switch back to peripheral mode
811 * This enables the phy to enter idle and then, if enabled, suspend.
812 */
813 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
814 dwc3_gadget_run(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530815}
816
817#define DWC3_ALIGN_MASK (16 - 1)
818
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530819/**
820 * dwc3_uboot_init - dwc3 core uboot initialization code
821 * @dwc3_dev: struct dwc3_device containing initialization data
822 *
823 * Entry point for dwc3 driver (equivalent to dwc3_probe in linux
824 * kernel driver). Pointer to dwc3_device should be passed containing
825 * base address and other initialization data. Returns '0' on success and
826 * a negative value on failure.
827 *
828 * Generally called from board_usb_init() implemented in board file.
829 */
830int dwc3_uboot_init(struct dwc3_device *dwc3_dev)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530831{
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530832 struct dwc3 *dwc;
Felipe Balbi424305f2015-10-01 14:22:18 -0500833 struct device *dev = NULL;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530834 u8 lpm_nyet_threshold;
835 u8 tx_de_emphasis;
836 u8 hird_threshold;
837
838 int ret;
839
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530840 void *mem;
841
Mugunthan V N121f93c2018-05-18 13:10:27 +0200842 mem = devm_kzalloc((struct udevice *)dev,
843 sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530844 if (!mem)
845 return -ENOMEM;
846
847 dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
848 dwc->mem = mem;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530849
Michal Simek698cd6f2015-10-30 16:24:06 +0100850 dwc->regs = (void *)(uintptr_t)(dwc3_dev->base +
851 DWC3_GLOBALS_REGS_START);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530852
853 /* default to highest possible threshold */
854 lpm_nyet_threshold = 0xff;
855
856 /* default to -3.5dB de-emphasis */
857 tx_de_emphasis = 1;
858
859 /*
860 * default to assert utmi_sleep_n and use maximum allowed HIRD
861 * threshold value of 0b1100
862 */
863 hird_threshold = 12;
864
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530865 dwc->maximum_speed = dwc3_dev->maximum_speed;
866 dwc->has_lpm_erratum = dwc3_dev->has_lpm_erratum;
867 if (dwc3_dev->lpm_nyet_threshold)
868 lpm_nyet_threshold = dwc3_dev->lpm_nyet_threshold;
869 dwc->is_utmi_l1_suspend = dwc3_dev->is_utmi_l1_suspend;
870 if (dwc3_dev->hird_threshold)
871 hird_threshold = dwc3_dev->hird_threshold;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530872
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530873 dwc->needs_fifo_resize = dwc3_dev->tx_fifo_resize;
874 dwc->dr_mode = dwc3_dev->dr_mode;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530875
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530876 dwc->disable_scramble_quirk = dwc3_dev->disable_scramble_quirk;
877 dwc->u2exit_lfps_quirk = dwc3_dev->u2exit_lfps_quirk;
878 dwc->u2ss_inp3_quirk = dwc3_dev->u2ss_inp3_quirk;
879 dwc->req_p1p2p3_quirk = dwc3_dev->req_p1p2p3_quirk;
880 dwc->del_p1p2p3_quirk = dwc3_dev->del_p1p2p3_quirk;
881 dwc->del_phy_power_chg_quirk = dwc3_dev->del_phy_power_chg_quirk;
882 dwc->lfps_filter_quirk = dwc3_dev->lfps_filter_quirk;
883 dwc->rx_detect_poll_quirk = dwc3_dev->rx_detect_poll_quirk;
884 dwc->dis_u3_susphy_quirk = dwc3_dev->dis_u3_susphy_quirk;
885 dwc->dis_u2_susphy_quirk = dwc3_dev->dis_u2_susphy_quirk;
Jagan Tekic1157dc2020-05-06 13:20:25 +0530886 dwc->dis_del_phy_power_chg_quirk = dwc3_dev->dis_del_phy_power_chg_quirk;
Jagan Teki0ece2f72020-05-26 11:33:48 +0800887 dwc->dis_tx_ipgap_linecheck_quirk = dwc3_dev->dis_tx_ipgap_linecheck_quirk;
Frank Wang0c3b6f52020-05-26 11:33:46 +0800888 dwc->dis_enblslpm_quirk = dwc3_dev->dis_enblslpm_quirk;
Frank Wangb29bcd72020-05-26 11:33:47 +0800889 dwc->dis_u2_freeclk_exists_quirk = dwc3_dev->dis_u2_freeclk_exists_quirk;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530890
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530891 dwc->tx_de_emphasis_quirk = dwc3_dev->tx_de_emphasis_quirk;
892 if (dwc3_dev->tx_de_emphasis)
893 tx_de_emphasis = dwc3_dev->tx_de_emphasis;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530894
895 /* default to superspeed if no maximum_speed passed */
896 if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
897 dwc->maximum_speed = USB_SPEED_SUPER;
898
899 dwc->lpm_nyet_threshold = lpm_nyet_threshold;
900 dwc->tx_de_emphasis = tx_de_emphasis;
901
902 dwc->hird_threshold = hird_threshold
903 | (dwc->is_utmi_l1_suspend << 4);
904
Frank Wanga4a29122020-05-26 11:34:30 +0800905 dwc->hsphy_mode = dwc3_dev->hsphy_mode;
906
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530907 dwc->index = dwc3_dev->index;
908
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530909 dwc3_cache_hwparams(dwc);
910
911 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
912 if (ret) {
913 dev_err(dwc->dev, "failed to allocate event buffers\n");
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530914 return -ENOMEM;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530915 }
916
Jean-Jacques Hiblot731a2a32019-09-11 11:33:53 +0200917 if (!IS_ENABLED(CONFIG_USB_DWC3_GADGET))
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530918 dwc->dr_mode = USB_DR_MODE_HOST;
Jean-Jacques Hiblot731a2a32019-09-11 11:33:53 +0200919 else if (!IS_ENABLED(CONFIG_USB_HOST))
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530920 dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
921
922 if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
923 dwc->dr_mode = USB_DR_MODE_OTG;
924
925 ret = dwc3_core_init(dwc);
926 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400927 dev_err(dwc->dev, "failed to initialize core\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530928 goto err0;
929 }
930
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530931 ret = dwc3_event_buffers_setup(dwc);
932 if (ret) {
933 dev_err(dwc->dev, "failed to setup event buffers\n");
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530934 goto err1;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530935 }
936
937 ret = dwc3_core_init_mode(dwc);
938 if (ret)
939 goto err2;
940
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530941 list_add_tail(&dwc->list, &dwc3_list);
942
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530943 return 0;
944
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530945err2:
946 dwc3_event_buffers_cleanup(dwc);
947
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530948err1:
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530949 dwc3_core_exit(dwc);
950
951err0:
952 dwc3_free_event_buffers(dwc);
953
954 return ret;
955}
956
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530957/**
958 * dwc3_uboot_exit - dwc3 core uboot cleanup code
959 * @index: index of this controller
960 *
961 * Performs cleanup of memory allocated in dwc3_uboot_init and other misc
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530962 * cleanups (equivalent to dwc3_remove in linux). index of _this_ controller
963 * should be passed and should match with the index passed in
964 * dwc3_device during init.
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530965 *
966 * Generally called from board file.
967 */
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530968void dwc3_uboot_exit(int index)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530969{
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530970 struct dwc3 *dwc;
971
972 list_for_each_entry(dwc, &dwc3_list, list) {
973 if (dwc->index != index)
974 continue;
975
976 dwc3_core_exit_mode(dwc);
977 dwc3_event_buffers_cleanup(dwc);
978 dwc3_free_event_buffers(dwc);
979 dwc3_core_exit(dwc);
980 list_del(&dwc->list);
981 kfree(dwc->mem);
982 break;
983 }
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530984}
985
Marek Vasut26ec65b2024-03-17 05:42:52 +0100986MODULE_ALIAS("platform:dwc3");
987MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
988MODULE_LICENSE("GPL v2");
989MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
990
Marek Vasute7f13152024-03-17 05:42:53 +0100991#if !CONFIG_IS_ENABLED(DM_USB_GADGET)
992__weak int dwc3_uboot_interrupt_status(struct udevice *dev)
993{
994 return 1;
995}
996
Kishon Vijay Abraham I1cee7b12015-02-23 18:40:06 +0530997/**
Marek Vasute7f13152024-03-17 05:42:53 +0100998 * dm_usb_gadget_handle_interrupts - handle dwc3 core interrupt
Marek Vasut283bbec2023-09-01 11:50:03 +0200999 * @dev: device of this controller
Kishon Vijay Abraham I1cee7b12015-02-23 18:40:06 +05301000 *
1001 * Invokes dwc3 gadget interrupts.
1002 *
1003 * Generally called from board file.
1004 */
Marek Vasute7f13152024-03-17 05:42:53 +01001005int dm_usb_gadget_handle_interrupts(struct udevice *dev)
Kishon Vijay Abraham I1cee7b12015-02-23 18:40:06 +05301006{
1007 struct dwc3 *dwc = NULL;
1008
Marek Vasute7f13152024-03-17 05:42:53 +01001009 if (!dwc3_uboot_interrupt_status(dev))
1010 return 0;
1011
Kishon Vijay Abraham I1cee7b12015-02-23 18:40:06 +05301012 list_for_each_entry(dwc, &dwc3_list, list) {
Marek Vasut283bbec2023-09-01 11:50:03 +02001013 if (dwc->dev != dev)
Kishon Vijay Abraham I1cee7b12015-02-23 18:40:06 +05301014 continue;
1015
1016 dwc3_gadget_uboot_handle_interrupt(dwc);
1017 break;
1018 }
Marek Vasut26ec65b2024-03-17 05:42:52 +01001019
1020 return 0;
1021}
1022#endif
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001023
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001024#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB)
developerf8bced12020-05-02 11:35:13 +02001025int dwc3_setup_phy(struct udevice *dev, struct phy_bulk *phys)
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001026{
developerf8bced12020-05-02 11:35:13 +02001027 int ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001028
developerf8bced12020-05-02 11:35:13 +02001029 ret = generic_phy_get_bulk(dev, phys);
1030 if (ret)
1031 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001032
developerf8bced12020-05-02 11:35:13 +02001033 ret = generic_phy_init_bulk(phys);
1034 if (ret)
1035 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001036
developerf8bced12020-05-02 11:35:13 +02001037 ret = generic_phy_power_on_bulk(phys);
1038 if (ret)
1039 generic_phy_exit_bulk(phys);
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001040
1041 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001042}
1043
developerf8bced12020-05-02 11:35:13 +02001044int dwc3_shutdown_phy(struct udevice *dev, struct phy_bulk *phys)
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001045{
developerf8bced12020-05-02 11:35:13 +02001046 int ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001047
developerf8bced12020-05-02 11:35:13 +02001048 ret = generic_phy_power_off_bulk(phys);
1049 ret |= generic_phy_exit_bulk(phys);
1050 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001051}
1052#endif
1053
Jean-Jacques Hiblot175cd7c2019-09-11 11:33:50 +02001054#if CONFIG_IS_ENABLED(DM_USB)
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001055void dwc3_of_parse(struct dwc3 *dwc)
1056{
1057 const u8 *tmp;
1058 struct udevice *dev = dwc->dev;
1059 u8 lpm_nyet_threshold;
1060 u8 tx_de_emphasis;
1061 u8 hird_threshold;
Michael Walle668bdf62021-10-15 15:15:22 +02001062 u32 val;
1063 int i;
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001064
1065 /* default to highest possible threshold */
1066 lpm_nyet_threshold = 0xff;
1067
1068 /* default to -3.5dB de-emphasis */
1069 tx_de_emphasis = 1;
1070
1071 /*
1072 * default to assert utmi_sleep_n and use maximum allowed HIRD
1073 * threshold value of 0b1100
1074 */
1075 hird_threshold = 12;
1076
Simon Glassa7ece582020-12-19 10:40:14 -07001077 dwc->hsphy_mode = usb_get_phy_mode(dev_ofnode(dev));
Frank Wanga4a29122020-05-26 11:34:30 +08001078
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001079 dwc->has_lpm_erratum = dev_read_bool(dev,
1080 "snps,has-lpm-erratum");
1081 tmp = dev_read_u8_array_ptr(dev, "snps,lpm-nyet-threshold", 1);
1082 if (tmp)
1083 lpm_nyet_threshold = *tmp;
1084
1085 dwc->is_utmi_l1_suspend = dev_read_bool(dev,
1086 "snps,is-utmi-l1-suspend");
1087 tmp = dev_read_u8_array_ptr(dev, "snps,hird-threshold", 1);
1088 if (tmp)
1089 hird_threshold = *tmp;
1090
1091 dwc->disable_scramble_quirk = dev_read_bool(dev,
1092 "snps,disable_scramble_quirk");
1093 dwc->u2exit_lfps_quirk = dev_read_bool(dev,
1094 "snps,u2exit_lfps_quirk");
1095 dwc->u2ss_inp3_quirk = dev_read_bool(dev,
1096 "snps,u2ss_inp3_quirk");
1097 dwc->req_p1p2p3_quirk = dev_read_bool(dev,
1098 "snps,req_p1p2p3_quirk");
1099 dwc->del_p1p2p3_quirk = dev_read_bool(dev,
1100 "snps,del_p1p2p3_quirk");
1101 dwc->del_phy_power_chg_quirk = dev_read_bool(dev,
1102 "snps,del_phy_power_chg_quirk");
1103 dwc->lfps_filter_quirk = dev_read_bool(dev,
1104 "snps,lfps_filter_quirk");
1105 dwc->rx_detect_poll_quirk = dev_read_bool(dev,
1106 "snps,rx_detect_poll_quirk");
1107 dwc->dis_u3_susphy_quirk = dev_read_bool(dev,
1108 "snps,dis_u3_susphy_quirk");
1109 dwc->dis_u2_susphy_quirk = dev_read_bool(dev,
1110 "snps,dis_u2_susphy_quirk");
Jagan Tekic1157dc2020-05-06 13:20:25 +05301111 dwc->dis_del_phy_power_chg_quirk = dev_read_bool(dev,
1112 "snps,dis-del-phy-power-chg-quirk");
Jagan Teki0ece2f72020-05-26 11:33:48 +08001113 dwc->dis_tx_ipgap_linecheck_quirk = dev_read_bool(dev,
1114 "snps,dis-tx-ipgap-linecheck-quirk");
Frank Wang0c3b6f52020-05-26 11:33:46 +08001115 dwc->dis_enblslpm_quirk = dev_read_bool(dev,
1116 "snps,dis_enblslpm_quirk");
Frank Wangb29bcd72020-05-26 11:33:47 +08001117 dwc->dis_u2_freeclk_exists_quirk = dev_read_bool(dev,
1118 "snps,dis-u2-freeclk-exists-quirk");
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001119 dwc->tx_de_emphasis_quirk = dev_read_bool(dev,
1120 "snps,tx_de_emphasis_quirk");
1121 tmp = dev_read_u8_array_ptr(dev, "snps,tx_de_emphasis", 1);
1122 if (tmp)
1123 tx_de_emphasis = *tmp;
1124
1125 dwc->lpm_nyet_threshold = lpm_nyet_threshold;
1126 dwc->tx_de_emphasis = tx_de_emphasis;
1127
1128 dwc->hird_threshold = hird_threshold
1129 | (dwc->is_utmi_l1_suspend << 4);
Michael Walle679f13c2021-10-15 15:15:21 +02001130
1131 dev_read_u32(dev, "snps,quirk-frame-length-adjustment", &dwc->fladj);
Michael Walle668bdf62021-10-15 15:15:22 +02001132
1133 /*
1134 * Handle property "snps,incr-burst-type-adjustment".
1135 * Get the number of value from this property:
1136 * result <= 0, means this property is not supported.
1137 * result = 1, means INCRx burst mode supported.
1138 * result > 1, means undefined length burst mode supported.
1139 */
1140 dwc->incrx_mode = INCRX_BURST_MODE;
1141 dwc->incrx_size = 0;
1142 for (i = 0; i < 8; i++) {
1143 if (dev_read_u32_index(dev, "snps,incr-burst-type-adjustment",
1144 i, &val))
1145 break;
1146
1147 dwc->incrx_mode = INCRX_UNDEF_LENGTH_BURST_MODE;
1148 dwc->incrx_size = max(dwc->incrx_size, val);
1149 }
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001150}
1151
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001152int dwc3_init(struct dwc3 *dwc)
1153{
1154 int ret;
Jagan Teki0ece2f72020-05-26 11:33:48 +08001155 u32 reg;
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001156
1157 dwc3_cache_hwparams(dwc);
1158
1159 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
1160 if (ret) {
1161 dev_err(dwc->dev, "failed to allocate event buffers\n");
1162 return -ENOMEM;
1163 }
1164
1165 ret = dwc3_core_init(dwc);
1166 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -04001167 dev_err(dwc->dev, "failed to initialize core\n");
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001168 goto core_fail;
1169 }
1170
1171 ret = dwc3_event_buffers_setup(dwc);
1172 if (ret) {
1173 dev_err(dwc->dev, "failed to setup event buffers\n");
1174 goto event_fail;
1175 }
1176
Jagan Teki0ece2f72020-05-26 11:33:48 +08001177 if (dwc->revision >= DWC3_REVISION_250A) {
1178 reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
1179
1180 /*
1181 * Enable hardware control of sending remote wakeup
1182 * in HS when the device is in the L1 state.
1183 */
1184 if (dwc->revision >= DWC3_REVISION_290A)
1185 reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
1186
1187 if (dwc->dis_tx_ipgap_linecheck_quirk)
1188 reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
1189
1190 dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
1191 }
1192
Jagan Teki461409b2020-05-26 11:34:29 +08001193 if (dwc->dr_mode == USB_DR_MODE_HOST ||
1194 dwc->dr_mode == USB_DR_MODE_OTG) {
1195 reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
1196
1197 reg |= DWC3_GUCTL_HSTINAUTORETRY;
1198
1199 dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
1200 }
1201
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001202 ret = dwc3_core_init_mode(dwc);
1203 if (ret)
1204 goto mode_fail;
1205
1206 return 0;
1207
1208mode_fail:
1209 dwc3_event_buffers_cleanup(dwc);
1210
1211event_fail:
1212 dwc3_core_exit(dwc);
1213
1214core_fail:
1215 dwc3_free_event_buffers(dwc);
1216
1217 return ret;
1218}
1219
1220void dwc3_remove(struct dwc3 *dwc)
1221{
1222 dwc3_core_exit_mode(dwc);
1223 dwc3_event_buffers_cleanup(dwc);
1224 dwc3_free_event_buffers(dwc);
Angus Ainslieeefabee2022-02-02 15:08:55 -08001225 dwc3_core_stop(dwc);
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001226 dwc3_core_exit(dwc);
1227 kfree(dwc->mem);
1228}
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001229#endif