blob: ed5d0d16f78541aad5fda17b26efae13fe55ece2 [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>
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053033
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053034#include "core.h"
35#include "gadget.h"
36#include "io.h"
37
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +053038#include "linux-compat.h"
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053039
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +053040static LIST_HEAD(dwc3_list);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053041/* -------------------------------------------------------------------------- */
42
Joonyoung Shimbf35c602015-03-03 17:32:09 +010043static void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053044{
45 u32 reg;
46
47 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
48 reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
49 reg |= DWC3_GCTL_PRTCAPDIR(mode);
50 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
51}
52
53/**
54 * dwc3_core_soft_reset - Issues core soft reset and PHY reset
55 * @dwc: pointer to our context structure
56 */
57static int dwc3_core_soft_reset(struct dwc3 *dwc)
58{
59 u32 reg;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053060
61 /* Before Resetting PHY, put Core in Reset */
62 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
63 reg |= DWC3_GCTL_CORESOFTRESET;
64 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
65
66 /* Assert USB3 PHY reset */
67 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
68 reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
69 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
70
71 /* Assert USB2 PHY reset */
72 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
73 reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
74 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
75
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053076 mdelay(100);
77
78 /* Clear USB3 PHY reset */
79 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
80 reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
81 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
82
83 /* Clear USB2 PHY reset */
84 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
85 reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
86 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
87
88 mdelay(100);
89
90 /* After PHYs are stable we can take Core out of reset state */
91 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
92 reg &= ~DWC3_GCTL_CORESOFTRESET;
93 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
94
95 return 0;
96}
97
Michael Walle679f13c2021-10-15 15:15:21 +020098/*
99 * dwc3_frame_length_adjustment - Adjusts frame length if required
100 * @dwc3: Pointer to our controller context structure
101 * @fladj: Value of GFLADJ_30MHZ to adjust frame length
102 */
103static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj)
104{
105 u32 reg;
106
107 if (dwc->revision < DWC3_REVISION_250A)
108 return;
109
110 if (fladj == 0)
111 return;
112
113 reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
114 reg &= ~DWC3_GFLADJ_30MHZ_MASK;
115 reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj;
116 dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
117}
118
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530119/**
Balaji Prakash J840d2192022-11-27 15:31:53 +0100120 * dwc3_ref_clk_period - Reference clock period configuration
121 * Default reference clock period depends on hardware
122 * configuration. For systems with reference clock that differs
123 * from the default, this will set clock period in DWC3_GUCTL
124 * register.
125 * @dwc: Pointer to our controller context structure
126 * @ref_clk_per: reference clock period in ns
127 */
128static void dwc3_ref_clk_period(struct dwc3 *dwc)
129{
Sean Andersonf6785a82022-11-27 15:31:54 +0100130 unsigned long period;
131 unsigned long rate;
Balaji Prakash J840d2192022-11-27 15:31:53 +0100132 u32 reg;
133
Sean Andersonf6785a82022-11-27 15:31:54 +0100134 if (dwc->ref_clk) {
135 rate = clk_get_rate(dwc->ref_clk);
136 if (!rate)
137 return;
138 period = NSEC_PER_SEC / rate;
139 } else if (dwc->ref_clk_per) {
140 period = dwc->ref_clk_per;
141 } else {
Balaji Prakash J840d2192022-11-27 15:31:53 +0100142 return;
Sean Andersonf6785a82022-11-27 15:31:54 +0100143 }
Balaji Prakash J840d2192022-11-27 15:31:53 +0100144
145 reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
146 reg &= ~DWC3_GUCTL_REFCLKPER_MASK;
Sean Andersonf6785a82022-11-27 15:31:54 +0100147 reg |= FIELD_PREP(DWC3_GUCTL_REFCLKPER_MASK, period);
Balaji Prakash J840d2192022-11-27 15:31:53 +0100148 dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
149}
150
151/**
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530152 * dwc3_free_one_event_buffer - Frees one event buffer
153 * @dwc: Pointer to our controller context structure
154 * @evt: Pointer to event buffer to be freed
155 */
156static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
157 struct dwc3_event_buffer *evt)
158{
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530159 dma_free_coherent(evt->buf);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530160}
161
162/**
163 * dwc3_alloc_one_event_buffer - Allocates one event buffer structure
164 * @dwc: Pointer to our controller context structure
165 * @length: size of the event buffer
166 *
167 * Returns a pointer to the allocated event buffer structure on success
168 * otherwise ERR_PTR(errno).
169 */
170static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
171 unsigned length)
172{
173 struct dwc3_event_buffer *evt;
174
Mugunthan V N121f93c2018-05-18 13:10:27 +0200175 evt = devm_kzalloc((struct udevice *)dwc->dev, sizeof(*evt),
176 GFP_KERNEL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530177 if (!evt)
178 return ERR_PTR(-ENOMEM);
179
180 evt->dwc = dwc;
181 evt->length = length;
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530182 evt->buf = dma_alloc_coherent(length,
183 (unsigned long *)&evt->dma);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530184 if (!evt->buf)
185 return ERR_PTR(-ENOMEM);
186
Philipp Tomsich8e17c162017-04-06 16:58:53 +0200187 dwc3_flush_cache((uintptr_t)evt->buf, evt->length);
188
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530189 return evt;
190}
191
192/**
193 * dwc3_free_event_buffers - frees all allocated event buffers
194 * @dwc: Pointer to our controller context structure
195 */
196static void dwc3_free_event_buffers(struct dwc3 *dwc)
197{
198 struct dwc3_event_buffer *evt;
199 int i;
200
201 for (i = 0; i < dwc->num_event_buffers; i++) {
202 evt = dwc->ev_buffs[i];
203 if (evt)
204 dwc3_free_one_event_buffer(dwc, evt);
205 }
206}
207
208/**
209 * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length
210 * @dwc: pointer to our controller context structure
211 * @length: size of event buffer
212 *
213 * Returns 0 on success otherwise negative errno. In the error case, dwc
214 * may contain some buffers allocated but not all which were requested.
215 */
216static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
217{
218 int num;
219 int i;
220
221 num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
222 dwc->num_event_buffers = num;
223
Kishon Vijay Abraham Ic7bdfe32015-02-23 18:40:13 +0530224 dwc->ev_buffs = memalign(CONFIG_SYS_CACHELINE_SIZE,
225 sizeof(*dwc->ev_buffs) * num);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530226 if (!dwc->ev_buffs)
227 return -ENOMEM;
228
229 for (i = 0; i < num; i++) {
230 struct dwc3_event_buffer *evt;
231
232 evt = dwc3_alloc_one_event_buffer(dwc, length);
233 if (IS_ERR(evt)) {
234 dev_err(dwc->dev, "can't allocate event buffer\n");
235 return PTR_ERR(evt);
236 }
237 dwc->ev_buffs[i] = evt;
238 }
239
240 return 0;
241}
242
243/**
244 * dwc3_event_buffers_setup - setup our allocated event buffers
245 * @dwc: pointer to our controller context structure
246 *
247 * Returns 0 on success otherwise negative errno.
248 */
249static int dwc3_event_buffers_setup(struct dwc3 *dwc)
250{
251 struct dwc3_event_buffer *evt;
252 int n;
253
254 for (n = 0; n < dwc->num_event_buffers; n++) {
255 evt = dwc->ev_buffs[n];
256 dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n",
257 evt->buf, (unsigned long long) evt->dma,
258 evt->length);
259
260 evt->lpos = 0;
261
262 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
263 lower_32_bits(evt->dma));
264 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
265 upper_32_bits(evt->dma));
266 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
267 DWC3_GEVNTSIZ_SIZE(evt->length));
268 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
269 }
270
271 return 0;
272}
273
274static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
275{
276 struct dwc3_event_buffer *evt;
277 int n;
278
279 for (n = 0; n < dwc->num_event_buffers; n++) {
280 evt = dwc->ev_buffs[n];
281
282 evt->lpos = 0;
283
284 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
285 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
286 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK
287 | DWC3_GEVNTSIZ_SIZE(0));
288 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
289 }
290}
291
292static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
293{
294 if (!dwc->has_hibernation)
295 return 0;
296
297 if (!dwc->nr_scratch)
298 return 0;
299
300 dwc->scratchbuf = kmalloc_array(dwc->nr_scratch,
301 DWC3_SCRATCHBUF_SIZE, GFP_KERNEL);
302 if (!dwc->scratchbuf)
303 return -ENOMEM;
304
305 return 0;
306}
307
308static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
309{
310 dma_addr_t scratch_addr;
311 u32 param;
312 int ret;
313
314 if (!dwc->has_hibernation)
315 return 0;
316
317 if (!dwc->nr_scratch)
318 return 0;
319
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530320 scratch_addr = dma_map_single(dwc->scratchbuf,
321 dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
322 DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530323 if (dma_mapping_error(dwc->dev, scratch_addr)) {
324 dev_err(dwc->dev, "failed to map scratch buffer\n");
325 ret = -EFAULT;
326 goto err0;
327 }
328
329 dwc->scratch_addr = scratch_addr;
330
331 param = lower_32_bits(scratch_addr);
332
333 ret = dwc3_send_gadget_generic_command(dwc,
334 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param);
335 if (ret < 0)
336 goto err1;
337
338 param = upper_32_bits(scratch_addr);
339
340 ret = dwc3_send_gadget_generic_command(dwc,
341 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param);
342 if (ret < 0)
343 goto err1;
344
345 return 0;
346
347err1:
Masahiro Yamada05a5dba2020-02-14 16:40:18 +0900348 dma_unmap_single(scratch_addr, dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
349 DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530350
351err0:
352 return ret;
353}
354
355static void dwc3_free_scratch_buffers(struct dwc3 *dwc)
356{
357 if (!dwc->has_hibernation)
358 return;
359
360 if (!dwc->nr_scratch)
361 return;
362
Masahiro Yamada05a5dba2020-02-14 16:40:18 +0900363 dma_unmap_single(dwc->scratch_addr, dwc->nr_scratch *
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530364 DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530365 kfree(dwc->scratchbuf);
366}
367
368static void dwc3_core_num_eps(struct dwc3 *dwc)
369{
370 struct dwc3_hwparams *parms = &dwc->hwparams;
371
372 dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
373 dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
374
375 dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
376 dwc->num_in_eps, dwc->num_out_eps);
377}
378
379static void dwc3_cache_hwparams(struct dwc3 *dwc)
380{
381 struct dwc3_hwparams *parms = &dwc->hwparams;
382
383 parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
384 parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
385 parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
386 parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
387 parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
388 parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
389 parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
390 parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
391 parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
392}
393
Frank Wanga4a29122020-05-26 11:34:30 +0800394static void dwc3_hsphy_mode_setup(struct dwc3 *dwc)
395{
396 enum usb_phy_interface hsphy_mode = dwc->hsphy_mode;
397 u32 reg;
398
399 /* Set dwc3 usb2 phy config */
400 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
401
402 switch (hsphy_mode) {
403 case USBPHY_INTERFACE_MODE_UTMI:
404 reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
405 DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
406 reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) |
407 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT);
408 break;
409 case USBPHY_INTERFACE_MODE_UTMIW:
410 reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
411 DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
412 reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) |
413 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT);
414 break;
415 default:
416 break;
417 }
418
419 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
420}
421
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530422/**
423 * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
424 * @dwc: Pointer to our controller context structure
425 */
426static void dwc3_phy_setup(struct dwc3 *dwc)
427{
428 u32 reg;
429
430 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
431
432 /*
433 * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
434 * to '0' during coreConsultant configuration. So default value
435 * will be '0' when the core is reset. Application needs to set it
436 * to '1' after the core initialization is completed.
437 */
438 if (dwc->revision > DWC3_REVISION_194A)
439 reg |= DWC3_GUSB3PIPECTL_SUSPHY;
440
441 if (dwc->u2ss_inp3_quirk)
442 reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
443
444 if (dwc->req_p1p2p3_quirk)
445 reg |= DWC3_GUSB3PIPECTL_REQP1P2P3;
446
447 if (dwc->del_p1p2p3_quirk)
448 reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN;
449
450 if (dwc->del_phy_power_chg_quirk)
451 reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE;
452
453 if (dwc->lfps_filter_quirk)
454 reg |= DWC3_GUSB3PIPECTL_LFPSFILT;
455
456 if (dwc->rx_detect_poll_quirk)
457 reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL;
458
459 if (dwc->tx_de_emphasis_quirk)
460 reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
461
462 if (dwc->dis_u3_susphy_quirk)
463 reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
464
Jagan Tekic1157dc2020-05-06 13:20:25 +0530465 if (dwc->dis_del_phy_power_chg_quirk)
466 reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
467
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530468 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
469
Frank Wanga4a29122020-05-26 11:34:30 +0800470 dwc3_hsphy_mode_setup(dwc);
471
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530472 mdelay(100);
473
474 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
475
476 /*
477 * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
478 * '0' during coreConsultant configuration. So default value will
479 * be '0' when the core is reset. Application needs to set it to
480 * '1' after the core initialization is completed.
481 */
482 if (dwc->revision > DWC3_REVISION_194A)
483 reg |= DWC3_GUSB2PHYCFG_SUSPHY;
484
485 if (dwc->dis_u2_susphy_quirk)
486 reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
487
Frank Wang0c3b6f52020-05-26 11:33:46 +0800488 if (dwc->dis_enblslpm_quirk)
489 reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
490
Frank Wangb29bcd72020-05-26 11:33:47 +0800491 if (dwc->dis_u2_freeclk_exists_quirk)
492 reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS;
493
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530494 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
495
496 mdelay(100);
497}
498
Michael Walle668bdf62021-10-15 15:15:22 +0200499/* set global incr burst type configuration registers */
500static void dwc3_set_incr_burst_type(struct dwc3 *dwc)
501{
502 struct udevice *dev = dwc->dev;
503 u32 cfg;
504
505 if (!dwc->incrx_size)
506 return;
507
508 cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0);
509
510 /* Enable Undefined Length INCR Burst and Enable INCRx Burst */
511 cfg &= ~DWC3_GSBUSCFG0_INCRBRST_MASK;
512 if (dwc->incrx_mode)
513 cfg |= DWC3_GSBUSCFG0_INCRBRSTENA;
514 switch (dwc->incrx_size) {
515 case 256:
516 cfg |= DWC3_GSBUSCFG0_INCR256BRSTENA;
517 break;
518 case 128:
519 cfg |= DWC3_GSBUSCFG0_INCR128BRSTENA;
520 break;
521 case 64:
522 cfg |= DWC3_GSBUSCFG0_INCR64BRSTENA;
523 break;
524 case 32:
525 cfg |= DWC3_GSBUSCFG0_INCR32BRSTENA;
526 break;
527 case 16:
528 cfg |= DWC3_GSBUSCFG0_INCR16BRSTENA;
529 break;
530 case 8:
531 cfg |= DWC3_GSBUSCFG0_INCR8BRSTENA;
532 break;
533 case 4:
534 cfg |= DWC3_GSBUSCFG0_INCR4BRSTENA;
535 break;
536 case 1:
537 break;
538 default:
539 dev_err(dev, "Invalid property\n");
540 break;
541 }
542
543 dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg);
544}
545
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530546/**
547 * dwc3_core_init - Low-level initialization of DWC3 Core
548 * @dwc: Pointer to our controller context structure
549 *
550 * Returns 0 on success otherwise negative errno.
551 */
552static int dwc3_core_init(struct dwc3 *dwc)
553{
554 unsigned long timeout;
555 u32 hwparams4 = dwc->hwparams.hwparams4;
556 u32 reg;
557 int ret;
558
559 reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
560 /* This should read as U3 followed by revision number */
561 if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
562 dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
563 ret = -ENODEV;
564 goto err0;
565 }
566 dwc->revision = reg;
567
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530568 /* Handle USB2.0-only core configuration */
569 if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
570 DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
571 if (dwc->maximum_speed == USB_SPEED_SUPER)
572 dwc->maximum_speed = USB_SPEED_HIGH;
573 }
574
575 /* issue device SoftReset too */
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530576 timeout = 5000;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530577 dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530578 while (timeout--) {
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530579 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
580 if (!(reg & DWC3_DCTL_CSFTRST))
581 break;
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530582 };
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530583
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530584 if (!timeout) {
585 dev_err(dwc->dev, "Reset Timed Out\n");
586 ret = -ETIMEDOUT;
587 goto err0;
588 }
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530589
T Karthik Reddy7bb245a2019-05-01 10:14:49 +0530590 dwc3_phy_setup(dwc);
591
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530592 ret = dwc3_core_soft_reset(dwc);
593 if (ret)
594 goto err0;
595
596 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
597 reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
598
599 switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
600 case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
601 /**
602 * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
603 * issue which would cause xHCI compliance tests to fail.
604 *
605 * Because of that we cannot enable clock gating on such
606 * configurations.
607 *
608 * Refers to:
609 *
610 * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based
611 * SOF/ITP Mode Used
612 */
613 if ((dwc->dr_mode == USB_DR_MODE_HOST ||
614 dwc->dr_mode == USB_DR_MODE_OTG) &&
615 (dwc->revision >= DWC3_REVISION_210A &&
616 dwc->revision <= DWC3_REVISION_250A))
617 reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
618 else
619 reg &= ~DWC3_GCTL_DSBLCLKGTNG;
620 break;
621 case DWC3_GHWPARAMS1_EN_PWROPT_HIB:
622 /* enable hibernation here */
623 dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4);
624
625 /*
626 * REVISIT Enabling this bit so that host-mode hibernation
627 * will work. Device-mode hibernation is not yet implemented.
628 */
629 reg |= DWC3_GCTL_GBLHIBERNATIONEN;
630 break;
631 default:
632 dev_dbg(dwc->dev, "No power optimization available\n");
633 }
634
635 /* check if current dwc3 is on simulation board */
636 if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
637 dev_dbg(dwc->dev, "it is on FPGA board\n");
638 dwc->is_fpga = true;
639 }
640
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530641 if(dwc->disable_scramble_quirk && !dwc->is_fpga)
642 WARN(true,
643 "disable_scramble cannot be used on non-FPGA builds\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530644
645 if (dwc->disable_scramble_quirk && dwc->is_fpga)
646 reg |= DWC3_GCTL_DISSCRAMBLE;
647 else
648 reg &= ~DWC3_GCTL_DISSCRAMBLE;
649
650 if (dwc->u2exit_lfps_quirk)
651 reg |= DWC3_GCTL_U2EXIT_LFPS;
652
653 /*
654 * WORKAROUND: DWC3 revisions <1.90a have a bug
655 * where the device can fail to connect at SuperSpeed
656 * and falls back to high-speed mode which causes
657 * the device to enter a Connect/Disconnect loop
658 */
659 if (dwc->revision < DWC3_REVISION_190A)
660 reg |= DWC3_GCTL_U2RSTECN;
661
662 dwc3_core_num_eps(dwc);
663
664 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
665
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530666 ret = dwc3_alloc_scratch_buffers(dwc);
667 if (ret)
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530668 goto err0;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530669
670 ret = dwc3_setup_scratch_buffers(dwc);
671 if (ret)
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530672 goto err1;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530673
Michael Walle679f13c2021-10-15 15:15:21 +0200674 /* Adjust Frame Length */
675 dwc3_frame_length_adjustment(dwc, dwc->fladj);
676
Balaji Prakash J840d2192022-11-27 15:31:53 +0100677 /* Adjust Reference Clock Period */
678 dwc3_ref_clk_period(dwc);
679
Michael Walle668bdf62021-10-15 15:15:22 +0200680 dwc3_set_incr_burst_type(dwc);
681
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530682 return 0;
683
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530684err1:
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530685 dwc3_free_scratch_buffers(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530686
687err0:
688 return ret;
689}
690
691static void dwc3_core_exit(struct dwc3 *dwc)
692{
693 dwc3_free_scratch_buffers(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530694}
695
696static int dwc3_core_init_mode(struct dwc3 *dwc)
697{
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530698 int ret;
699
700 switch (dwc->dr_mode) {
701 case USB_DR_MODE_PERIPHERAL:
702 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
703 ret = dwc3_gadget_init(dwc);
704 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400705 dev_err(dwc->dev, "failed to initialize gadget\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530706 return ret;
707 }
708 break;
709 case USB_DR_MODE_HOST:
710 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
711 ret = dwc3_host_init(dwc);
712 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400713 dev_err(dwc->dev, "failed to initialize host\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530714 return ret;
715 }
716 break;
717 case USB_DR_MODE_OTG:
718 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
719 ret = dwc3_host_init(dwc);
720 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400721 dev_err(dwc->dev, "failed to initialize host\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530722 return ret;
723 }
724
725 ret = dwc3_gadget_init(dwc);
726 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400727 dev_err(dwc->dev, "failed to initialize gadget\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530728 return ret;
729 }
730 break;
731 default:
Sean Anderson2789ce82020-09-15 10:45:16 -0400732 dev_err(dwc->dev,
733 "Unsupported mode of operation %d\n", dwc->dr_mode);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530734 return -EINVAL;
735 }
736
737 return 0;
738}
739
Jean-Jacques Hiblot73a1b8b2019-09-11 11:33:45 +0200740static void dwc3_gadget_run(struct dwc3 *dwc)
741{
742 dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_RUN_STOP);
743 mdelay(100);
744}
745
Angus Ainslieeefabee2022-02-02 15:08:55 -0800746static void dwc3_core_stop(struct dwc3 *dwc)
747{
748 u32 reg;
749
750 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
751 dwc3_writel(dwc->regs, DWC3_DCTL, reg & ~(DWC3_DCTL_RUN_STOP));
752}
753
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530754static void dwc3_core_exit_mode(struct dwc3 *dwc)
755{
756 switch (dwc->dr_mode) {
757 case USB_DR_MODE_PERIPHERAL:
758 dwc3_gadget_exit(dwc);
759 break;
760 case USB_DR_MODE_HOST:
761 dwc3_host_exit(dwc);
762 break;
763 case USB_DR_MODE_OTG:
764 dwc3_host_exit(dwc);
765 dwc3_gadget_exit(dwc);
766 break;
767 default:
768 /* do nothing */
769 break;
770 }
Jean-Jacques Hiblot73a1b8b2019-09-11 11:33:45 +0200771
772 /*
773 * switch back to peripheral mode
774 * This enables the phy to enter idle and then, if enabled, suspend.
775 */
776 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
777 dwc3_gadget_run(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530778}
779
780#define DWC3_ALIGN_MASK (16 - 1)
781
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530782/**
783 * dwc3_uboot_init - dwc3 core uboot initialization code
784 * @dwc3_dev: struct dwc3_device containing initialization data
785 *
786 * Entry point for dwc3 driver (equivalent to dwc3_probe in linux
787 * kernel driver). Pointer to dwc3_device should be passed containing
788 * base address and other initialization data. Returns '0' on success and
789 * a negative value on failure.
790 *
791 * Generally called from board_usb_init() implemented in board file.
792 */
793int dwc3_uboot_init(struct dwc3_device *dwc3_dev)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530794{
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530795 struct dwc3 *dwc;
Felipe Balbi424305f2015-10-01 14:22:18 -0500796 struct device *dev = NULL;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530797 u8 lpm_nyet_threshold;
798 u8 tx_de_emphasis;
799 u8 hird_threshold;
800
801 int ret;
802
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530803 void *mem;
804
Mugunthan V N121f93c2018-05-18 13:10:27 +0200805 mem = devm_kzalloc((struct udevice *)dev,
806 sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530807 if (!mem)
808 return -ENOMEM;
809
810 dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
811 dwc->mem = mem;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530812
Michal Simek698cd6f2015-10-30 16:24:06 +0100813 dwc->regs = (void *)(uintptr_t)(dwc3_dev->base +
814 DWC3_GLOBALS_REGS_START);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530815
816 /* default to highest possible threshold */
817 lpm_nyet_threshold = 0xff;
818
819 /* default to -3.5dB de-emphasis */
820 tx_de_emphasis = 1;
821
822 /*
823 * default to assert utmi_sleep_n and use maximum allowed HIRD
824 * threshold value of 0b1100
825 */
826 hird_threshold = 12;
827
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530828 dwc->maximum_speed = dwc3_dev->maximum_speed;
829 dwc->has_lpm_erratum = dwc3_dev->has_lpm_erratum;
830 if (dwc3_dev->lpm_nyet_threshold)
831 lpm_nyet_threshold = dwc3_dev->lpm_nyet_threshold;
832 dwc->is_utmi_l1_suspend = dwc3_dev->is_utmi_l1_suspend;
833 if (dwc3_dev->hird_threshold)
834 hird_threshold = dwc3_dev->hird_threshold;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530835
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530836 dwc->needs_fifo_resize = dwc3_dev->tx_fifo_resize;
837 dwc->dr_mode = dwc3_dev->dr_mode;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530838
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530839 dwc->disable_scramble_quirk = dwc3_dev->disable_scramble_quirk;
840 dwc->u2exit_lfps_quirk = dwc3_dev->u2exit_lfps_quirk;
841 dwc->u2ss_inp3_quirk = dwc3_dev->u2ss_inp3_quirk;
842 dwc->req_p1p2p3_quirk = dwc3_dev->req_p1p2p3_quirk;
843 dwc->del_p1p2p3_quirk = dwc3_dev->del_p1p2p3_quirk;
844 dwc->del_phy_power_chg_quirk = dwc3_dev->del_phy_power_chg_quirk;
845 dwc->lfps_filter_quirk = dwc3_dev->lfps_filter_quirk;
846 dwc->rx_detect_poll_quirk = dwc3_dev->rx_detect_poll_quirk;
847 dwc->dis_u3_susphy_quirk = dwc3_dev->dis_u3_susphy_quirk;
848 dwc->dis_u2_susphy_quirk = dwc3_dev->dis_u2_susphy_quirk;
Jagan Tekic1157dc2020-05-06 13:20:25 +0530849 dwc->dis_del_phy_power_chg_quirk = dwc3_dev->dis_del_phy_power_chg_quirk;
Jagan Teki0ece2f72020-05-26 11:33:48 +0800850 dwc->dis_tx_ipgap_linecheck_quirk = dwc3_dev->dis_tx_ipgap_linecheck_quirk;
Frank Wang0c3b6f52020-05-26 11:33:46 +0800851 dwc->dis_enblslpm_quirk = dwc3_dev->dis_enblslpm_quirk;
Frank Wangb29bcd72020-05-26 11:33:47 +0800852 dwc->dis_u2_freeclk_exists_quirk = dwc3_dev->dis_u2_freeclk_exists_quirk;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530853
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530854 dwc->tx_de_emphasis_quirk = dwc3_dev->tx_de_emphasis_quirk;
855 if (dwc3_dev->tx_de_emphasis)
856 tx_de_emphasis = dwc3_dev->tx_de_emphasis;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530857
858 /* default to superspeed if no maximum_speed passed */
859 if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
860 dwc->maximum_speed = USB_SPEED_SUPER;
861
862 dwc->lpm_nyet_threshold = lpm_nyet_threshold;
863 dwc->tx_de_emphasis = tx_de_emphasis;
864
865 dwc->hird_threshold = hird_threshold
866 | (dwc->is_utmi_l1_suspend << 4);
867
Frank Wanga4a29122020-05-26 11:34:30 +0800868 dwc->hsphy_mode = dwc3_dev->hsphy_mode;
869
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530870 dwc->index = dwc3_dev->index;
871
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530872 dwc3_cache_hwparams(dwc);
873
874 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
875 if (ret) {
876 dev_err(dwc->dev, "failed to allocate event buffers\n");
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530877 return -ENOMEM;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530878 }
879
Jean-Jacques Hiblot731a2a32019-09-11 11:33:53 +0200880 if (!IS_ENABLED(CONFIG_USB_DWC3_GADGET))
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530881 dwc->dr_mode = USB_DR_MODE_HOST;
Jean-Jacques Hiblot731a2a32019-09-11 11:33:53 +0200882 else if (!IS_ENABLED(CONFIG_USB_HOST))
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530883 dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
884
885 if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
886 dwc->dr_mode = USB_DR_MODE_OTG;
887
888 ret = dwc3_core_init(dwc);
889 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400890 dev_err(dwc->dev, "failed to initialize core\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530891 goto err0;
892 }
893
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530894 ret = dwc3_event_buffers_setup(dwc);
895 if (ret) {
896 dev_err(dwc->dev, "failed to setup event buffers\n");
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530897 goto err1;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530898 }
899
900 ret = dwc3_core_init_mode(dwc);
901 if (ret)
902 goto err2;
903
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530904 list_add_tail(&dwc->list, &dwc3_list);
905
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530906 return 0;
907
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530908err2:
909 dwc3_event_buffers_cleanup(dwc);
910
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530911err1:
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530912 dwc3_core_exit(dwc);
913
914err0:
915 dwc3_free_event_buffers(dwc);
916
917 return ret;
918}
919
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530920/**
921 * dwc3_uboot_exit - dwc3 core uboot cleanup code
922 * @index: index of this controller
923 *
924 * Performs cleanup of memory allocated in dwc3_uboot_init and other misc
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530925 * cleanups (equivalent to dwc3_remove in linux). index of _this_ controller
926 * should be passed and should match with the index passed in
927 * dwc3_device during init.
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530928 *
929 * Generally called from board file.
930 */
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530931void dwc3_uboot_exit(int index)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530932{
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530933 struct dwc3 *dwc;
934
935 list_for_each_entry(dwc, &dwc3_list, list) {
936 if (dwc->index != index)
937 continue;
938
939 dwc3_core_exit_mode(dwc);
940 dwc3_event_buffers_cleanup(dwc);
941 dwc3_free_event_buffers(dwc);
942 dwc3_core_exit(dwc);
943 list_del(&dwc->list);
944 kfree(dwc->mem);
945 break;
946 }
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530947}
948
Kishon Vijay Abraham I1cee7b12015-02-23 18:40:06 +0530949/**
950 * dwc3_uboot_handle_interrupt - handle dwc3 core interrupt
951 * @index: index of this controller
952 *
953 * Invokes dwc3 gadget interrupts.
954 *
955 * Generally called from board file.
956 */
957void dwc3_uboot_handle_interrupt(int index)
958{
959 struct dwc3 *dwc = NULL;
960
961 list_for_each_entry(dwc, &dwc3_list, list) {
962 if (dwc->index != index)
963 continue;
964
965 dwc3_gadget_uboot_handle_interrupt(dwc);
966 break;
967 }
968}
969
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530970MODULE_ALIAS("platform:dwc3");
971MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
972MODULE_LICENSE("GPL v2");
973MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
Mugunthan V N5f7ff712018-05-18 13:15:04 +0200974
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100975#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB)
developerf8bced12020-05-02 11:35:13 +0200976int dwc3_setup_phy(struct udevice *dev, struct phy_bulk *phys)
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100977{
developerf8bced12020-05-02 11:35:13 +0200978 int ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100979
developerf8bced12020-05-02 11:35:13 +0200980 ret = generic_phy_get_bulk(dev, phys);
981 if (ret)
982 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100983
developerf8bced12020-05-02 11:35:13 +0200984 ret = generic_phy_init_bulk(phys);
985 if (ret)
986 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100987
developerf8bced12020-05-02 11:35:13 +0200988 ret = generic_phy_power_on_bulk(phys);
989 if (ret)
990 generic_phy_exit_bulk(phys);
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100991
992 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100993}
994
developerf8bced12020-05-02 11:35:13 +0200995int dwc3_shutdown_phy(struct udevice *dev, struct phy_bulk *phys)
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100996{
developerf8bced12020-05-02 11:35:13 +0200997 int ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100998
developerf8bced12020-05-02 11:35:13 +0200999 ret = generic_phy_power_off_bulk(phys);
1000 ret |= generic_phy_exit_bulk(phys);
1001 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +01001002}
1003#endif
1004
Jean-Jacques Hiblot175cd7c2019-09-11 11:33:50 +02001005#if CONFIG_IS_ENABLED(DM_USB)
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001006void dwc3_of_parse(struct dwc3 *dwc)
1007{
1008 const u8 *tmp;
1009 struct udevice *dev = dwc->dev;
1010 u8 lpm_nyet_threshold;
1011 u8 tx_de_emphasis;
1012 u8 hird_threshold;
Michael Walle668bdf62021-10-15 15:15:22 +02001013 u32 val;
1014 int i;
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001015
1016 /* default to highest possible threshold */
1017 lpm_nyet_threshold = 0xff;
1018
1019 /* default to -3.5dB de-emphasis */
1020 tx_de_emphasis = 1;
1021
1022 /*
1023 * default to assert utmi_sleep_n and use maximum allowed HIRD
1024 * threshold value of 0b1100
1025 */
1026 hird_threshold = 12;
1027
Simon Glassa7ece582020-12-19 10:40:14 -07001028 dwc->hsphy_mode = usb_get_phy_mode(dev_ofnode(dev));
Frank Wanga4a29122020-05-26 11:34:30 +08001029
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001030 dwc->has_lpm_erratum = dev_read_bool(dev,
1031 "snps,has-lpm-erratum");
1032 tmp = dev_read_u8_array_ptr(dev, "snps,lpm-nyet-threshold", 1);
1033 if (tmp)
1034 lpm_nyet_threshold = *tmp;
1035
1036 dwc->is_utmi_l1_suspend = dev_read_bool(dev,
1037 "snps,is-utmi-l1-suspend");
1038 tmp = dev_read_u8_array_ptr(dev, "snps,hird-threshold", 1);
1039 if (tmp)
1040 hird_threshold = *tmp;
1041
1042 dwc->disable_scramble_quirk = dev_read_bool(dev,
1043 "snps,disable_scramble_quirk");
1044 dwc->u2exit_lfps_quirk = dev_read_bool(dev,
1045 "snps,u2exit_lfps_quirk");
1046 dwc->u2ss_inp3_quirk = dev_read_bool(dev,
1047 "snps,u2ss_inp3_quirk");
1048 dwc->req_p1p2p3_quirk = dev_read_bool(dev,
1049 "snps,req_p1p2p3_quirk");
1050 dwc->del_p1p2p3_quirk = dev_read_bool(dev,
1051 "snps,del_p1p2p3_quirk");
1052 dwc->del_phy_power_chg_quirk = dev_read_bool(dev,
1053 "snps,del_phy_power_chg_quirk");
1054 dwc->lfps_filter_quirk = dev_read_bool(dev,
1055 "snps,lfps_filter_quirk");
1056 dwc->rx_detect_poll_quirk = dev_read_bool(dev,
1057 "snps,rx_detect_poll_quirk");
1058 dwc->dis_u3_susphy_quirk = dev_read_bool(dev,
1059 "snps,dis_u3_susphy_quirk");
1060 dwc->dis_u2_susphy_quirk = dev_read_bool(dev,
1061 "snps,dis_u2_susphy_quirk");
Jagan Tekic1157dc2020-05-06 13:20:25 +05301062 dwc->dis_del_phy_power_chg_quirk = dev_read_bool(dev,
1063 "snps,dis-del-phy-power-chg-quirk");
Jagan Teki0ece2f72020-05-26 11:33:48 +08001064 dwc->dis_tx_ipgap_linecheck_quirk = dev_read_bool(dev,
1065 "snps,dis-tx-ipgap-linecheck-quirk");
Frank Wang0c3b6f52020-05-26 11:33:46 +08001066 dwc->dis_enblslpm_quirk = dev_read_bool(dev,
1067 "snps,dis_enblslpm_quirk");
Frank Wangb29bcd72020-05-26 11:33:47 +08001068 dwc->dis_u2_freeclk_exists_quirk = dev_read_bool(dev,
1069 "snps,dis-u2-freeclk-exists-quirk");
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001070 dwc->tx_de_emphasis_quirk = dev_read_bool(dev,
1071 "snps,tx_de_emphasis_quirk");
1072 tmp = dev_read_u8_array_ptr(dev, "snps,tx_de_emphasis", 1);
1073 if (tmp)
1074 tx_de_emphasis = *tmp;
1075
1076 dwc->lpm_nyet_threshold = lpm_nyet_threshold;
1077 dwc->tx_de_emphasis = tx_de_emphasis;
1078
1079 dwc->hird_threshold = hird_threshold
1080 | (dwc->is_utmi_l1_suspend << 4);
Michael Walle679f13c2021-10-15 15:15:21 +02001081
1082 dev_read_u32(dev, "snps,quirk-frame-length-adjustment", &dwc->fladj);
Balaji Prakash J840d2192022-11-27 15:31:53 +01001083 dev_read_u32(dev, "snps,ref-clock-period-ns", &dwc->ref_clk_per);
Michael Walle668bdf62021-10-15 15:15:22 +02001084
1085 /*
1086 * Handle property "snps,incr-burst-type-adjustment".
1087 * Get the number of value from this property:
1088 * result <= 0, means this property is not supported.
1089 * result = 1, means INCRx burst mode supported.
1090 * result > 1, means undefined length burst mode supported.
1091 */
1092 dwc->incrx_mode = INCRX_BURST_MODE;
1093 dwc->incrx_size = 0;
1094 for (i = 0; i < 8; i++) {
1095 if (dev_read_u32_index(dev, "snps,incr-burst-type-adjustment",
1096 i, &val))
1097 break;
1098
1099 dwc->incrx_mode = INCRX_UNDEF_LENGTH_BURST_MODE;
1100 dwc->incrx_size = max(dwc->incrx_size, val);
1101 }
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001102}
1103
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001104int dwc3_init(struct dwc3 *dwc)
1105{
1106 int ret;
Jagan Teki0ece2f72020-05-26 11:33:48 +08001107 u32 reg;
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001108
1109 dwc3_cache_hwparams(dwc);
1110
1111 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
1112 if (ret) {
1113 dev_err(dwc->dev, "failed to allocate event buffers\n");
1114 return -ENOMEM;
1115 }
1116
1117 ret = dwc3_core_init(dwc);
1118 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -04001119 dev_err(dwc->dev, "failed to initialize core\n");
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001120 goto core_fail;
1121 }
1122
1123 ret = dwc3_event_buffers_setup(dwc);
1124 if (ret) {
1125 dev_err(dwc->dev, "failed to setup event buffers\n");
1126 goto event_fail;
1127 }
1128
Jagan Teki0ece2f72020-05-26 11:33:48 +08001129 if (dwc->revision >= DWC3_REVISION_250A) {
1130 reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
1131
1132 /*
1133 * Enable hardware control of sending remote wakeup
1134 * in HS when the device is in the L1 state.
1135 */
1136 if (dwc->revision >= DWC3_REVISION_290A)
1137 reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
1138
1139 if (dwc->dis_tx_ipgap_linecheck_quirk)
1140 reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
1141
1142 dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
1143 }
1144
Jagan Teki461409b2020-05-26 11:34:29 +08001145 if (dwc->dr_mode == USB_DR_MODE_HOST ||
1146 dwc->dr_mode == USB_DR_MODE_OTG) {
1147 reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
1148
1149 reg |= DWC3_GUCTL_HSTINAUTORETRY;
1150
1151 dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
1152 }
1153
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001154 ret = dwc3_core_init_mode(dwc);
1155 if (ret)
1156 goto mode_fail;
1157
1158 return 0;
1159
1160mode_fail:
1161 dwc3_event_buffers_cleanup(dwc);
1162
1163event_fail:
1164 dwc3_core_exit(dwc);
1165
1166core_fail:
1167 dwc3_free_event_buffers(dwc);
1168
1169 return ret;
1170}
1171
1172void dwc3_remove(struct dwc3 *dwc)
1173{
1174 dwc3_core_exit_mode(dwc);
1175 dwc3_event_buffers_cleanup(dwc);
1176 dwc3_free_event_buffers(dwc);
Angus Ainslieeefabee2022-02-02 15:08:55 -08001177 dwc3_core_stop(dwc);
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001178 dwc3_core_exit(dwc);
1179 kfree(dwc->mem);
1180}
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001181#endif