blob: 7ca9d09824e67296488180437d0fd8cb4f5853cc [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +05302/**
3 * core.c - DesignWare USB3 DRD Controller Core file
4 *
Kishon Vijay Abraham I30c31d52015-02-23 18:39:52 +05305 * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +05306 *
7 * Authors: Felipe Balbi <balbi@ti.com>,
8 * Sebastian Andrzej Siewior <bigeasy@linutronix.de>
9 *
Kishon Vijay Abraham I30c31d52015-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 I85d5e702015-02-23 18:39:50 +053012 *
Kishon Vijay Abraham I30c31d52015-02-23 18:39:52 +053013 * commit cd72f890d2 : usb: dwc3: core: enable phy suspend quirk on non-FPGA
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +053014 */
15
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +053016#include <common.h>
Sean Anderson6bae0eb2022-11-27 15:31:54 +010017#include <clk.h>
Simon Glass1eb69ae2019-11-14 12:57:39 -070018#include <cpu_func.h>
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +053019#include <malloc.h>
Kishon Vijay Abraham I8e1906a2015-02-23 18:40:04 +053020#include <dwc3-uboot.h>
Simon Glass336d4612020-02-03 07:36:16 -070021#include <dm/device_compat.h>
Simon Glass61b29b82020-02-03 07:36:15 -070022#include <dm/devres.h>
Simon Glasseb41d8a2020-05-10 11:40:08 -060023#include <linux/bug.h>
Simon Glassc05ed002020-05-10 11:40:11 -060024#include <linux/delay.h>
Masahiro Yamada9d86b892020-02-14 16:40:19 +090025#include <linux/dma-mapping.h>
Simon Glass61b29b82020-02-03 07:36:15 -070026#include <linux/err.h>
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +053027#include <linux/ioport.h>
Mugunthan V N0ad3f772018-05-18 13:10:27 +020028#include <dm.h>
Jean-Jacques Hiblotd648a502018-11-29 10:52:45 +010029#include <generic-phy.h>
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +053030#include <linux/usb/ch9.h>
31#include <linux/usb/gadget.h>
Balaji Prakash J57548e82022-11-27 15:31:53 +010032#include <linux/bitfield.h>
Sean Andersonc55ac512022-11-27 15:31:55 +010033#include <linux/math64.h>
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +053034
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +053035#include "core.h"
36#include "gadget.h"
37#include "io.h"
38
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +053039#include "linux-compat.h"
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +053040
Sean Andersonc55ac512022-11-27 15:31:55 +010041#define NSEC_PER_SEC 1000000000L
42
Kishon Vijay Abraham I793d3472015-02-23 18:40:05 +053043static LIST_HEAD(dwc3_list);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +053044/* -------------------------------------------------------------------------- */
45
Joonyoung Shim7e9cb792015-03-03 17:32:09 +010046static void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +053047{
48 u32 reg;
49
50 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
51 reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
52 reg |= DWC3_GCTL_PRTCAPDIR(mode);
53 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
54}
55
56/**
57 * dwc3_core_soft_reset - Issues core soft reset and PHY reset
58 * @dwc: pointer to our context structure
59 */
60static int dwc3_core_soft_reset(struct dwc3 *dwc)
61{
62 u32 reg;
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +053063
64 /* Before Resetting PHY, put Core in Reset */
65 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
66 reg |= DWC3_GCTL_CORESOFTRESET;
67 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
68
69 /* Assert USB3 PHY reset */
70 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
71 reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
72 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
73
74 /* Assert USB2 PHY reset */
75 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
76 reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
77 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
78
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +053079 mdelay(100);
80
81 /* Clear USB3 PHY reset */
82 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
83 reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
84 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
85
86 /* Clear USB2 PHY reset */
87 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
88 reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
89 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
90
91 mdelay(100);
92
93 /* After PHYs are stable we can take Core out of reset state */
94 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
95 reg &= ~DWC3_GCTL_CORESOFTRESET;
96 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
97
98 return 0;
99}
100
Michael Walled274cbb2021-10-15 15:15:21 +0200101/*
102 * dwc3_frame_length_adjustment - Adjusts frame length if required
103 * @dwc3: Pointer to our controller context structure
104 * @fladj: Value of GFLADJ_30MHZ to adjust frame length
105 */
106static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj)
107{
108 u32 reg;
109
110 if (dwc->revision < DWC3_REVISION_250A)
111 return;
112
113 if (fladj == 0)
114 return;
115
116 reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
117 reg &= ~DWC3_GFLADJ_30MHZ_MASK;
118 reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj;
119 dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
120}
121
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530122/**
Balaji Prakash J57548e82022-11-27 15:31:53 +0100123 * dwc3_ref_clk_period - Reference clock period configuration
124 * Default reference clock period depends on hardware
125 * configuration. For systems with reference clock that differs
126 * from the default, this will set clock period in DWC3_GUCTL
127 * register.
128 * @dwc: Pointer to our controller context structure
129 * @ref_clk_per: reference clock period in ns
130 */
131static void dwc3_ref_clk_period(struct dwc3 *dwc)
132{
Sean Anderson6bae0eb2022-11-27 15:31:54 +0100133 unsigned long period;
Sean Andersonc55ac512022-11-27 15:31:55 +0100134 unsigned long fladj;
135 unsigned long decr;
Sean Anderson6bae0eb2022-11-27 15:31:54 +0100136 unsigned long rate;
Balaji Prakash J57548e82022-11-27 15:31:53 +0100137 u32 reg;
138
Sean Anderson6bae0eb2022-11-27 15:31:54 +0100139 if (dwc->ref_clk) {
140 rate = clk_get_rate(dwc->ref_clk);
141 if (!rate)
142 return;
143 period = NSEC_PER_SEC / rate;
Sean Anderson6bae0eb2022-11-27 15:31:54 +0100144 } else {
Balaji Prakash J57548e82022-11-27 15:31:53 +0100145 return;
Sean Anderson6bae0eb2022-11-27 15:31:54 +0100146 }
Balaji Prakash J57548e82022-11-27 15:31:53 +0100147
148 reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
149 reg &= ~DWC3_GUCTL_REFCLKPER_MASK;
Sean Anderson6bae0eb2022-11-27 15:31:54 +0100150 reg |= FIELD_PREP(DWC3_GUCTL_REFCLKPER_MASK, period);
Balaji Prakash J57548e82022-11-27 15:31:53 +0100151 dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
Sean Andersonc55ac512022-11-27 15:31:55 +0100152
153 if (dwc->revision <= DWC3_REVISION_250A)
154 return;
155
156 /*
157 * The calculation below is
158 *
159 * 125000 * (NSEC_PER_SEC / (rate * period) - 1)
160 *
161 * but rearranged for fixed-point arithmetic. The division must be
162 * 64-bit because 125000 * NSEC_PER_SEC doesn't fit in 32 bits (and
163 * neither does rate * period).
164 *
165 * Note that rate * period ~= NSEC_PER_SECOND, minus the number of
166 * nanoseconds of error caused by the truncation which happened during
167 * the division when calculating rate or period (whichever one was
168 * derived from the other). We first calculate the relative error, then
169 * scale it to units of 8 ppm.
170 */
171 fladj = div64_u64(125000ULL * NSEC_PER_SEC, (u64)rate * period);
172 fladj -= 125000;
173
174 /*
175 * The documented 240MHz constant is scaled by 2 to get PLS1 as well.
176 */
177 decr = 480000000 / rate;
178
179 reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
180 reg &= ~DWC3_GFLADJ_REFCLK_FLADJ_MASK
181 & ~DWC3_GFLADJ_240MHZDECR
182 & ~DWC3_GFLADJ_240MHZDECR_PLS1;
183 reg |= FIELD_PREP(DWC3_GFLADJ_REFCLK_FLADJ_MASK, fladj)
184 | FIELD_PREP(DWC3_GFLADJ_240MHZDECR, decr >> 1)
185 | FIELD_PREP(DWC3_GFLADJ_240MHZDECR_PLS1, decr & 1);
186 dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
Balaji Prakash J57548e82022-11-27 15:31:53 +0100187}
188
189/**
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530190 * dwc3_free_one_event_buffer - Frees one event buffer
191 * @dwc: Pointer to our controller context structure
192 * @evt: Pointer to event buffer to be freed
193 */
194static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
195 struct dwc3_event_buffer *evt)
196{
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530197 dma_free_coherent(evt->buf);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530198}
199
200/**
201 * dwc3_alloc_one_event_buffer - Allocates one event buffer structure
202 * @dwc: Pointer to our controller context structure
203 * @length: size of the event buffer
204 *
205 * Returns a pointer to the allocated event buffer structure on success
206 * otherwise ERR_PTR(errno).
207 */
208static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
209 unsigned length)
210{
211 struct dwc3_event_buffer *evt;
212
Mugunthan V N0ad3f772018-05-18 13:10:27 +0200213 evt = devm_kzalloc((struct udevice *)dwc->dev, sizeof(*evt),
214 GFP_KERNEL);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530215 if (!evt)
216 return ERR_PTR(-ENOMEM);
217
218 evt->dwc = dwc;
219 evt->length = length;
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530220 evt->buf = dma_alloc_coherent(length,
221 (unsigned long *)&evt->dma);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530222 if (!evt->buf)
223 return ERR_PTR(-ENOMEM);
224
Philipp Tomsich889239d2017-04-06 16:58:53 +0200225 dwc3_flush_cache((uintptr_t)evt->buf, evt->length);
226
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530227 return evt;
228}
229
230/**
231 * dwc3_free_event_buffers - frees all allocated event buffers
232 * @dwc: Pointer to our controller context structure
233 */
234static void dwc3_free_event_buffers(struct dwc3 *dwc)
235{
236 struct dwc3_event_buffer *evt;
237 int i;
238
239 for (i = 0; i < dwc->num_event_buffers; i++) {
240 evt = dwc->ev_buffs[i];
241 if (evt)
242 dwc3_free_one_event_buffer(dwc, evt);
243 }
244}
245
246/**
247 * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length
248 * @dwc: pointer to our controller context structure
249 * @length: size of event buffer
250 *
251 * Returns 0 on success otherwise negative errno. In the error case, dwc
252 * may contain some buffers allocated but not all which were requested.
253 */
254static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
255{
256 int num;
257 int i;
258
259 num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
260 dwc->num_event_buffers = num;
261
Kishon Vijay Abraham I526a50f2015-02-23 18:40:13 +0530262 dwc->ev_buffs = memalign(CONFIG_SYS_CACHELINE_SIZE,
263 sizeof(*dwc->ev_buffs) * num);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530264 if (!dwc->ev_buffs)
265 return -ENOMEM;
266
267 for (i = 0; i < num; i++) {
268 struct dwc3_event_buffer *evt;
269
270 evt = dwc3_alloc_one_event_buffer(dwc, length);
271 if (IS_ERR(evt)) {
272 dev_err(dwc->dev, "can't allocate event buffer\n");
273 return PTR_ERR(evt);
274 }
275 dwc->ev_buffs[i] = evt;
276 }
277
278 return 0;
279}
280
281/**
282 * dwc3_event_buffers_setup - setup our allocated event buffers
283 * @dwc: pointer to our controller context structure
284 *
285 * Returns 0 on success otherwise negative errno.
286 */
287static int dwc3_event_buffers_setup(struct dwc3 *dwc)
288{
289 struct dwc3_event_buffer *evt;
290 int n;
291
292 for (n = 0; n < dwc->num_event_buffers; n++) {
293 evt = dwc->ev_buffs[n];
294 dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n",
295 evt->buf, (unsigned long long) evt->dma,
296 evt->length);
297
298 evt->lpos = 0;
299
300 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
301 lower_32_bits(evt->dma));
302 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
303 upper_32_bits(evt->dma));
304 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
305 DWC3_GEVNTSIZ_SIZE(evt->length));
306 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
307 }
308
309 return 0;
310}
311
312static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
313{
314 struct dwc3_event_buffer *evt;
315 int n;
316
317 for (n = 0; n < dwc->num_event_buffers; n++) {
318 evt = dwc->ev_buffs[n];
319
320 evt->lpos = 0;
321
322 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
323 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
324 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK
325 | DWC3_GEVNTSIZ_SIZE(0));
326 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
327 }
328}
329
330static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
331{
332 if (!dwc->has_hibernation)
333 return 0;
334
335 if (!dwc->nr_scratch)
336 return 0;
337
338 dwc->scratchbuf = kmalloc_array(dwc->nr_scratch,
339 DWC3_SCRATCHBUF_SIZE, GFP_KERNEL);
340 if (!dwc->scratchbuf)
341 return -ENOMEM;
342
343 return 0;
344}
345
346static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
347{
348 dma_addr_t scratch_addr;
349 u32 param;
350 int ret;
351
352 if (!dwc->has_hibernation)
353 return 0;
354
355 if (!dwc->nr_scratch)
356 return 0;
357
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530358 scratch_addr = dma_map_single(dwc->scratchbuf,
359 dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
360 DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530361 if (dma_mapping_error(dwc->dev, scratch_addr)) {
362 dev_err(dwc->dev, "failed to map scratch buffer\n");
363 ret = -EFAULT;
364 goto err0;
365 }
366
367 dwc->scratch_addr = scratch_addr;
368
369 param = lower_32_bits(scratch_addr);
370
371 ret = dwc3_send_gadget_generic_command(dwc,
372 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param);
373 if (ret < 0)
374 goto err1;
375
376 param = upper_32_bits(scratch_addr);
377
378 ret = dwc3_send_gadget_generic_command(dwc,
379 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param);
380 if (ret < 0)
381 goto err1;
382
383 return 0;
384
385err1:
Masahiro Yamada950c5962020-02-14 16:40:18 +0900386 dma_unmap_single(scratch_addr, dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
387 DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530388
389err0:
390 return ret;
391}
392
393static void dwc3_free_scratch_buffers(struct dwc3 *dwc)
394{
395 if (!dwc->has_hibernation)
396 return;
397
398 if (!dwc->nr_scratch)
399 return;
400
Masahiro Yamada950c5962020-02-14 16:40:18 +0900401 dma_unmap_single(dwc->scratch_addr, dwc->nr_scratch *
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530402 DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530403 kfree(dwc->scratchbuf);
404}
405
406static void dwc3_core_num_eps(struct dwc3 *dwc)
407{
408 struct dwc3_hwparams *parms = &dwc->hwparams;
409
410 dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
411 dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
412
413 dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
414 dwc->num_in_eps, dwc->num_out_eps);
415}
416
417static void dwc3_cache_hwparams(struct dwc3 *dwc)
418{
419 struct dwc3_hwparams *parms = &dwc->hwparams;
420
421 parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
422 parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
423 parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
424 parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
425 parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
426 parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
427 parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
428 parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
429 parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
430}
431
Frank Wang64697942020-05-26 11:34:30 +0800432static void dwc3_hsphy_mode_setup(struct dwc3 *dwc)
433{
434 enum usb_phy_interface hsphy_mode = dwc->hsphy_mode;
435 u32 reg;
436
437 /* Set dwc3 usb2 phy config */
438 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
439
440 switch (hsphy_mode) {
441 case USBPHY_INTERFACE_MODE_UTMI:
442 reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
443 DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
444 reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) |
445 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT);
446 break;
447 case USBPHY_INTERFACE_MODE_UTMIW:
448 reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
449 DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
450 reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) |
451 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT);
452 break;
453 default:
454 break;
455 }
456
457 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
458}
459
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530460/**
461 * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
462 * @dwc: Pointer to our controller context structure
463 */
464static void dwc3_phy_setup(struct dwc3 *dwc)
465{
466 u32 reg;
467
468 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
469
470 /*
471 * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
472 * to '0' during coreConsultant configuration. So default value
473 * will be '0' when the core is reset. Application needs to set it
474 * to '1' after the core initialization is completed.
475 */
476 if (dwc->revision > DWC3_REVISION_194A)
477 reg |= DWC3_GUSB3PIPECTL_SUSPHY;
478
479 if (dwc->u2ss_inp3_quirk)
480 reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
481
482 if (dwc->req_p1p2p3_quirk)
483 reg |= DWC3_GUSB3PIPECTL_REQP1P2P3;
484
485 if (dwc->del_p1p2p3_quirk)
486 reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN;
487
488 if (dwc->del_phy_power_chg_quirk)
489 reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE;
490
491 if (dwc->lfps_filter_quirk)
492 reg |= DWC3_GUSB3PIPECTL_LFPSFILT;
493
494 if (dwc->rx_detect_poll_quirk)
495 reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL;
496
497 if (dwc->tx_de_emphasis_quirk)
498 reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
499
500 if (dwc->dis_u3_susphy_quirk)
501 reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
502
Jagan Teki73ca0142020-05-06 13:20:25 +0530503 if (dwc->dis_del_phy_power_chg_quirk)
504 reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
505
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530506 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
507
Frank Wang64697942020-05-26 11:34:30 +0800508 dwc3_hsphy_mode_setup(dwc);
509
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530510 mdelay(100);
511
512 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
513
514 /*
515 * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
516 * '0' during coreConsultant configuration. So default value will
517 * be '0' when the core is reset. Application needs to set it to
518 * '1' after the core initialization is completed.
519 */
520 if (dwc->revision > DWC3_REVISION_194A)
521 reg |= DWC3_GUSB2PHYCFG_SUSPHY;
522
523 if (dwc->dis_u2_susphy_quirk)
524 reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
525
Frank Wang7bb62702020-05-26 11:33:46 +0800526 if (dwc->dis_enblslpm_quirk)
527 reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
528
Frank Wangb34f8b52020-05-26 11:33:47 +0800529 if (dwc->dis_u2_freeclk_exists_quirk)
530 reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS;
531
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530532 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
533
534 mdelay(100);
535}
536
Michael Wallef150b8d2021-10-15 15:15:22 +0200537/* set global incr burst type configuration registers */
538static void dwc3_set_incr_burst_type(struct dwc3 *dwc)
539{
540 struct udevice *dev = dwc->dev;
541 u32 cfg;
542
543 if (!dwc->incrx_size)
544 return;
545
546 cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0);
547
548 /* Enable Undefined Length INCR Burst and Enable INCRx Burst */
549 cfg &= ~DWC3_GSBUSCFG0_INCRBRST_MASK;
550 if (dwc->incrx_mode)
551 cfg |= DWC3_GSBUSCFG0_INCRBRSTENA;
552 switch (dwc->incrx_size) {
553 case 256:
554 cfg |= DWC3_GSBUSCFG0_INCR256BRSTENA;
555 break;
556 case 128:
557 cfg |= DWC3_GSBUSCFG0_INCR128BRSTENA;
558 break;
559 case 64:
560 cfg |= DWC3_GSBUSCFG0_INCR64BRSTENA;
561 break;
562 case 32:
563 cfg |= DWC3_GSBUSCFG0_INCR32BRSTENA;
564 break;
565 case 16:
566 cfg |= DWC3_GSBUSCFG0_INCR16BRSTENA;
567 break;
568 case 8:
569 cfg |= DWC3_GSBUSCFG0_INCR8BRSTENA;
570 break;
571 case 4:
572 cfg |= DWC3_GSBUSCFG0_INCR4BRSTENA;
573 break;
574 case 1:
575 break;
576 default:
577 dev_err(dev, "Invalid property\n");
578 break;
579 }
580
581 dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg);
582}
583
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530584/**
585 * dwc3_core_init - Low-level initialization of DWC3 Core
586 * @dwc: Pointer to our controller context structure
587 *
588 * Returns 0 on success otherwise negative errno.
589 */
590static int dwc3_core_init(struct dwc3 *dwc)
591{
592 unsigned long timeout;
593 u32 hwparams4 = dwc->hwparams.hwparams4;
594 u32 reg;
595 int ret;
596
597 reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
598 /* This should read as U3 followed by revision number */
599 if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
600 dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
601 ret = -ENODEV;
602 goto err0;
603 }
604 dwc->revision = reg;
605
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530606 /* Handle USB2.0-only core configuration */
607 if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
608 DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
609 if (dwc->maximum_speed == USB_SPEED_SUPER)
610 dwc->maximum_speed = USB_SPEED_HIGH;
611 }
612
613 /* issue device SoftReset too */
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530614 timeout = 5000;
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530615 dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530616 while (timeout--) {
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530617 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
618 if (!(reg & DWC3_DCTL_CSFTRST))
619 break;
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530620 };
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530621
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530622 if (!timeout) {
623 dev_err(dwc->dev, "Reset Timed Out\n");
624 ret = -ETIMEDOUT;
625 goto err0;
626 }
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530627
T Karthik Reddy1a031d22019-05-01 10:14:49 +0530628 dwc3_phy_setup(dwc);
629
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530630 ret = dwc3_core_soft_reset(dwc);
631 if (ret)
632 goto err0;
633
634 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
635 reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
636
637 switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
638 case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
639 /**
640 * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
641 * issue which would cause xHCI compliance tests to fail.
642 *
643 * Because of that we cannot enable clock gating on such
644 * configurations.
645 *
646 * Refers to:
647 *
648 * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based
649 * SOF/ITP Mode Used
650 */
651 if ((dwc->dr_mode == USB_DR_MODE_HOST ||
652 dwc->dr_mode == USB_DR_MODE_OTG) &&
653 (dwc->revision >= DWC3_REVISION_210A &&
654 dwc->revision <= DWC3_REVISION_250A))
655 reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
656 else
657 reg &= ~DWC3_GCTL_DSBLCLKGTNG;
658 break;
659 case DWC3_GHWPARAMS1_EN_PWROPT_HIB:
660 /* enable hibernation here */
661 dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4);
662
663 /*
664 * REVISIT Enabling this bit so that host-mode hibernation
665 * will work. Device-mode hibernation is not yet implemented.
666 */
667 reg |= DWC3_GCTL_GBLHIBERNATIONEN;
668 break;
669 default:
670 dev_dbg(dwc->dev, "No power optimization available\n");
671 }
672
673 /* check if current dwc3 is on simulation board */
674 if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
675 dev_dbg(dwc->dev, "it is on FPGA board\n");
676 dwc->is_fpga = true;
677 }
678
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530679 if(dwc->disable_scramble_quirk && !dwc->is_fpga)
680 WARN(true,
681 "disable_scramble cannot be used on non-FPGA builds\n");
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530682
683 if (dwc->disable_scramble_quirk && dwc->is_fpga)
684 reg |= DWC3_GCTL_DISSCRAMBLE;
685 else
686 reg &= ~DWC3_GCTL_DISSCRAMBLE;
687
688 if (dwc->u2exit_lfps_quirk)
689 reg |= DWC3_GCTL_U2EXIT_LFPS;
690
691 /*
692 * WORKAROUND: DWC3 revisions <1.90a have a bug
693 * where the device can fail to connect at SuperSpeed
694 * and falls back to high-speed mode which causes
695 * the device to enter a Connect/Disconnect loop
696 */
697 if (dwc->revision < DWC3_REVISION_190A)
698 reg |= DWC3_GCTL_U2RSTECN;
699
700 dwc3_core_num_eps(dwc);
701
702 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
703
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530704 ret = dwc3_alloc_scratch_buffers(dwc);
705 if (ret)
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530706 goto err0;
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530707
708 ret = dwc3_setup_scratch_buffers(dwc);
709 if (ret)
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530710 goto err1;
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530711
Michael Walled274cbb2021-10-15 15:15:21 +0200712 /* Adjust Frame Length */
713 dwc3_frame_length_adjustment(dwc, dwc->fladj);
714
Balaji Prakash J57548e82022-11-27 15:31:53 +0100715 /* Adjust Reference Clock Period */
716 dwc3_ref_clk_period(dwc);
717
Michael Wallef150b8d2021-10-15 15:15:22 +0200718 dwc3_set_incr_burst_type(dwc);
719
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530720 return 0;
721
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530722err1:
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530723 dwc3_free_scratch_buffers(dwc);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530724
725err0:
726 return ret;
727}
728
729static void dwc3_core_exit(struct dwc3 *dwc)
730{
731 dwc3_free_scratch_buffers(dwc);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530732}
733
734static int dwc3_core_init_mode(struct dwc3 *dwc)
735{
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530736 int ret;
737
738 switch (dwc->dr_mode) {
739 case USB_DR_MODE_PERIPHERAL:
740 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
741 ret = dwc3_gadget_init(dwc);
742 if (ret) {
Sean Andersondf5eabc2020-09-15 10:45:16 -0400743 dev_err(dwc->dev, "failed to initialize gadget\n");
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530744 return ret;
745 }
746 break;
747 case USB_DR_MODE_HOST:
748 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
749 ret = dwc3_host_init(dwc);
750 if (ret) {
Sean Andersondf5eabc2020-09-15 10:45:16 -0400751 dev_err(dwc->dev, "failed to initialize host\n");
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530752 return ret;
753 }
754 break;
755 case USB_DR_MODE_OTG:
756 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
757 ret = dwc3_host_init(dwc);
758 if (ret) {
Sean Andersondf5eabc2020-09-15 10:45:16 -0400759 dev_err(dwc->dev, "failed to initialize host\n");
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530760 return ret;
761 }
762
763 ret = dwc3_gadget_init(dwc);
764 if (ret) {
Sean Andersondf5eabc2020-09-15 10:45:16 -0400765 dev_err(dwc->dev, "failed to initialize gadget\n");
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530766 return ret;
767 }
768 break;
769 default:
Sean Andersondf5eabc2020-09-15 10:45:16 -0400770 dev_err(dwc->dev,
771 "Unsupported mode of operation %d\n", dwc->dr_mode);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530772 return -EINVAL;
773 }
774
775 return 0;
776}
777
Jean-Jacques Hiblotbbe3d4a2019-09-11 11:33:45 +0200778static void dwc3_gadget_run(struct dwc3 *dwc)
779{
780 dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_RUN_STOP);
781 mdelay(100);
782}
783
Angus Ainsliefb146fb2022-02-02 15:08:55 -0800784static void dwc3_core_stop(struct dwc3 *dwc)
785{
786 u32 reg;
787
788 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
789 dwc3_writel(dwc->regs, DWC3_DCTL, reg & ~(DWC3_DCTL_RUN_STOP));
790}
791
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530792static void dwc3_core_exit_mode(struct dwc3 *dwc)
793{
794 switch (dwc->dr_mode) {
795 case USB_DR_MODE_PERIPHERAL:
796 dwc3_gadget_exit(dwc);
797 break;
798 case USB_DR_MODE_HOST:
799 dwc3_host_exit(dwc);
800 break;
801 case USB_DR_MODE_OTG:
802 dwc3_host_exit(dwc);
803 dwc3_gadget_exit(dwc);
804 break;
805 default:
806 /* do nothing */
807 break;
808 }
Jean-Jacques Hiblotbbe3d4a2019-09-11 11:33:45 +0200809
810 /*
811 * switch back to peripheral mode
812 * This enables the phy to enter idle and then, if enabled, suspend.
813 */
814 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
815 dwc3_gadget_run(dwc);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530816}
817
818#define DWC3_ALIGN_MASK (16 - 1)
819
Kishon Vijay Abraham I8e1906a2015-02-23 18:40:04 +0530820/**
821 * dwc3_uboot_init - dwc3 core uboot initialization code
822 * @dwc3_dev: struct dwc3_device containing initialization data
823 *
824 * Entry point for dwc3 driver (equivalent to dwc3_probe in linux
825 * kernel driver). Pointer to dwc3_device should be passed containing
826 * base address and other initialization data. Returns '0' on success and
827 * a negative value on failure.
828 *
829 * Generally called from board_usb_init() implemented in board file.
830 */
831int dwc3_uboot_init(struct dwc3_device *dwc3_dev)
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530832{
Kishon Vijay Abraham I793d3472015-02-23 18:40:05 +0530833 struct dwc3 *dwc;
Felipe Balbic2ad4e12015-10-01 14:22:18 -0500834 struct device *dev = NULL;
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530835 u8 lpm_nyet_threshold;
836 u8 tx_de_emphasis;
837 u8 hird_threshold;
838
839 int ret;
840
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530841 void *mem;
842
Mugunthan V N0ad3f772018-05-18 13:10:27 +0200843 mem = devm_kzalloc((struct udevice *)dev,
844 sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530845 if (!mem)
846 return -ENOMEM;
847
848 dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
849 dwc->mem = mem;
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530850
Michal Simek01c94c42015-10-30 16:24:06 +0100851 dwc->regs = (void *)(uintptr_t)(dwc3_dev->base +
852 DWC3_GLOBALS_REGS_START);
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530853
854 /* default to highest possible threshold */
855 lpm_nyet_threshold = 0xff;
856
857 /* default to -3.5dB de-emphasis */
858 tx_de_emphasis = 1;
859
860 /*
861 * default to assert utmi_sleep_n and use maximum allowed HIRD
862 * threshold value of 0b1100
863 */
864 hird_threshold = 12;
865
Kishon Vijay Abraham I8e1906a2015-02-23 18:40:04 +0530866 dwc->maximum_speed = dwc3_dev->maximum_speed;
867 dwc->has_lpm_erratum = dwc3_dev->has_lpm_erratum;
868 if (dwc3_dev->lpm_nyet_threshold)
869 lpm_nyet_threshold = dwc3_dev->lpm_nyet_threshold;
870 dwc->is_utmi_l1_suspend = dwc3_dev->is_utmi_l1_suspend;
871 if (dwc3_dev->hird_threshold)
872 hird_threshold = dwc3_dev->hird_threshold;
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530873
Kishon Vijay Abraham I8e1906a2015-02-23 18:40:04 +0530874 dwc->needs_fifo_resize = dwc3_dev->tx_fifo_resize;
875 dwc->dr_mode = dwc3_dev->dr_mode;
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530876
Kishon Vijay Abraham I8e1906a2015-02-23 18:40:04 +0530877 dwc->disable_scramble_quirk = dwc3_dev->disable_scramble_quirk;
878 dwc->u2exit_lfps_quirk = dwc3_dev->u2exit_lfps_quirk;
879 dwc->u2ss_inp3_quirk = dwc3_dev->u2ss_inp3_quirk;
880 dwc->req_p1p2p3_quirk = dwc3_dev->req_p1p2p3_quirk;
881 dwc->del_p1p2p3_quirk = dwc3_dev->del_p1p2p3_quirk;
882 dwc->del_phy_power_chg_quirk = dwc3_dev->del_phy_power_chg_quirk;
883 dwc->lfps_filter_quirk = dwc3_dev->lfps_filter_quirk;
884 dwc->rx_detect_poll_quirk = dwc3_dev->rx_detect_poll_quirk;
885 dwc->dis_u3_susphy_quirk = dwc3_dev->dis_u3_susphy_quirk;
886 dwc->dis_u2_susphy_quirk = dwc3_dev->dis_u2_susphy_quirk;
Jagan Teki73ca0142020-05-06 13:20:25 +0530887 dwc->dis_del_phy_power_chg_quirk = dwc3_dev->dis_del_phy_power_chg_quirk;
Jagan Tekidc184132020-05-26 11:33:48 +0800888 dwc->dis_tx_ipgap_linecheck_quirk = dwc3_dev->dis_tx_ipgap_linecheck_quirk;
Frank Wang7bb62702020-05-26 11:33:46 +0800889 dwc->dis_enblslpm_quirk = dwc3_dev->dis_enblslpm_quirk;
Frank Wangb34f8b52020-05-26 11:33:47 +0800890 dwc->dis_u2_freeclk_exists_quirk = dwc3_dev->dis_u2_freeclk_exists_quirk;
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530891
Kishon Vijay Abraham I8e1906a2015-02-23 18:40:04 +0530892 dwc->tx_de_emphasis_quirk = dwc3_dev->tx_de_emphasis_quirk;
893 if (dwc3_dev->tx_de_emphasis)
894 tx_de_emphasis = dwc3_dev->tx_de_emphasis;
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530895
896 /* default to superspeed if no maximum_speed passed */
897 if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
898 dwc->maximum_speed = USB_SPEED_SUPER;
899
900 dwc->lpm_nyet_threshold = lpm_nyet_threshold;
901 dwc->tx_de_emphasis = tx_de_emphasis;
902
903 dwc->hird_threshold = hird_threshold
904 | (dwc->is_utmi_l1_suspend << 4);
905
Frank Wang64697942020-05-26 11:34:30 +0800906 dwc->hsphy_mode = dwc3_dev->hsphy_mode;
907
Kishon Vijay Abraham I793d3472015-02-23 18:40:05 +0530908 dwc->index = dwc3_dev->index;
909
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530910 dwc3_cache_hwparams(dwc);
911
912 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
913 if (ret) {
914 dev_err(dwc->dev, "failed to allocate event buffers\n");
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530915 return -ENOMEM;
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530916 }
917
Jean-Jacques Hiblot3e6ab732019-09-11 11:33:53 +0200918 if (!IS_ENABLED(CONFIG_USB_DWC3_GADGET))
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530919 dwc->dr_mode = USB_DR_MODE_HOST;
Jean-Jacques Hiblot3e6ab732019-09-11 11:33:53 +0200920 else if (!IS_ENABLED(CONFIG_USB_HOST))
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530921 dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
922
923 if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
924 dwc->dr_mode = USB_DR_MODE_OTG;
925
926 ret = dwc3_core_init(dwc);
927 if (ret) {
Sean Andersondf5eabc2020-09-15 10:45:16 -0400928 dev_err(dwc->dev, "failed to initialize core\n");
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530929 goto err0;
930 }
931
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530932 ret = dwc3_event_buffers_setup(dwc);
933 if (ret) {
934 dev_err(dwc->dev, "failed to setup event buffers\n");
Kishon Vijay Abraham I71744d02015-02-23 18:40:02 +0530935 goto err1;
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530936 }
937
938 ret = dwc3_core_init_mode(dwc);
939 if (ret)
940 goto err2;
941
Kishon Vijay Abraham I793d3472015-02-23 18:40:05 +0530942 list_add_tail(&dwc->list, &dwc3_list);
943
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530944 return 0;
945
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530946err2:
947 dwc3_event_buffers_cleanup(dwc);
948
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530949err1:
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530950 dwc3_core_exit(dwc);
951
952err0:
953 dwc3_free_event_buffers(dwc);
954
955 return ret;
956}
957
Kishon Vijay Abraham I8e1906a2015-02-23 18:40:04 +0530958/**
959 * dwc3_uboot_exit - dwc3 core uboot cleanup code
960 * @index: index of this controller
961 *
962 * Performs cleanup of memory allocated in dwc3_uboot_init and other misc
Kishon Vijay Abraham I793d3472015-02-23 18:40:05 +0530963 * cleanups (equivalent to dwc3_remove in linux). index of _this_ controller
964 * should be passed and should match with the index passed in
965 * dwc3_device during init.
Kishon Vijay Abraham I8e1906a2015-02-23 18:40:04 +0530966 *
967 * Generally called from board file.
968 */
Kishon Vijay Abraham I793d3472015-02-23 18:40:05 +0530969void dwc3_uboot_exit(int index)
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530970{
Kishon Vijay Abraham I793d3472015-02-23 18:40:05 +0530971 struct dwc3 *dwc;
972
973 list_for_each_entry(dwc, &dwc3_list, list) {
974 if (dwc->index != index)
975 continue;
976
977 dwc3_core_exit_mode(dwc);
978 dwc3_event_buffers_cleanup(dwc);
979 dwc3_free_event_buffers(dwc);
980 dwc3_core_exit(dwc);
981 list_del(&dwc->list);
982 kfree(dwc->mem);
983 break;
984 }
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +0530985}
986
Kishon Vijay Abraham I27d3b892015-02-23 18:40:06 +0530987/**
988 * dwc3_uboot_handle_interrupt - handle dwc3 core interrupt
Marek Vasut2caf9742023-09-01 11:50:03 +0200989 * @dev: device of this controller
Kishon Vijay Abraham I27d3b892015-02-23 18:40:06 +0530990 *
991 * Invokes dwc3 gadget interrupts.
992 *
993 * Generally called from board file.
994 */
Marek Vasut2caf9742023-09-01 11:50:03 +0200995void dwc3_uboot_handle_interrupt(struct udevice *dev)
Kishon Vijay Abraham I27d3b892015-02-23 18:40:06 +0530996{
997 struct dwc3 *dwc = NULL;
998
999 list_for_each_entry(dwc, &dwc3_list, list) {
Marek Vasut2caf9742023-09-01 11:50:03 +02001000 if (dwc->dev != dev)
Kishon Vijay Abraham I27d3b892015-02-23 18:40:06 +05301001 continue;
1002
1003 dwc3_gadget_uboot_handle_interrupt(dwc);
1004 break;
1005 }
1006}
1007
Kishon Vijay Abraham I85d5e702015-02-23 18:39:50 +05301008MODULE_ALIAS("platform:dwc3");
1009MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
1010MODULE_LICENSE("GPL v2");
1011MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
Mugunthan V N23ba2d62018-05-18 13:15:04 +02001012
Jean-Jacques Hiblotd648a502018-11-29 10:52:45 +01001013#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB)
Chunfeng Yun6dfb8a82020-05-02 11:35:13 +02001014int dwc3_setup_phy(struct udevice *dev, struct phy_bulk *phys)
Jean-Jacques Hiblotd648a502018-11-29 10:52:45 +01001015{
Chunfeng Yun6dfb8a82020-05-02 11:35:13 +02001016 int ret;
Jean-Jacques Hiblotd648a502018-11-29 10:52:45 +01001017
Chunfeng Yun6dfb8a82020-05-02 11:35:13 +02001018 ret = generic_phy_get_bulk(dev, phys);
1019 if (ret)
1020 return ret;
Jean-Jacques Hiblotd648a502018-11-29 10:52:45 +01001021
Chunfeng Yun6dfb8a82020-05-02 11:35:13 +02001022 ret = generic_phy_init_bulk(phys);
1023 if (ret)
1024 return ret;
Jean-Jacques Hiblotd648a502018-11-29 10:52:45 +01001025
Chunfeng Yun6dfb8a82020-05-02 11:35:13 +02001026 ret = generic_phy_power_on_bulk(phys);
1027 if (ret)
1028 generic_phy_exit_bulk(phys);
Jean-Jacques Hiblotd648a502018-11-29 10:52:45 +01001029
1030 return ret;
1031}
1032
Chunfeng Yun6dfb8a82020-05-02 11:35:13 +02001033int dwc3_shutdown_phy(struct udevice *dev, struct phy_bulk *phys)
Jean-Jacques Hiblotd648a502018-11-29 10:52:45 +01001034{
Chunfeng Yun6dfb8a82020-05-02 11:35:13 +02001035 int ret;
Jean-Jacques Hiblotd648a502018-11-29 10:52:45 +01001036
Chunfeng Yun6dfb8a82020-05-02 11:35:13 +02001037 ret = generic_phy_power_off_bulk(phys);
1038 ret |= generic_phy_exit_bulk(phys);
1039 return ret;
Jean-Jacques Hiblotd648a502018-11-29 10:52:45 +01001040}
1041#endif
1042
Jean-Jacques Hiblotb575e902019-09-11 11:33:50 +02001043#if CONFIG_IS_ENABLED(DM_USB)
Jean-Jacques Hiblotba6c5f72019-09-11 11:33:52 +02001044void dwc3_of_parse(struct dwc3 *dwc)
1045{
1046 const u8 *tmp;
1047 struct udevice *dev = dwc->dev;
1048 u8 lpm_nyet_threshold;
1049 u8 tx_de_emphasis;
1050 u8 hird_threshold;
Michael Wallef150b8d2021-10-15 15:15:22 +02001051 u32 val;
1052 int i;
Jean-Jacques Hiblotba6c5f72019-09-11 11:33:52 +02001053
1054 /* default to highest possible threshold */
1055 lpm_nyet_threshold = 0xff;
1056
1057 /* default to -3.5dB de-emphasis */
1058 tx_de_emphasis = 1;
1059
1060 /*
1061 * default to assert utmi_sleep_n and use maximum allowed HIRD
1062 * threshold value of 0b1100
1063 */
1064 hird_threshold = 12;
1065
Simon Glassf10643c2020-12-19 10:40:14 -07001066 dwc->hsphy_mode = usb_get_phy_mode(dev_ofnode(dev));
Frank Wang64697942020-05-26 11:34:30 +08001067
Jean-Jacques Hiblotba6c5f72019-09-11 11:33:52 +02001068 dwc->has_lpm_erratum = dev_read_bool(dev,
1069 "snps,has-lpm-erratum");
1070 tmp = dev_read_u8_array_ptr(dev, "snps,lpm-nyet-threshold", 1);
1071 if (tmp)
1072 lpm_nyet_threshold = *tmp;
1073
1074 dwc->is_utmi_l1_suspend = dev_read_bool(dev,
1075 "snps,is-utmi-l1-suspend");
1076 tmp = dev_read_u8_array_ptr(dev, "snps,hird-threshold", 1);
1077 if (tmp)
1078 hird_threshold = *tmp;
1079
1080 dwc->disable_scramble_quirk = dev_read_bool(dev,
1081 "snps,disable_scramble_quirk");
1082 dwc->u2exit_lfps_quirk = dev_read_bool(dev,
1083 "snps,u2exit_lfps_quirk");
1084 dwc->u2ss_inp3_quirk = dev_read_bool(dev,
1085 "snps,u2ss_inp3_quirk");
1086 dwc->req_p1p2p3_quirk = dev_read_bool(dev,
1087 "snps,req_p1p2p3_quirk");
1088 dwc->del_p1p2p3_quirk = dev_read_bool(dev,
1089 "snps,del_p1p2p3_quirk");
1090 dwc->del_phy_power_chg_quirk = dev_read_bool(dev,
1091 "snps,del_phy_power_chg_quirk");
1092 dwc->lfps_filter_quirk = dev_read_bool(dev,
1093 "snps,lfps_filter_quirk");
1094 dwc->rx_detect_poll_quirk = dev_read_bool(dev,
1095 "snps,rx_detect_poll_quirk");
1096 dwc->dis_u3_susphy_quirk = dev_read_bool(dev,
1097 "snps,dis_u3_susphy_quirk");
1098 dwc->dis_u2_susphy_quirk = dev_read_bool(dev,
1099 "snps,dis_u2_susphy_quirk");
Jagan Teki73ca0142020-05-06 13:20:25 +05301100 dwc->dis_del_phy_power_chg_quirk = dev_read_bool(dev,
1101 "snps,dis-del-phy-power-chg-quirk");
Jagan Tekidc184132020-05-26 11:33:48 +08001102 dwc->dis_tx_ipgap_linecheck_quirk = dev_read_bool(dev,
1103 "snps,dis-tx-ipgap-linecheck-quirk");
Frank Wang7bb62702020-05-26 11:33:46 +08001104 dwc->dis_enblslpm_quirk = dev_read_bool(dev,
1105 "snps,dis_enblslpm_quirk");
Frank Wangb34f8b52020-05-26 11:33:47 +08001106 dwc->dis_u2_freeclk_exists_quirk = dev_read_bool(dev,
1107 "snps,dis-u2-freeclk-exists-quirk");
Jean-Jacques Hiblotba6c5f72019-09-11 11:33:52 +02001108 dwc->tx_de_emphasis_quirk = dev_read_bool(dev,
1109 "snps,tx_de_emphasis_quirk");
1110 tmp = dev_read_u8_array_ptr(dev, "snps,tx_de_emphasis", 1);
1111 if (tmp)
1112 tx_de_emphasis = *tmp;
1113
1114 dwc->lpm_nyet_threshold = lpm_nyet_threshold;
1115 dwc->tx_de_emphasis = tx_de_emphasis;
1116
1117 dwc->hird_threshold = hird_threshold
1118 | (dwc->is_utmi_l1_suspend << 4);
Michael Walled274cbb2021-10-15 15:15:21 +02001119
1120 dev_read_u32(dev, "snps,quirk-frame-length-adjustment", &dwc->fladj);
Michael Wallef150b8d2021-10-15 15:15:22 +02001121
1122 /*
1123 * Handle property "snps,incr-burst-type-adjustment".
1124 * Get the number of value from this property:
1125 * result <= 0, means this property is not supported.
1126 * result = 1, means INCRx burst mode supported.
1127 * result > 1, means undefined length burst mode supported.
1128 */
1129 dwc->incrx_mode = INCRX_BURST_MODE;
1130 dwc->incrx_size = 0;
1131 for (i = 0; i < 8; i++) {
1132 if (dev_read_u32_index(dev, "snps,incr-burst-type-adjustment",
1133 i, &val))
1134 break;
1135
1136 dwc->incrx_mode = INCRX_UNDEF_LENGTH_BURST_MODE;
1137 dwc->incrx_size = max(dwc->incrx_size, val);
1138 }
Jean-Jacques Hiblotba6c5f72019-09-11 11:33:52 +02001139}
1140
Mugunthan V N23ba2d62018-05-18 13:15:04 +02001141int dwc3_init(struct dwc3 *dwc)
1142{
1143 int ret;
Jagan Tekidc184132020-05-26 11:33:48 +08001144 u32 reg;
Mugunthan V N23ba2d62018-05-18 13:15:04 +02001145
1146 dwc3_cache_hwparams(dwc);
1147
1148 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
1149 if (ret) {
1150 dev_err(dwc->dev, "failed to allocate event buffers\n");
1151 return -ENOMEM;
1152 }
1153
1154 ret = dwc3_core_init(dwc);
1155 if (ret) {
Sean Andersondf5eabc2020-09-15 10:45:16 -04001156 dev_err(dwc->dev, "failed to initialize core\n");
Mugunthan V N23ba2d62018-05-18 13:15:04 +02001157 goto core_fail;
1158 }
1159
1160 ret = dwc3_event_buffers_setup(dwc);
1161 if (ret) {
1162 dev_err(dwc->dev, "failed to setup event buffers\n");
1163 goto event_fail;
1164 }
1165
Jagan Tekidc184132020-05-26 11:33:48 +08001166 if (dwc->revision >= DWC3_REVISION_250A) {
1167 reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
1168
1169 /*
1170 * Enable hardware control of sending remote wakeup
1171 * in HS when the device is in the L1 state.
1172 */
1173 if (dwc->revision >= DWC3_REVISION_290A)
1174 reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
1175
1176 if (dwc->dis_tx_ipgap_linecheck_quirk)
1177 reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
1178
1179 dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
1180 }
1181
Jagan Tekifafaa022020-05-26 11:34:29 +08001182 if (dwc->dr_mode == USB_DR_MODE_HOST ||
1183 dwc->dr_mode == USB_DR_MODE_OTG) {
1184 reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
1185
1186 reg |= DWC3_GUCTL_HSTINAUTORETRY;
1187
1188 dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
1189 }
1190
Mugunthan V N23ba2d62018-05-18 13:15:04 +02001191 ret = dwc3_core_init_mode(dwc);
1192 if (ret)
1193 goto mode_fail;
1194
1195 return 0;
1196
1197mode_fail:
1198 dwc3_event_buffers_cleanup(dwc);
1199
1200event_fail:
1201 dwc3_core_exit(dwc);
1202
1203core_fail:
1204 dwc3_free_event_buffers(dwc);
1205
1206 return ret;
1207}
1208
1209void dwc3_remove(struct dwc3 *dwc)
1210{
1211 dwc3_core_exit_mode(dwc);
1212 dwc3_event_buffers_cleanup(dwc);
1213 dwc3_free_event_buffers(dwc);
Angus Ainsliefb146fb2022-02-02 15:08:55 -08001214 dwc3_core_stop(dwc);
Mugunthan V N23ba2d62018-05-18 13:15:04 +02001215 dwc3_core_exit(dwc);
1216 kfree(dwc->mem);
1217}
Mugunthan V N23ba2d62018-05-18 13:15:04 +02001218#endif