blob: 96e850b7170f346051f46e30462551bbe7c11a36 [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
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +053016#include <common.h>
Sean Andersonf6785a82022-11-27 15:31:54 +010017#include <clk.h>
Simon Glass63334482019-11-14 12:57:39 -070018#include <cpu_func.h>
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +053019#include <malloc.h>
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +053020#include <dwc3-uboot.h>
Simon Glass9bc15642020-02-03 07:36:16 -070021#include <dm/device_compat.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070022#include <dm/devres.h>
Simon Glassc06c1be2020-05-10 11:40:08 -060023#include <linux/bug.h>
Simon Glassdbd79542020-05-10 11:40:11 -060024#include <linux/delay.h>
Masahiro Yamada6373a172020-02-14 16:40:19 +090025#include <linux/dma-mapping.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070026#include <linux/err.h>
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053027#include <linux/ioport.h>
Mugunthan V N121f93c2018-05-18 13:10:27 +020028#include <dm.h>
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +010029#include <generic-phy.h>
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053030#include <linux/usb/ch9.h>
31#include <linux/usb/gadget.h>
Balaji Prakash J840d2192022-11-27 15:31:53 +010032#include <linux/bitfield.h>
Sean Anderson27ef4e62022-11-27 15:31:55 +010033#include <linux/math64.h>
Igor Prusovc3421ea2023-11-09 20:10:04 +030034#include <linux/time.h>
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053035
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053036#include "core.h"
37#include "gadget.h"
38#include "io.h"
39
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +053040#include "linux-compat.h"
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053041
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +053042static LIST_HEAD(dwc3_list);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053043/* -------------------------------------------------------------------------- */
44
Joonyoung Shimbf35c602015-03-03 17:32:09 +010045static void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053046{
47 u32 reg;
48
49 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
50 reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
51 reg |= DWC3_GCTL_PRTCAPDIR(mode);
52 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
53}
54
55/**
56 * dwc3_core_soft_reset - Issues core soft reset and PHY reset
57 * @dwc: pointer to our context structure
58 */
59static int dwc3_core_soft_reset(struct dwc3 *dwc)
60{
61 u32 reg;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053062
63 /* Before Resetting PHY, put Core in Reset */
64 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
65 reg |= DWC3_GCTL_CORESOFTRESET;
66 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
67
68 /* Assert USB3 PHY reset */
69 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
70 reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
71 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
72
73 /* Assert USB2 PHY reset */
74 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
75 reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
76 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
77
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053078 mdelay(100);
79
80 /* Clear USB3 PHY reset */
81 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
82 reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
83 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
84
85 /* Clear USB2 PHY reset */
86 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
87 reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
88 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
89
90 mdelay(100);
91
92 /* After PHYs are stable we can take Core out of reset state */
93 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
94 reg &= ~DWC3_GCTL_CORESOFTRESET;
95 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
96
97 return 0;
98}
99
Michael Walle679f13c2021-10-15 15:15:21 +0200100/*
101 * dwc3_frame_length_adjustment - Adjusts frame length if required
102 * @dwc3: Pointer to our controller context structure
103 * @fladj: Value of GFLADJ_30MHZ to adjust frame length
104 */
105static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj)
106{
107 u32 reg;
108
109 if (dwc->revision < DWC3_REVISION_250A)
110 return;
111
112 if (fladj == 0)
113 return;
114
115 reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
116 reg &= ~DWC3_GFLADJ_30MHZ_MASK;
117 reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj;
118 dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
119}
120
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530121/**
Balaji Prakash J840d2192022-11-27 15:31:53 +0100122 * dwc3_ref_clk_period - Reference clock period configuration
123 * Default reference clock period depends on hardware
124 * configuration. For systems with reference clock that differs
125 * from the default, this will set clock period in DWC3_GUCTL
126 * register.
127 * @dwc: Pointer to our controller context structure
128 * @ref_clk_per: reference clock period in ns
129 */
130static void dwc3_ref_clk_period(struct dwc3 *dwc)
131{
Sean Andersonf6785a82022-11-27 15:31:54 +0100132 unsigned long period;
Sean Anderson27ef4e62022-11-27 15:31:55 +0100133 unsigned long fladj;
134 unsigned long decr;
Sean Andersonf6785a82022-11-27 15:31:54 +0100135 unsigned long rate;
Balaji Prakash J840d2192022-11-27 15:31:53 +0100136 u32 reg;
137
Sean Andersonf6785a82022-11-27 15:31:54 +0100138 if (dwc->ref_clk) {
139 rate = clk_get_rate(dwc->ref_clk);
140 if (!rate)
141 return;
142 period = NSEC_PER_SEC / rate;
Sean Andersonf6785a82022-11-27 15:31:54 +0100143 } else {
Balaji Prakash J840d2192022-11-27 15:31:53 +0100144 return;
Sean Andersonf6785a82022-11-27 15:31:54 +0100145 }
Balaji Prakash J840d2192022-11-27 15:31:53 +0100146
147 reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
148 reg &= ~DWC3_GUCTL_REFCLKPER_MASK;
Sean Andersonf6785a82022-11-27 15:31:54 +0100149 reg |= FIELD_PREP(DWC3_GUCTL_REFCLKPER_MASK, period);
Balaji Prakash J840d2192022-11-27 15:31:53 +0100150 dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
Sean Anderson27ef4e62022-11-27 15:31:55 +0100151
152 if (dwc->revision <= DWC3_REVISION_250A)
153 return;
154
155 /*
156 * The calculation below is
157 *
158 * 125000 * (NSEC_PER_SEC / (rate * period) - 1)
159 *
160 * but rearranged for fixed-point arithmetic. The division must be
161 * 64-bit because 125000 * NSEC_PER_SEC doesn't fit in 32 bits (and
162 * neither does rate * period).
163 *
164 * Note that rate * period ~= NSEC_PER_SECOND, minus the number of
165 * nanoseconds of error caused by the truncation which happened during
166 * the division when calculating rate or period (whichever one was
167 * derived from the other). We first calculate the relative error, then
168 * scale it to units of 8 ppm.
169 */
170 fladj = div64_u64(125000ULL * NSEC_PER_SEC, (u64)rate * period);
171 fladj -= 125000;
172
173 /*
174 * The documented 240MHz constant is scaled by 2 to get PLS1 as well.
175 */
176 decr = 480000000 / rate;
177
178 reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
179 reg &= ~DWC3_GFLADJ_REFCLK_FLADJ_MASK
180 & ~DWC3_GFLADJ_240MHZDECR
181 & ~DWC3_GFLADJ_240MHZDECR_PLS1;
182 reg |= FIELD_PREP(DWC3_GFLADJ_REFCLK_FLADJ_MASK, fladj)
183 | FIELD_PREP(DWC3_GFLADJ_240MHZDECR, decr >> 1)
184 | FIELD_PREP(DWC3_GFLADJ_240MHZDECR_PLS1, decr & 1);
185 dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
Balaji Prakash J840d2192022-11-27 15:31:53 +0100186}
187
188/**
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530189 * dwc3_free_one_event_buffer - Frees one event buffer
190 * @dwc: Pointer to our controller context structure
191 * @evt: Pointer to event buffer to be freed
192 */
193static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
194 struct dwc3_event_buffer *evt)
195{
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530196 dma_free_coherent(evt->buf);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530197}
198
199/**
200 * dwc3_alloc_one_event_buffer - Allocates one event buffer structure
201 * @dwc: Pointer to our controller context structure
202 * @length: size of the event buffer
203 *
204 * Returns a pointer to the allocated event buffer structure on success
205 * otherwise ERR_PTR(errno).
206 */
207static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
208 unsigned length)
209{
210 struct dwc3_event_buffer *evt;
211
Mugunthan V N121f93c2018-05-18 13:10:27 +0200212 evt = devm_kzalloc((struct udevice *)dwc->dev, sizeof(*evt),
213 GFP_KERNEL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530214 if (!evt)
215 return ERR_PTR(-ENOMEM);
216
217 evt->dwc = dwc;
218 evt->length = length;
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530219 evt->buf = dma_alloc_coherent(length,
220 (unsigned long *)&evt->dma);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530221 if (!evt->buf)
222 return ERR_PTR(-ENOMEM);
223
Philipp Tomsich8e17c162017-04-06 16:58:53 +0200224 dwc3_flush_cache((uintptr_t)evt->buf, evt->length);
225
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530226 return evt;
227}
228
229/**
230 * dwc3_free_event_buffers - frees all allocated event buffers
231 * @dwc: Pointer to our controller context structure
232 */
233static void dwc3_free_event_buffers(struct dwc3 *dwc)
234{
235 struct dwc3_event_buffer *evt;
236 int i;
237
238 for (i = 0; i < dwc->num_event_buffers; i++) {
239 evt = dwc->ev_buffs[i];
240 if (evt)
241 dwc3_free_one_event_buffer(dwc, evt);
242 }
243}
244
245/**
246 * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length
247 * @dwc: pointer to our controller context structure
248 * @length: size of event buffer
249 *
250 * Returns 0 on success otherwise negative errno. In the error case, dwc
251 * may contain some buffers allocated but not all which were requested.
252 */
253static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
254{
255 int num;
256 int i;
257
258 num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
259 dwc->num_event_buffers = num;
260
Kishon Vijay Abraham Ic7bdfe32015-02-23 18:40:13 +0530261 dwc->ev_buffs = memalign(CONFIG_SYS_CACHELINE_SIZE,
262 sizeof(*dwc->ev_buffs) * num);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530263 if (!dwc->ev_buffs)
264 return -ENOMEM;
265
266 for (i = 0; i < num; i++) {
267 struct dwc3_event_buffer *evt;
268
269 evt = dwc3_alloc_one_event_buffer(dwc, length);
270 if (IS_ERR(evt)) {
271 dev_err(dwc->dev, "can't allocate event buffer\n");
272 return PTR_ERR(evt);
273 }
274 dwc->ev_buffs[i] = evt;
275 }
276
277 return 0;
278}
279
280/**
281 * dwc3_event_buffers_setup - setup our allocated event buffers
282 * @dwc: pointer to our controller context structure
283 *
284 * Returns 0 on success otherwise negative errno.
285 */
286static int dwc3_event_buffers_setup(struct dwc3 *dwc)
287{
288 struct dwc3_event_buffer *evt;
289 int n;
290
291 for (n = 0; n < dwc->num_event_buffers; n++) {
292 evt = dwc->ev_buffs[n];
293 dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n",
294 evt->buf, (unsigned long long) evt->dma,
295 evt->length);
296
297 evt->lpos = 0;
298
299 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
300 lower_32_bits(evt->dma));
301 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
302 upper_32_bits(evt->dma));
303 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
304 DWC3_GEVNTSIZ_SIZE(evt->length));
305 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
306 }
307
308 return 0;
309}
310
311static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
312{
313 struct dwc3_event_buffer *evt;
314 int n;
315
316 for (n = 0; n < dwc->num_event_buffers; n++) {
317 evt = dwc->ev_buffs[n];
318
319 evt->lpos = 0;
320
321 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
322 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
323 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK
324 | DWC3_GEVNTSIZ_SIZE(0));
325 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
326 }
327}
328
329static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
330{
331 if (!dwc->has_hibernation)
332 return 0;
333
334 if (!dwc->nr_scratch)
335 return 0;
336
337 dwc->scratchbuf = kmalloc_array(dwc->nr_scratch,
338 DWC3_SCRATCHBUF_SIZE, GFP_KERNEL);
339 if (!dwc->scratchbuf)
340 return -ENOMEM;
341
342 return 0;
343}
344
345static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
346{
347 dma_addr_t scratch_addr;
348 u32 param;
349 int ret;
350
351 if (!dwc->has_hibernation)
352 return 0;
353
354 if (!dwc->nr_scratch)
355 return 0;
356
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530357 scratch_addr = dma_map_single(dwc->scratchbuf,
358 dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
359 DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530360 if (dma_mapping_error(dwc->dev, scratch_addr)) {
361 dev_err(dwc->dev, "failed to map scratch buffer\n");
362 ret = -EFAULT;
363 goto err0;
364 }
365
366 dwc->scratch_addr = scratch_addr;
367
368 param = lower_32_bits(scratch_addr);
369
370 ret = dwc3_send_gadget_generic_command(dwc,
371 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param);
372 if (ret < 0)
373 goto err1;
374
375 param = upper_32_bits(scratch_addr);
376
377 ret = dwc3_send_gadget_generic_command(dwc,
378 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param);
379 if (ret < 0)
380 goto err1;
381
382 return 0;
383
384err1:
Masahiro Yamada05a5dba2020-02-14 16:40:18 +0900385 dma_unmap_single(scratch_addr, dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
386 DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530387
388err0:
389 return ret;
390}
391
392static void dwc3_free_scratch_buffers(struct dwc3 *dwc)
393{
394 if (!dwc->has_hibernation)
395 return;
396
397 if (!dwc->nr_scratch)
398 return;
399
Masahiro Yamada05a5dba2020-02-14 16:40:18 +0900400 dma_unmap_single(dwc->scratch_addr, dwc->nr_scratch *
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530401 DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530402 kfree(dwc->scratchbuf);
403}
404
405static void dwc3_core_num_eps(struct dwc3 *dwc)
406{
407 struct dwc3_hwparams *parms = &dwc->hwparams;
408
409 dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
410 dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
411
412 dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
413 dwc->num_in_eps, dwc->num_out_eps);
414}
415
416static void dwc3_cache_hwparams(struct dwc3 *dwc)
417{
418 struct dwc3_hwparams *parms = &dwc->hwparams;
419
420 parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
421 parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
422 parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
423 parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
424 parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
425 parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
426 parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
427 parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
428 parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
429}
430
Frank Wanga4a29122020-05-26 11:34:30 +0800431static void dwc3_hsphy_mode_setup(struct dwc3 *dwc)
432{
433 enum usb_phy_interface hsphy_mode = dwc->hsphy_mode;
434 u32 reg;
435
436 /* Set dwc3 usb2 phy config */
437 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
438
439 switch (hsphy_mode) {
440 case USBPHY_INTERFACE_MODE_UTMI:
441 reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
442 DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
443 reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) |
444 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT);
445 break;
446 case USBPHY_INTERFACE_MODE_UTMIW:
447 reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
448 DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
449 reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) |
450 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT);
451 break;
452 default:
453 break;
454 }
455
456 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
457}
458
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530459/**
460 * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
461 * @dwc: Pointer to our controller context structure
462 */
463static void dwc3_phy_setup(struct dwc3 *dwc)
464{
465 u32 reg;
466
467 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
468
469 /*
470 * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
471 * to '0' during coreConsultant configuration. So default value
472 * will be '0' when the core is reset. Application needs to set it
473 * to '1' after the core initialization is completed.
474 */
475 if (dwc->revision > DWC3_REVISION_194A)
476 reg |= DWC3_GUSB3PIPECTL_SUSPHY;
477
478 if (dwc->u2ss_inp3_quirk)
479 reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
480
481 if (dwc->req_p1p2p3_quirk)
482 reg |= DWC3_GUSB3PIPECTL_REQP1P2P3;
483
484 if (dwc->del_p1p2p3_quirk)
485 reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN;
486
487 if (dwc->del_phy_power_chg_quirk)
488 reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE;
489
490 if (dwc->lfps_filter_quirk)
491 reg |= DWC3_GUSB3PIPECTL_LFPSFILT;
492
493 if (dwc->rx_detect_poll_quirk)
494 reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL;
495
496 if (dwc->tx_de_emphasis_quirk)
497 reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
498
499 if (dwc->dis_u3_susphy_quirk)
500 reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
501
Jagan Tekic1157dc2020-05-06 13:20:25 +0530502 if (dwc->dis_del_phy_power_chg_quirk)
503 reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
504
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530505 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
506
Frank Wanga4a29122020-05-26 11:34:30 +0800507 dwc3_hsphy_mode_setup(dwc);
508
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530509 mdelay(100);
510
511 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
512
513 /*
514 * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
515 * '0' during coreConsultant configuration. So default value will
516 * be '0' when the core is reset. Application needs to set it to
517 * '1' after the core initialization is completed.
518 */
519 if (dwc->revision > DWC3_REVISION_194A)
520 reg |= DWC3_GUSB2PHYCFG_SUSPHY;
521
522 if (dwc->dis_u2_susphy_quirk)
523 reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
524
Frank Wang0c3b6f52020-05-26 11:33:46 +0800525 if (dwc->dis_enblslpm_quirk)
526 reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
527
Frank Wangb29bcd72020-05-26 11:33:47 +0800528 if (dwc->dis_u2_freeclk_exists_quirk)
529 reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS;
530
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530531 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
532
533 mdelay(100);
534}
535
Michael Walle668bdf62021-10-15 15:15:22 +0200536/* set global incr burst type configuration registers */
537static void dwc3_set_incr_burst_type(struct dwc3 *dwc)
538{
539 struct udevice *dev = dwc->dev;
540 u32 cfg;
541
542 if (!dwc->incrx_size)
543 return;
544
545 cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0);
546
547 /* Enable Undefined Length INCR Burst and Enable INCRx Burst */
548 cfg &= ~DWC3_GSBUSCFG0_INCRBRST_MASK;
549 if (dwc->incrx_mode)
550 cfg |= DWC3_GSBUSCFG0_INCRBRSTENA;
551 switch (dwc->incrx_size) {
552 case 256:
553 cfg |= DWC3_GSBUSCFG0_INCR256BRSTENA;
554 break;
555 case 128:
556 cfg |= DWC3_GSBUSCFG0_INCR128BRSTENA;
557 break;
558 case 64:
559 cfg |= DWC3_GSBUSCFG0_INCR64BRSTENA;
560 break;
561 case 32:
562 cfg |= DWC3_GSBUSCFG0_INCR32BRSTENA;
563 break;
564 case 16:
565 cfg |= DWC3_GSBUSCFG0_INCR16BRSTENA;
566 break;
567 case 8:
568 cfg |= DWC3_GSBUSCFG0_INCR8BRSTENA;
569 break;
570 case 4:
571 cfg |= DWC3_GSBUSCFG0_INCR4BRSTENA;
572 break;
573 case 1:
574 break;
575 default:
576 dev_err(dev, "Invalid property\n");
577 break;
578 }
579
580 dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg);
581}
582
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530583/**
584 * dwc3_core_init - Low-level initialization of DWC3 Core
585 * @dwc: Pointer to our controller context structure
586 *
587 * Returns 0 on success otherwise negative errno.
588 */
589static int dwc3_core_init(struct dwc3 *dwc)
590{
591 unsigned long timeout;
592 u32 hwparams4 = dwc->hwparams.hwparams4;
593 u32 reg;
594 int ret;
595
596 reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
597 /* This should read as U3 followed by revision number */
598 if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
599 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