blob: 6e0876d2c4590722acadc9903b5683d955b91212 [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 *
Kishon Vijay Abraham Id1e431a2015-02-23 18:39:52 +05305 * Copyright (C) 2015 Texas Instruments Incorporated - http://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>
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
Sean Anderson27ef4e62022-11-27 15:31:55 +010041#define NSEC_PER_SEC 1000000000L
42
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +053043static LIST_HEAD(dwc3_list);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053044/* -------------------------------------------------------------------------- */
45
Joonyoung Shimbf35c602015-03-03 17:32:09 +010046static void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
Kishon Vijay Abraham I1530fe32015-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 I1530fe32015-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 I1530fe32015-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 Walle679f13c2021-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 I1530fe32015-02-23 18:39:50 +0530122/**
Balaji Prakash J840d2192022-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 Andersonf6785a82022-11-27 15:31:54 +0100133 unsigned long period;
Sean Anderson27ef4e62022-11-27 15:31:55 +0100134 unsigned long fladj;
135 unsigned long decr;
Sean Andersonf6785a82022-11-27 15:31:54 +0100136 unsigned long rate;
Balaji Prakash J840d2192022-11-27 15:31:53 +0100137 u32 reg;
138
Sean Andersonf6785a82022-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;
144 } else if (dwc->ref_clk_per) {
145 period = dwc->ref_clk_per;
Sean Anderson27ef4e62022-11-27 15:31:55 +0100146 rate = NSEC_PER_SEC / period;
Sean Andersonf6785a82022-11-27 15:31:54 +0100147 } else {
Balaji Prakash J840d2192022-11-27 15:31:53 +0100148 return;
Sean Andersonf6785a82022-11-27 15:31:54 +0100149 }
Balaji Prakash J840d2192022-11-27 15:31:53 +0100150
151 reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
152 reg &= ~DWC3_GUCTL_REFCLKPER_MASK;
Sean Andersonf6785a82022-11-27 15:31:54 +0100153 reg |= FIELD_PREP(DWC3_GUCTL_REFCLKPER_MASK, period);
Balaji Prakash J840d2192022-11-27 15:31:53 +0100154 dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
Sean Anderson27ef4e62022-11-27 15:31:55 +0100155
156 if (dwc->revision <= DWC3_REVISION_250A)
157 return;
158
159 /*
160 * The calculation below is
161 *
162 * 125000 * (NSEC_PER_SEC / (rate * period) - 1)
163 *
164 * but rearranged for fixed-point arithmetic. The division must be
165 * 64-bit because 125000 * NSEC_PER_SEC doesn't fit in 32 bits (and
166 * neither does rate * period).
167 *
168 * Note that rate * period ~= NSEC_PER_SECOND, minus the number of
169 * nanoseconds of error caused by the truncation which happened during
170 * the division when calculating rate or period (whichever one was
171 * derived from the other). We first calculate the relative error, then
172 * scale it to units of 8 ppm.
173 */
174 fladj = div64_u64(125000ULL * NSEC_PER_SEC, (u64)rate * period);
175 fladj -= 125000;
176
177 /*
178 * The documented 240MHz constant is scaled by 2 to get PLS1 as well.
179 */
180 decr = 480000000 / rate;
181
182 reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
183 reg &= ~DWC3_GFLADJ_REFCLK_FLADJ_MASK
184 & ~DWC3_GFLADJ_240MHZDECR
185 & ~DWC3_GFLADJ_240MHZDECR_PLS1;
186 reg |= FIELD_PREP(DWC3_GFLADJ_REFCLK_FLADJ_MASK, fladj)
187 | FIELD_PREP(DWC3_GFLADJ_240MHZDECR, decr >> 1)
188 | FIELD_PREP(DWC3_GFLADJ_240MHZDECR_PLS1, decr & 1);
189 dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
Balaji Prakash J840d2192022-11-27 15:31:53 +0100190}
191
192/**
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530193 * dwc3_free_one_event_buffer - Frees one event buffer
194 * @dwc: Pointer to our controller context structure
195 * @evt: Pointer to event buffer to be freed
196 */
197static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
198 struct dwc3_event_buffer *evt)
199{
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530200 dma_free_coherent(evt->buf);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530201}
202
203/**
204 * dwc3_alloc_one_event_buffer - Allocates one event buffer structure
205 * @dwc: Pointer to our controller context structure
206 * @length: size of the event buffer
207 *
208 * Returns a pointer to the allocated event buffer structure on success
209 * otherwise ERR_PTR(errno).
210 */
211static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
212 unsigned length)
213{
214 struct dwc3_event_buffer *evt;
215
Mugunthan V N121f93c2018-05-18 13:10:27 +0200216 evt = devm_kzalloc((struct udevice *)dwc->dev, sizeof(*evt),
217 GFP_KERNEL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530218 if (!evt)
219 return ERR_PTR(-ENOMEM);
220
221 evt->dwc = dwc;
222 evt->length = length;
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530223 evt->buf = dma_alloc_coherent(length,
224 (unsigned long *)&evt->dma);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530225 if (!evt->buf)
226 return ERR_PTR(-ENOMEM);
227
Philipp Tomsich8e17c162017-04-06 16:58:53 +0200228 dwc3_flush_cache((uintptr_t)evt->buf, evt->length);
229
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530230 return evt;
231}
232
233/**
234 * dwc3_free_event_buffers - frees all allocated event buffers
235 * @dwc: Pointer to our controller context structure
236 */
237static void dwc3_free_event_buffers(struct dwc3 *dwc)
238{
239 struct dwc3_event_buffer *evt;
240 int i;
241
242 for (i = 0; i < dwc->num_event_buffers; i++) {
243 evt = dwc->ev_buffs[i];
244 if (evt)
245 dwc3_free_one_event_buffer(dwc, evt);
246 }
247}
248
249/**
250 * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length
251 * @dwc: pointer to our controller context structure
252 * @length: size of event buffer
253 *
254 * Returns 0 on success otherwise negative errno. In the error case, dwc
255 * may contain some buffers allocated but not all which were requested.
256 */
257static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
258{
259 int num;
260 int i;
261
262 num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
263 dwc->num_event_buffers = num;
264
Kishon Vijay Abraham Ic7bdfe32015-02-23 18:40:13 +0530265 dwc->ev_buffs = memalign(CONFIG_SYS_CACHELINE_SIZE,
266 sizeof(*dwc->ev_buffs) * num);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530267 if (!dwc->ev_buffs)
268 return -ENOMEM;
269
270 for (i = 0; i < num; i++) {
271 struct dwc3_event_buffer *evt;
272
273 evt = dwc3_alloc_one_event_buffer(dwc, length);
274 if (IS_ERR(evt)) {
275 dev_err(dwc->dev, "can't allocate event buffer\n");
276 return PTR_ERR(evt);
277 }
278 dwc->ev_buffs[i] = evt;
279 }
280
281 return 0;
282}
283
284/**
285 * dwc3_event_buffers_setup - setup our allocated event buffers
286 * @dwc: pointer to our controller context structure
287 *
288 * Returns 0 on success otherwise negative errno.
289 */
290static int dwc3_event_buffers_setup(struct dwc3 *dwc)
291{
292 struct dwc3_event_buffer *evt;
293 int n;
294
295 for (n = 0; n < dwc->num_event_buffers; n++) {
296 evt = dwc->ev_buffs[n];
297 dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n",
298 evt->buf, (unsigned long long) evt->dma,
299 evt->length);
300
301 evt->lpos = 0;
302
303 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
304 lower_32_bits(evt->dma));
305 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
306 upper_32_bits(evt->dma));
307 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
308 DWC3_GEVNTSIZ_SIZE(evt->length));
309 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
310 }
311
312 return 0;
313}
314
315static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
316{
317 struct dwc3_event_buffer *evt;
318 int n;
319
320 for (n = 0; n < dwc->num_event_buffers; n++) {
321 evt = dwc->ev_buffs[n];
322
323 evt->lpos = 0;
324
325 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
326 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
327 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK
328 | DWC3_GEVNTSIZ_SIZE(0));
329 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
330 }
331}
332
333static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
334{
335 if (!dwc->has_hibernation)
336 return 0;
337
338 if (!dwc->nr_scratch)
339 return 0;
340
341 dwc->scratchbuf = kmalloc_array(dwc->nr_scratch,
342 DWC3_SCRATCHBUF_SIZE, GFP_KERNEL);
343 if (!dwc->scratchbuf)
344 return -ENOMEM;
345
346 return 0;
347}
348
349static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
350{
351 dma_addr_t scratch_addr;
352 u32 param;
353 int ret;
354
355 if (!dwc->has_hibernation)
356 return 0;
357
358 if (!dwc->nr_scratch)
359 return 0;
360
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530361 scratch_addr = dma_map_single(dwc->scratchbuf,
362 dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
363 DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530364 if (dma_mapping_error(dwc->dev, scratch_addr)) {
365 dev_err(dwc->dev, "failed to map scratch buffer\n");
366 ret = -EFAULT;
367 goto err0;
368 }
369
370 dwc->scratch_addr = scratch_addr;
371
372 param = lower_32_bits(scratch_addr);
373
374 ret = dwc3_send_gadget_generic_command(dwc,
375 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param);
376 if (ret < 0)
377 goto err1;
378
379 param = upper_32_bits(scratch_addr);
380
381 ret = dwc3_send_gadget_generic_command(dwc,
382 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param);
383 if (ret < 0)
384 goto err1;
385
386 return 0;
387
388err1:
Masahiro Yamada05a5dba2020-02-14 16:40:18 +0900389 dma_unmap_single(scratch_addr, dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
390 DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530391
392err0:
393 return ret;
394}
395
396static void dwc3_free_scratch_buffers(struct dwc3 *dwc)
397{
398 if (!dwc->has_hibernation)
399 return;
400
401 if (!dwc->nr_scratch)
402 return;
403
Masahiro Yamada05a5dba2020-02-14 16:40:18 +0900404 dma_unmap_single(dwc->scratch_addr, dwc->nr_scratch *
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530405 DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530406 kfree(dwc->scratchbuf);
407}
408
409static void dwc3_core_num_eps(struct dwc3 *dwc)
410{
411 struct dwc3_hwparams *parms = &dwc->hwparams;
412
413 dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
414 dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
415
416 dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
417 dwc->num_in_eps, dwc->num_out_eps);
418}
419
420static void dwc3_cache_hwparams(struct dwc3 *dwc)
421{
422 struct dwc3_hwparams *parms = &dwc->hwparams;
423
424 parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
425 parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
426 parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
427 parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
428 parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
429 parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
430 parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
431 parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
432 parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
433}
434
Frank Wanga4a29122020-05-26 11:34:30 +0800435static void dwc3_hsphy_mode_setup(struct dwc3 *dwc)
436{
437 enum usb_phy_interface hsphy_mode = dwc->hsphy_mode;
438 u32 reg;
439
440 /* Set dwc3 usb2 phy config */
441 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
442
443 switch (hsphy_mode) {
444 case USBPHY_INTERFACE_MODE_UTMI:
445 reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
446 DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
447 reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) |
448 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT);
449 break;
450 case USBPHY_INTERFACE_MODE_UTMIW:
451 reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
452 DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
453 reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) |
454 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT);
455 break;
456 default:
457 break;
458 }
459
460 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
461}
462
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530463/**
464 * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
465 * @dwc: Pointer to our controller context structure
466 */
467static void dwc3_phy_setup(struct dwc3 *dwc)
468{
469 u32 reg;
470
471 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
472
473 /*
474 * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
475 * to '0' during coreConsultant configuration. So default value
476 * will be '0' when the core is reset. Application needs to set it
477 * to '1' after the core initialization is completed.
478 */
479 if (dwc->revision > DWC3_REVISION_194A)
480 reg |= DWC3_GUSB3PIPECTL_SUSPHY;
481
482 if (dwc->u2ss_inp3_quirk)
483 reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
484
485 if (dwc->req_p1p2p3_quirk)
486 reg |= DWC3_GUSB3PIPECTL_REQP1P2P3;
487
488 if (dwc->del_p1p2p3_quirk)
489 reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN;
490
491 if (dwc->del_phy_power_chg_quirk)
492 reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE;
493
494 if (dwc->lfps_filter_quirk)
495 reg |= DWC3_GUSB3PIPECTL_LFPSFILT;
496
497 if (dwc->rx_detect_poll_quirk)
498 reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL;
499
500 if (dwc->tx_de_emphasis_quirk)
501 reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
502
503 if (dwc->dis_u3_susphy_quirk)
504 reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
505
Jagan Tekic1157dc2020-05-06 13:20:25 +0530506 if (dwc->dis_del_phy_power_chg_quirk)
507 reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
508
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530509 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
510
Frank Wanga4a29122020-05-26 11:34:30 +0800511 dwc3_hsphy_mode_setup(dwc);
512
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530513 mdelay(100);
514
515 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
516
517 /*
518 * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
519 * '0' during coreConsultant configuration. So default value will
520 * be '0' when the core is reset. Application needs to set it to
521 * '1' after the core initialization is completed.
522 */
523 if (dwc->revision > DWC3_REVISION_194A)
524 reg |= DWC3_GUSB2PHYCFG_SUSPHY;
525
526 if (dwc->dis_u2_susphy_quirk)
527 reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
528
Frank Wang0c3b6f52020-05-26 11:33:46 +0800529 if (dwc->dis_enblslpm_quirk)
530 reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
531
Frank Wangb29bcd72020-05-26 11:33:47 +0800532 if (dwc->dis_u2_freeclk_exists_quirk)
533 reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS;
534
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530535 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
536
537 mdelay(100);
538}
539
Michael Walle668bdf62021-10-15 15:15:22 +0200540/* set global incr burst type configuration registers */
541static void dwc3_set_incr_burst_type(struct dwc3 *dwc)
542{
543 struct udevice *dev = dwc->dev;
544 u32 cfg;
545
546 if (!dwc->incrx_size)
547 return;
548
549 cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0);
550
551 /* Enable Undefined Length INCR Burst and Enable INCRx Burst */
552 cfg &= ~DWC3_GSBUSCFG0_INCRBRST_MASK;
553 if (dwc->incrx_mode)
554 cfg |= DWC3_GSBUSCFG0_INCRBRSTENA;
555 switch (dwc->incrx_size) {
556 case 256:
557 cfg |= DWC3_GSBUSCFG0_INCR256BRSTENA;
558 break;
559 case 128:
560 cfg |= DWC3_GSBUSCFG0_INCR128BRSTENA;
561 break;
562 case 64:
563 cfg |= DWC3_GSBUSCFG0_INCR64BRSTENA;
564 break;
565 case 32:
566 cfg |= DWC3_GSBUSCFG0_INCR32BRSTENA;
567 break;
568 case 16:
569 cfg |= DWC3_GSBUSCFG0_INCR16BRSTENA;
570 break;
571 case 8:
572 cfg |= DWC3_GSBUSCFG0_INCR8BRSTENA;
573 break;
574 case 4:
575 cfg |= DWC3_GSBUSCFG0_INCR4BRSTENA;
576 break;
577 case 1:
578 break;
579 default:
580 dev_err(dev, "Invalid property\n");
581 break;
582 }
583
584 dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg);
585}
586
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530587/**
588 * dwc3_core_init - Low-level initialization of DWC3 Core
589 * @dwc: Pointer to our controller context structure
590 *
591 * Returns 0 on success otherwise negative errno.
592 */
593static int dwc3_core_init(struct dwc3 *dwc)
594{
595 unsigned long timeout;
596 u32 hwparams4 = dwc->hwparams.hwparams4;
597 u32 reg;
598 int ret;
599
600 reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
601 /* This should read as U3 followed by revision number */
602 if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
603 dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
604 ret = -ENODEV;
605 goto err0;
606 }
607 dwc->revision = reg;
608
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530609 /* Handle USB2.0-only core configuration */
610 if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
611 DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
612 if (dwc->maximum_speed == USB_SPEED_SUPER)
613 dwc->maximum_speed = USB_SPEED_HIGH;
614 }
615
616 /* issue device SoftReset too */
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530617 timeout = 5000;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530618 dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530619 while (timeout--) {
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530620 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
621 if (!(reg & DWC3_DCTL_CSFTRST))
622 break;
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530623 };
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530624
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530625 if (!timeout) {
626 dev_err(dwc->dev, "Reset Timed Out\n");
627 ret = -ETIMEDOUT;
628 goto err0;
629 }
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530630
T Karthik Reddy7bb245a2019-05-01 10:14:49 +0530631 dwc3_phy_setup(dwc);
632
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530633 ret = dwc3_core_soft_reset(dwc);
634 if (ret)
635 goto err0;
636
637 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
638 reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
639
640 switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
641 case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
642 /**
643 * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
644 * issue which would cause xHCI compliance tests to fail.
645 *
646 * Because of that we cannot enable clock gating on such
647 * configurations.
648 *
649 * Refers to:
650 *
651 * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based
652 * SOF/ITP Mode Used
653 */
654 if ((dwc->dr_mode == USB_DR_MODE_HOST ||
655 dwc->dr_mode == USB_DR_MODE_OTG) &&
656 (dwc->revision >= DWC3_REVISION_210A &&
657 dwc->revision <= DWC3_REVISION_250A))
658 reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
659 else
660 reg &= ~DWC3_GCTL_DSBLCLKGTNG;
661 break;
662 case DWC3_GHWPARAMS1_EN_PWROPT_HIB:
663 /* enable hibernation here */
664 dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4);
665
666 /*
667 * REVISIT Enabling this bit so that host-mode hibernation
668 * will work. Device-mode hibernation is not yet implemented.
669 */
670 reg |= DWC3_GCTL_GBLHIBERNATIONEN;
671 break;
672 default:
673 dev_dbg(dwc->dev, "No power optimization available\n");
674 }
675
676 /* check if current dwc3 is on simulation board */
677 if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
678 dev_dbg(dwc->dev, "it is on FPGA board\n");
679 dwc->is_fpga = true;
680 }
681
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530682 if(dwc->disable_scramble_quirk && !dwc->is_fpga)
683 WARN(true,
684 "disable_scramble cannot be used on non-FPGA builds\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530685
686 if (dwc->disable_scramble_quirk && dwc->is_fpga)
687 reg |= DWC3_GCTL_DISSCRAMBLE;
688 else
689 reg &= ~DWC3_GCTL_DISSCRAMBLE;
690
691 if (dwc->u2exit_lfps_quirk)
692 reg |= DWC3_GCTL_U2EXIT_LFPS;
693
694 /*
695 * WORKAROUND: DWC3 revisions <1.90a have a bug
696 * where the device can fail to connect at SuperSpeed
697 * and falls back to high-speed mode which causes
698 * the device to enter a Connect/Disconnect loop
699 */
700 if (dwc->revision < DWC3_REVISION_190A)
701 reg |= DWC3_GCTL_U2RSTECN;
702
703 dwc3_core_num_eps(dwc);
704
705 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
706
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530707 ret = dwc3_alloc_scratch_buffers(dwc);
708 if (ret)
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530709 goto err0;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530710
711 ret = dwc3_setup_scratch_buffers(dwc);
712 if (ret)
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530713 goto err1;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530714
Michael Walle679f13c2021-10-15 15:15:21 +0200715 /* Adjust Frame Length */
716 dwc3_frame_length_adjustment(dwc, dwc->fladj);
717
Balaji Prakash J840d2192022-11-27 15:31:53 +0100718 /* Adjust Reference Clock Period */
719 dwc3_ref_clk_period(dwc);
720
Michael Walle668bdf62021-10-15 15:15:22 +0200721 dwc3_set_incr_burst_type(dwc);
722
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530723 return 0;
724
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530725err1:
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530726 dwc3_free_scratch_buffers(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530727
728err0:
729 return ret;
730}
731
732static void dwc3_core_exit(struct dwc3 *dwc)
733{
734 dwc3_free_scratch_buffers(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530735}
736
737static int dwc3_core_init_mode(struct dwc3 *dwc)
738{
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530739 int ret;
740
741 switch (dwc->dr_mode) {
742 case USB_DR_MODE_PERIPHERAL:
743 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
744 ret = dwc3_gadget_init(dwc);
745 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400746 dev_err(dwc->dev, "failed to initialize gadget\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530747 return ret;
748 }
749 break;
750 case USB_DR_MODE_HOST:
751 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
752 ret = dwc3_host_init(dwc);
753 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400754 dev_err(dwc->dev, "failed to initialize host\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530755 return ret;
756 }
757 break;
758 case USB_DR_MODE_OTG:
759 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
760 ret = dwc3_host_init(dwc);
761 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400762 dev_err(dwc->dev, "failed to initialize host\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530763 return ret;
764 }
765
766 ret = dwc3_gadget_init(dwc);
767 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400768 dev_err(dwc->dev, "failed to initialize gadget\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530769 return ret;
770 }
771 break;
772 default:
Sean Anderson2789ce82020-09-15 10:45:16 -0400773 dev_err(dwc->dev,
774 "Unsupported mode of operation %d\n", dwc->dr_mode);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530775 return -EINVAL;
776 }
777
778 return 0;
779}
780
Jean-Jacques Hiblot73a1b8b2019-09-11 11:33:45 +0200781static void dwc3_gadget_run(struct dwc3 *dwc)
782{
783 dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_RUN_STOP);
784 mdelay(100);
785}
786
Angus Ainslieeefabee2022-02-02 15:08:55 -0800787static void dwc3_core_stop(struct dwc3 *dwc)
788{
789 u32 reg;
790
791 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
792 dwc3_writel(dwc->regs, DWC3_DCTL, reg & ~(DWC3_DCTL_RUN_STOP));
793}
794
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530795static void dwc3_core_exit_mode(struct dwc3 *dwc)
796{
797 switch (dwc->dr_mode) {
798 case USB_DR_MODE_PERIPHERAL:
799 dwc3_gadget_exit(dwc);
800 break;
801 case USB_DR_MODE_HOST:
802 dwc3_host_exit(dwc);
803 break;
804 case USB_DR_MODE_OTG:
805 dwc3_host_exit(dwc);
806 dwc3_gadget_exit(dwc);
807 break;
808 default:
809 /* do nothing */
810 break;
811 }
Jean-Jacques Hiblot73a1b8b2019-09-11 11:33:45 +0200812
813 /*
814 * switch back to peripheral mode
815 * This enables the phy to enter idle and then, if enabled, suspend.
816 */
817 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
818 dwc3_gadget_run(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530819}
820
821#define DWC3_ALIGN_MASK (16 - 1)
822
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530823/**
824 * dwc3_uboot_init - dwc3 core uboot initialization code
825 * @dwc3_dev: struct dwc3_device containing initialization data
826 *
827 * Entry point for dwc3 driver (equivalent to dwc3_probe in linux
828 * kernel driver). Pointer to dwc3_device should be passed containing
829 * base address and other initialization data. Returns '0' on success and
830 * a negative value on failure.
831 *
832 * Generally called from board_usb_init() implemented in board file.
833 */
834int dwc3_uboot_init(struct dwc3_device *dwc3_dev)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530835{
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530836 struct dwc3 *dwc;
Felipe Balbi424305f2015-10-01 14:22:18 -0500837 struct device *dev = NULL;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530838 u8 lpm_nyet_threshold;
839 u8 tx_de_emphasis;
840 u8 hird_threshold;
841
842 int ret;
843
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530844 void *mem;
845
Mugunthan V N121f93c2018-05-18 13:10:27 +0200846 mem = devm_kzalloc((struct udevice *)dev,
847 sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530848 if (!mem)
849 return -ENOMEM;
850
851 dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
852 dwc->mem = mem;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530853
Michal Simek698cd6f2015-10-30 16:24:06 +0100854 dwc->regs = (void *)(uintptr_t)(dwc3_dev->base +
855 DWC3_GLOBALS_REGS_START);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530856
857 /* default to highest possible threshold */
858 lpm_nyet_threshold = 0xff;
859
860 /* default to -3.5dB de-emphasis */
861 tx_de_emphasis = 1;
862
863 /*
864 * default to assert utmi_sleep_n and use maximum allowed HIRD
865 * threshold value of 0b1100
866 */
867 hird_threshold = 12;
868
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530869 dwc->maximum_speed = dwc3_dev->maximum_speed;
870 dwc->has_lpm_erratum = dwc3_dev->has_lpm_erratum;
871 if (dwc3_dev->lpm_nyet_threshold)
872 lpm_nyet_threshold = dwc3_dev->lpm_nyet_threshold;
873 dwc->is_utmi_l1_suspend = dwc3_dev->is_utmi_l1_suspend;
874 if (dwc3_dev->hird_threshold)
875 hird_threshold = dwc3_dev->hird_threshold;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530876
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530877 dwc->needs_fifo_resize = dwc3_dev->tx_fifo_resize;
878 dwc->dr_mode = dwc3_dev->dr_mode;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530879
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530880 dwc->disable_scramble_quirk = dwc3_dev->disable_scramble_quirk;
881 dwc->u2exit_lfps_quirk = dwc3_dev->u2exit_lfps_quirk;
882 dwc->u2ss_inp3_quirk = dwc3_dev->u2ss_inp3_quirk;
883 dwc->req_p1p2p3_quirk = dwc3_dev->req_p1p2p3_quirk;
884 dwc->del_p1p2p3_quirk = dwc3_dev->del_p1p2p3_quirk;
885 dwc->del_phy_power_chg_quirk = dwc3_dev->del_phy_power_chg_quirk;
886 dwc->lfps_filter_quirk = dwc3_dev->lfps_filter_quirk;
887 dwc->rx_detect_poll_quirk = dwc3_dev->rx_detect_poll_quirk;
888 dwc->dis_u3_susphy_quirk = dwc3_dev->dis_u3_susphy_quirk;
889 dwc->dis_u2_susphy_quirk = dwc3_dev->dis_u2_susphy_quirk;
Jagan Tekic1157dc2020-05-06 13:20:25 +0530890 dwc->dis_del_phy_power_chg_quirk = dwc3_dev->dis_del_phy_power_chg_quirk;
Jagan Teki0ece2f72020-05-26 11:33:48 +0800891 dwc->dis_tx_ipgap_linecheck_quirk = dwc3_dev->dis_tx_ipgap_linecheck_quirk;
Frank Wang0c3b6f52020-05-26 11:33:46 +0800892 dwc->dis_enblslpm_quirk = dwc3_dev->dis_enblslpm_quirk;
Frank Wangb29bcd72020-05-26 11:33:47 +0800893 dwc->dis_u2_freeclk_exists_quirk = dwc3_dev->dis_u2_freeclk_exists_quirk;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530894
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530895 dwc->tx_de_emphasis_quirk = dwc3_dev->tx_de_emphasis_quirk;
896 if (dwc3_dev->tx_de_emphasis)
897 tx_de_emphasis = dwc3_dev->tx_de_emphasis;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530898
899 /* default to superspeed if no maximum_speed passed */
900 if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
901 dwc->maximum_speed = USB_SPEED_SUPER;
902
903 dwc->lpm_nyet_threshold = lpm_nyet_threshold;
904 dwc->tx_de_emphasis = tx_de_emphasis;
905
906 dwc->hird_threshold = hird_threshold
907 | (dwc->is_utmi_l1_suspend << 4);
908
Frank Wanga4a29122020-05-26 11:34:30 +0800909 dwc->hsphy_mode = dwc3_dev->hsphy_mode;
910
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530911 dwc->index = dwc3_dev->index;
912
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530913 dwc3_cache_hwparams(dwc);
914
915 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
916 if (ret) {
917 dev_err(dwc->dev, "failed to allocate event buffers\n");
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530918 return -ENOMEM;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530919 }
920
Jean-Jacques Hiblot731a2a32019-09-11 11:33:53 +0200921 if (!IS_ENABLED(CONFIG_USB_DWC3_GADGET))
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530922 dwc->dr_mode = USB_DR_MODE_HOST;
Jean-Jacques Hiblot731a2a32019-09-11 11:33:53 +0200923 else if (!IS_ENABLED(CONFIG_USB_HOST))
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530924 dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
925
926 if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
927 dwc->dr_mode = USB_DR_MODE_OTG;
928
929 ret = dwc3_core_init(dwc);
930 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400931 dev_err(dwc->dev, "failed to initialize core\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530932 goto err0;
933 }
934
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530935 ret = dwc3_event_buffers_setup(dwc);
936 if (ret) {
937 dev_err(dwc->dev, "failed to setup event buffers\n");
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530938 goto err1;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530939 }
940
941 ret = dwc3_core_init_mode(dwc);
942 if (ret)
943 goto err2;
944
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530945 list_add_tail(&dwc->list, &dwc3_list);
946
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530947 return 0;
948
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530949err2:
950 dwc3_event_buffers_cleanup(dwc);
951
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530952err1:
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530953 dwc3_core_exit(dwc);
954
955err0:
956 dwc3_free_event_buffers(dwc);
957
958 return ret;
959}
960
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530961/**
962 * dwc3_uboot_exit - dwc3 core uboot cleanup code
963 * @index: index of this controller
964 *
965 * Performs cleanup of memory allocated in dwc3_uboot_init and other misc
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530966 * cleanups (equivalent to dwc3_remove in linux). index of _this_ controller
967 * should be passed and should match with the index passed in
968 * dwc3_device during init.
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530969 *
970 * Generally called from board file.
971 */
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530972void dwc3_uboot_exit(int index)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530973{
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530974 struct dwc3 *dwc;
975
976 list_for_each_entry(dwc, &dwc3_list, list) {
977 if (dwc->index != index)
978 continue;
979
980 dwc3_core_exit_mode(dwc);
981 dwc3_event_buffers_cleanup(dwc);
982 dwc3_free_event_buffers(dwc);
983 dwc3_core_exit(dwc);
984 list_del(&dwc->list);
985 kfree(dwc->mem);
986 break;
987 }
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530988}
989
Kishon Vijay Abraham I1cee7b12015-02-23 18:40:06 +0530990/**
991 * dwc3_uboot_handle_interrupt - handle dwc3 core interrupt
992 * @index: index of this controller
993 *
994 * Invokes dwc3 gadget interrupts.
995 *
996 * Generally called from board file.
997 */
998void dwc3_uboot_handle_interrupt(int index)
999{
1000 struct dwc3 *dwc = NULL;
1001
1002 list_for_each_entry(dwc, &dwc3_list, list) {
1003 if (dwc->index != index)
1004 continue;
1005
1006 dwc3_gadget_uboot_handle_interrupt(dwc);
1007 break;
1008 }
1009}
1010
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +05301011MODULE_ALIAS("platform:dwc3");
1012MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
1013MODULE_LICENSE("GPL v2");
1014MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001015
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001016#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB)
developerf8bced12020-05-02 11:35:13 +02001017int dwc3_setup_phy(struct udevice *dev, struct phy_bulk *phys)
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001018{
developerf8bced12020-05-02 11:35:13 +02001019 int ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001020
developerf8bced12020-05-02 11:35:13 +02001021 ret = generic_phy_get_bulk(dev, phys);
1022 if (ret)
1023 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001024
developerf8bced12020-05-02 11:35:13 +02001025 ret = generic_phy_init_bulk(phys);
1026 if (ret)
1027 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001028
developerf8bced12020-05-02 11:35:13 +02001029 ret = generic_phy_power_on_bulk(phys);
1030 if (ret)
1031 generic_phy_exit_bulk(phys);
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001032
1033 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001034}
1035
developerf8bced12020-05-02 11:35:13 +02001036int dwc3_shutdown_phy(struct udevice *dev, struct phy_bulk *phys)
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001037{
developerf8bced12020-05-02 11:35:13 +02001038 int ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001039
developerf8bced12020-05-02 11:35:13 +02001040 ret = generic_phy_power_off_bulk(phys);
1041 ret |= generic_phy_exit_bulk(phys);
1042 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001043}
1044#endif
1045
Jean-Jacques Hiblot175cd7c2019-09-11 11:33:50 +02001046#if CONFIG_IS_ENABLED(DM_USB)
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001047void dwc3_of_parse(struct dwc3 *dwc)
1048{
1049 const u8 *tmp;
1050 struct udevice *dev = dwc->dev;
1051 u8 lpm_nyet_threshold;
1052 u8 tx_de_emphasis;
1053 u8 hird_threshold;
Michael Walle668bdf62021-10-15 15:15:22 +02001054 u32 val;
1055 int i;
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001056
1057 /* default to highest possible threshold */
1058 lpm_nyet_threshold = 0xff;
1059
1060 /* default to -3.5dB de-emphasis */
1061 tx_de_emphasis = 1;
1062
1063 /*
1064 * default to assert utmi_sleep_n and use maximum allowed HIRD
1065 * threshold value of 0b1100
1066 */
1067 hird_threshold = 12;
1068
Simon Glassa7ece582020-12-19 10:40:14 -07001069 dwc->hsphy_mode = usb_get_phy_mode(dev_ofnode(dev));
Frank Wanga4a29122020-05-26 11:34:30 +08001070
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001071 dwc->has_lpm_erratum = dev_read_bool(dev,
1072 "snps,has-lpm-erratum");
1073 tmp = dev_read_u8_array_ptr(dev, "snps,lpm-nyet-threshold", 1);
1074 if (tmp)
1075 lpm_nyet_threshold = *tmp;
1076
1077 dwc->is_utmi_l1_suspend = dev_read_bool(dev,
1078 "snps,is-utmi-l1-suspend");
1079 tmp = dev_read_u8_array_ptr(dev, "snps,hird-threshold", 1);
1080 if (tmp)
1081 hird_threshold = *tmp;
1082
1083 dwc->disable_scramble_quirk = dev_read_bool(dev,
1084 "snps,disable_scramble_quirk");
1085 dwc->u2exit_lfps_quirk = dev_read_bool(dev,
1086 "snps,u2exit_lfps_quirk");
1087 dwc->u2ss_inp3_quirk = dev_read_bool(dev,
1088 "snps,u2ss_inp3_quirk");
1089 dwc->req_p1p2p3_quirk = dev_read_bool(dev,
1090 "snps,req_p1p2p3_quirk");
1091 dwc->del_p1p2p3_quirk = dev_read_bool(dev,
1092 "snps,del_p1p2p3_quirk");
1093 dwc->del_phy_power_chg_quirk = dev_read_bool(dev,
1094 "snps,del_phy_power_chg_quirk");
1095 dwc->lfps_filter_quirk = dev_read_bool(dev,
1096 "snps,lfps_filter_quirk");
1097 dwc->rx_detect_poll_quirk = dev_read_bool(dev,
1098 "snps,rx_detect_poll_quirk");
1099 dwc->dis_u3_susphy_quirk = dev_read_bool(dev,
1100 "snps,dis_u3_susphy_quirk");
1101 dwc->dis_u2_susphy_quirk = dev_read_bool(dev,
1102 "snps,dis_u2_susphy_quirk");
Jagan Tekic1157dc2020-05-06 13:20:25 +05301103 dwc->dis_del_phy_power_chg_quirk = dev_read_bool(dev,
1104 "snps,dis-del-phy-power-chg-quirk");
Jagan Teki0ece2f72020-05-26 11:33:48 +08001105 dwc->dis_tx_ipgap_linecheck_quirk = dev_read_bool(dev,
1106 "snps,dis-tx-ipgap-linecheck-quirk");
Frank Wang0c3b6f52020-05-26 11:33:46 +08001107 dwc->dis_enblslpm_quirk = dev_read_bool(dev,
1108 "snps,dis_enblslpm_quirk");
Frank Wangb29bcd72020-05-26 11:33:47 +08001109 dwc->dis_u2_freeclk_exists_quirk = dev_read_bool(dev,
1110 "snps,dis-u2-freeclk-exists-quirk");
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001111 dwc->tx_de_emphasis_quirk = dev_read_bool(dev,
1112 "snps,tx_de_emphasis_quirk");
1113 tmp = dev_read_u8_array_ptr(dev, "snps,tx_de_emphasis", 1);
1114 if (tmp)
1115 tx_de_emphasis = *tmp;
1116
1117 dwc->lpm_nyet_threshold = lpm_nyet_threshold;
1118 dwc->tx_de_emphasis = tx_de_emphasis;
1119
1120 dwc->hird_threshold = hird_threshold
1121 | (dwc->is_utmi_l1_suspend << 4);
Michael Walle679f13c2021-10-15 15:15:21 +02001122
1123 dev_read_u32(dev, "snps,quirk-frame-length-adjustment", &dwc->fladj);
Balaji Prakash J840d2192022-11-27 15:31:53 +01001124 dev_read_u32(dev, "snps,ref-clock-period-ns", &dwc->ref_clk_per);
Michael Walle668bdf62021-10-15 15:15:22 +02001125
1126 /*
1127 * Handle property "snps,incr-burst-type-adjustment".
1128 * Get the number of value from this property:
1129 * result <= 0, means this property is not supported.
1130 * result = 1, means INCRx burst mode supported.
1131 * result > 1, means undefined length burst mode supported.
1132 */
1133 dwc->incrx_mode = INCRX_BURST_MODE;
1134 dwc->incrx_size = 0;
1135 for (i = 0; i < 8; i++) {
1136 if (dev_read_u32_index(dev, "snps,incr-burst-type-adjustment",
1137 i, &val))
1138 break;
1139
1140 dwc->incrx_mode = INCRX_UNDEF_LENGTH_BURST_MODE;
1141 dwc->incrx_size = max(dwc->incrx_size, val);
1142 }
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001143}
1144
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001145int dwc3_init(struct dwc3 *dwc)
1146{
1147 int ret;
Jagan Teki0ece2f72020-05-26 11:33:48 +08001148 u32 reg;
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001149
1150 dwc3_cache_hwparams(dwc);
1151
1152 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
1153 if (ret) {
1154 dev_err(dwc->dev, "failed to allocate event buffers\n");
1155 return -ENOMEM;
1156 }
1157
1158 ret = dwc3_core_init(dwc);
1159 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -04001160 dev_err(dwc->dev, "failed to initialize core\n");
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001161 goto core_fail;
1162 }
1163
1164 ret = dwc3_event_buffers_setup(dwc);
1165 if (ret) {
1166 dev_err(dwc->dev, "failed to setup event buffers\n");
1167 goto event_fail;
1168 }
1169
Jagan Teki0ece2f72020-05-26 11:33:48 +08001170 if (dwc->revision >= DWC3_REVISION_250A) {
1171 reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
1172
1173 /*
1174 * Enable hardware control of sending remote wakeup
1175 * in HS when the device is in the L1 state.
1176 */
1177 if (dwc->revision >= DWC3_REVISION_290A)
1178 reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
1179
1180 if (dwc->dis_tx_ipgap_linecheck_quirk)
1181 reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
1182
1183 dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
1184 }
1185
Jagan Teki461409b2020-05-26 11:34:29 +08001186 if (dwc->dr_mode == USB_DR_MODE_HOST ||
1187 dwc->dr_mode == USB_DR_MODE_OTG) {
1188 reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
1189
1190 reg |= DWC3_GUCTL_HSTINAUTORETRY;
1191
1192 dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
1193 }
1194
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001195 ret = dwc3_core_init_mode(dwc);
1196 if (ret)
1197 goto mode_fail;
1198
1199 return 0;
1200
1201mode_fail:
1202 dwc3_event_buffers_cleanup(dwc);
1203
1204event_fail:
1205 dwc3_core_exit(dwc);
1206
1207core_fail:
1208 dwc3_free_event_buffers(dwc);
1209
1210 return ret;
1211}
1212
1213void dwc3_remove(struct dwc3 *dwc)
1214{
1215 dwc3_core_exit_mode(dwc);
1216 dwc3_event_buffers_cleanup(dwc);
1217 dwc3_free_event_buffers(dwc);
Angus Ainslieeefabee2022-02-02 15:08:55 -08001218 dwc3_core_stop(dwc);
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001219 dwc3_core_exit(dwc);
1220 kfree(dwc->mem);
1221}
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001222#endif