blob: 300450100c90c6bd55faf58361322e5d41cfd22d [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>
Simon Glass63334482019-11-14 12:57:39 -070017#include <cpu_func.h>
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +053018#include <malloc.h>
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +053019#include <dwc3-uboot.h>
Simon Glass9bc15642020-02-03 07:36:16 -070020#include <dm/device_compat.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070021#include <dm/devres.h>
Simon Glassc06c1be2020-05-10 11:40:08 -060022#include <linux/bug.h>
Simon Glassdbd79542020-05-10 11:40:11 -060023#include <linux/delay.h>
Masahiro Yamada6373a172020-02-14 16:40:19 +090024#include <linux/dma-mapping.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070025#include <linux/err.h>
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053026#include <linux/ioport.h>
Mugunthan V N121f93c2018-05-18 13:10:27 +020027#include <dm.h>
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +010028#include <generic-phy.h>
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053029#include <linux/usb/ch9.h>
30#include <linux/usb/gadget.h>
Balaji Prakash J840d2192022-11-27 15:31:53 +010031#include <linux/bitfield.h>
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053032
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053033#include "core.h"
34#include "gadget.h"
35#include "io.h"
36
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +053037#include "linux-compat.h"
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053038
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +053039static LIST_HEAD(dwc3_list);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053040/* -------------------------------------------------------------------------- */
41
Joonyoung Shimbf35c602015-03-03 17:32:09 +010042static void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053043{
44 u32 reg;
45
46 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
47 reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
48 reg |= DWC3_GCTL_PRTCAPDIR(mode);
49 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
50}
51
52/**
53 * dwc3_core_soft_reset - Issues core soft reset and PHY reset
54 * @dwc: pointer to our context structure
55 */
56static int dwc3_core_soft_reset(struct dwc3 *dwc)
57{
58 u32 reg;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053059
60 /* Before Resetting PHY, put Core in Reset */
61 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
62 reg |= DWC3_GCTL_CORESOFTRESET;
63 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
64
65 /* Assert USB3 PHY reset */
66 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
67 reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
68 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
69
70 /* Assert USB2 PHY reset */
71 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
72 reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
73 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
74
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +053075 mdelay(100);
76
77 /* Clear USB3 PHY reset */
78 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
79 reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
80 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
81
82 /* Clear USB2 PHY reset */
83 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
84 reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
85 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
86
87 mdelay(100);
88
89 /* After PHYs are stable we can take Core out of reset state */
90 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
91 reg &= ~DWC3_GCTL_CORESOFTRESET;
92 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
93
94 return 0;
95}
96
Michael Walle679f13c2021-10-15 15:15:21 +020097/*
98 * dwc3_frame_length_adjustment - Adjusts frame length if required
99 * @dwc3: Pointer to our controller context structure
100 * @fladj: Value of GFLADJ_30MHZ to adjust frame length
101 */
102static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj)
103{
104 u32 reg;
105
106 if (dwc->revision < DWC3_REVISION_250A)
107 return;
108
109 if (fladj == 0)
110 return;
111
112 reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
113 reg &= ~DWC3_GFLADJ_30MHZ_MASK;
114 reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj;
115 dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
116}
117
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530118/**
Balaji Prakash J840d2192022-11-27 15:31:53 +0100119 * dwc3_ref_clk_period - Reference clock period configuration
120 * Default reference clock period depends on hardware
121 * configuration. For systems with reference clock that differs
122 * from the default, this will set clock period in DWC3_GUCTL
123 * register.
124 * @dwc: Pointer to our controller context structure
125 * @ref_clk_per: reference clock period in ns
126 */
127static void dwc3_ref_clk_period(struct dwc3 *dwc)
128{
129 u32 reg;
130
131 if (dwc->ref_clk_per == 0)
132 return;
133
134 reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
135 reg &= ~DWC3_GUCTL_REFCLKPER_MASK;
136 reg |= FIELD_PREP(DWC3_GUCTL_REFCLKPER_MASK, dwc->ref_clk_per);
137 dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
138}
139
140/**
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530141 * dwc3_free_one_event_buffer - Frees one event buffer
142 * @dwc: Pointer to our controller context structure
143 * @evt: Pointer to event buffer to be freed
144 */
145static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
146 struct dwc3_event_buffer *evt)
147{
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530148 dma_free_coherent(evt->buf);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530149}
150
151/**
152 * dwc3_alloc_one_event_buffer - Allocates one event buffer structure
153 * @dwc: Pointer to our controller context structure
154 * @length: size of the event buffer
155 *
156 * Returns a pointer to the allocated event buffer structure on success
157 * otherwise ERR_PTR(errno).
158 */
159static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
160 unsigned length)
161{
162 struct dwc3_event_buffer *evt;
163
Mugunthan V N121f93c2018-05-18 13:10:27 +0200164 evt = devm_kzalloc((struct udevice *)dwc->dev, sizeof(*evt),
165 GFP_KERNEL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530166 if (!evt)
167 return ERR_PTR(-ENOMEM);
168
169 evt->dwc = dwc;
170 evt->length = length;
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530171 evt->buf = dma_alloc_coherent(length,
172 (unsigned long *)&evt->dma);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530173 if (!evt->buf)
174 return ERR_PTR(-ENOMEM);
175
Philipp Tomsich8e17c162017-04-06 16:58:53 +0200176 dwc3_flush_cache((uintptr_t)evt->buf, evt->length);
177
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530178 return evt;
179}
180
181/**
182 * dwc3_free_event_buffers - frees all allocated event buffers
183 * @dwc: Pointer to our controller context structure
184 */
185static void dwc3_free_event_buffers(struct dwc3 *dwc)
186{
187 struct dwc3_event_buffer *evt;
188 int i;
189
190 for (i = 0; i < dwc->num_event_buffers; i++) {
191 evt = dwc->ev_buffs[i];
192 if (evt)
193 dwc3_free_one_event_buffer(dwc, evt);
194 }
195}
196
197/**
198 * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length
199 * @dwc: pointer to our controller context structure
200 * @length: size of event buffer
201 *
202 * Returns 0 on success otherwise negative errno. In the error case, dwc
203 * may contain some buffers allocated but not all which were requested.
204 */
205static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
206{
207 int num;
208 int i;
209
210 num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
211 dwc->num_event_buffers = num;
212
Kishon Vijay Abraham Ic7bdfe32015-02-23 18:40:13 +0530213 dwc->ev_buffs = memalign(CONFIG_SYS_CACHELINE_SIZE,
214 sizeof(*dwc->ev_buffs) * num);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530215 if (!dwc->ev_buffs)
216 return -ENOMEM;
217
218 for (i = 0; i < num; i++) {
219 struct dwc3_event_buffer *evt;
220
221 evt = dwc3_alloc_one_event_buffer(dwc, length);
222 if (IS_ERR(evt)) {
223 dev_err(dwc->dev, "can't allocate event buffer\n");
224 return PTR_ERR(evt);
225 }
226 dwc->ev_buffs[i] = evt;
227 }
228
229 return 0;
230}
231
232/**
233 * dwc3_event_buffers_setup - setup our allocated event buffers
234 * @dwc: pointer to our controller context structure
235 *
236 * Returns 0 on success otherwise negative errno.
237 */
238static int dwc3_event_buffers_setup(struct dwc3 *dwc)
239{
240 struct dwc3_event_buffer *evt;
241 int n;
242
243 for (n = 0; n < dwc->num_event_buffers; n++) {
244 evt = dwc->ev_buffs[n];
245 dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n",
246 evt->buf, (unsigned long long) evt->dma,
247 evt->length);
248
249 evt->lpos = 0;
250
251 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
252 lower_32_bits(evt->dma));
253 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
254 upper_32_bits(evt->dma));
255 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
256 DWC3_GEVNTSIZ_SIZE(evt->length));
257 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
258 }
259
260 return 0;
261}
262
263static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
264{
265 struct dwc3_event_buffer *evt;
266 int n;
267
268 for (n = 0; n < dwc->num_event_buffers; n++) {
269 evt = dwc->ev_buffs[n];
270
271 evt->lpos = 0;
272
273 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
274 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
275 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK
276 | DWC3_GEVNTSIZ_SIZE(0));
277 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
278 }
279}
280
281static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
282{
283 if (!dwc->has_hibernation)
284 return 0;
285
286 if (!dwc->nr_scratch)
287 return 0;
288
289 dwc->scratchbuf = kmalloc_array(dwc->nr_scratch,
290 DWC3_SCRATCHBUF_SIZE, GFP_KERNEL);
291 if (!dwc->scratchbuf)
292 return -ENOMEM;
293
294 return 0;
295}
296
297static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
298{
299 dma_addr_t scratch_addr;
300 u32 param;
301 int ret;
302
303 if (!dwc->has_hibernation)
304 return 0;
305
306 if (!dwc->nr_scratch)
307 return 0;
308
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530309 scratch_addr = dma_map_single(dwc->scratchbuf,
310 dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
311 DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530312 if (dma_mapping_error(dwc->dev, scratch_addr)) {
313 dev_err(dwc->dev, "failed to map scratch buffer\n");
314 ret = -EFAULT;
315 goto err0;
316 }
317
318 dwc->scratch_addr = scratch_addr;
319
320 param = lower_32_bits(scratch_addr);
321
322 ret = dwc3_send_gadget_generic_command(dwc,
323 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param);
324 if (ret < 0)
325 goto err1;
326
327 param = upper_32_bits(scratch_addr);
328
329 ret = dwc3_send_gadget_generic_command(dwc,
330 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param);
331 if (ret < 0)
332 goto err1;
333
334 return 0;
335
336err1:
Masahiro Yamada05a5dba2020-02-14 16:40:18 +0900337 dma_unmap_single(scratch_addr, dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
338 DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530339
340err0:
341 return ret;
342}
343
344static void dwc3_free_scratch_buffers(struct dwc3 *dwc)
345{
346 if (!dwc->has_hibernation)
347 return;
348
349 if (!dwc->nr_scratch)
350 return;
351
Masahiro Yamada05a5dba2020-02-14 16:40:18 +0900352 dma_unmap_single(dwc->scratch_addr, dwc->nr_scratch *
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530353 DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530354 kfree(dwc->scratchbuf);
355}
356
357static void dwc3_core_num_eps(struct dwc3 *dwc)
358{
359 struct dwc3_hwparams *parms = &dwc->hwparams;
360
361 dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
362 dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
363
364 dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
365 dwc->num_in_eps, dwc->num_out_eps);
366}
367
368static void dwc3_cache_hwparams(struct dwc3 *dwc)
369{
370 struct dwc3_hwparams *parms = &dwc->hwparams;
371
372 parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
373 parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
374 parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
375 parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
376 parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
377 parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
378 parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
379 parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
380 parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
381}
382
Frank Wanga4a29122020-05-26 11:34:30 +0800383static void dwc3_hsphy_mode_setup(struct dwc3 *dwc)
384{
385 enum usb_phy_interface hsphy_mode = dwc->hsphy_mode;
386 u32 reg;
387
388 /* Set dwc3 usb2 phy config */
389 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
390
391 switch (hsphy_mode) {
392 case USBPHY_INTERFACE_MODE_UTMI:
393 reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
394 DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
395 reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) |
396 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT);
397 break;
398 case USBPHY_INTERFACE_MODE_UTMIW:
399 reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
400 DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
401 reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) |
402 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT);
403 break;
404 default:
405 break;
406 }
407
408 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
409}
410
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530411/**
412 * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
413 * @dwc: Pointer to our controller context structure
414 */
415static void dwc3_phy_setup(struct dwc3 *dwc)
416{
417 u32 reg;
418
419 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
420
421 /*
422 * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
423 * to '0' during coreConsultant configuration. So default value
424 * will be '0' when the core is reset. Application needs to set it
425 * to '1' after the core initialization is completed.
426 */
427 if (dwc->revision > DWC3_REVISION_194A)
428 reg |= DWC3_GUSB3PIPECTL_SUSPHY;
429
430 if (dwc->u2ss_inp3_quirk)
431 reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
432
433 if (dwc->req_p1p2p3_quirk)
434 reg |= DWC3_GUSB3PIPECTL_REQP1P2P3;
435
436 if (dwc->del_p1p2p3_quirk)
437 reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN;
438
439 if (dwc->del_phy_power_chg_quirk)
440 reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE;
441
442 if (dwc->lfps_filter_quirk)
443 reg |= DWC3_GUSB3PIPECTL_LFPSFILT;
444
445 if (dwc->rx_detect_poll_quirk)
446 reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL;
447
448 if (dwc->tx_de_emphasis_quirk)
449 reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
450
451 if (dwc->dis_u3_susphy_quirk)
452 reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
453
Jagan Tekic1157dc2020-05-06 13:20:25 +0530454 if (dwc->dis_del_phy_power_chg_quirk)
455 reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
456
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530457 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
458
Frank Wanga4a29122020-05-26 11:34:30 +0800459 dwc3_hsphy_mode_setup(dwc);
460
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530461 mdelay(100);
462
463 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
464
465 /*
466 * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
467 * '0' during coreConsultant configuration. So default value will
468 * be '0' when the core is reset. Application needs to set it to
469 * '1' after the core initialization is completed.
470 */
471 if (dwc->revision > DWC3_REVISION_194A)
472 reg |= DWC3_GUSB2PHYCFG_SUSPHY;
473
474 if (dwc->dis_u2_susphy_quirk)
475 reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
476
Frank Wang0c3b6f52020-05-26 11:33:46 +0800477 if (dwc->dis_enblslpm_quirk)
478 reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
479
Frank Wangb29bcd72020-05-26 11:33:47 +0800480 if (dwc->dis_u2_freeclk_exists_quirk)
481 reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS;
482
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530483 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
484
485 mdelay(100);
486}
487
Michael Walle668bdf62021-10-15 15:15:22 +0200488/* set global incr burst type configuration registers */
489static void dwc3_set_incr_burst_type(struct dwc3 *dwc)
490{
491 struct udevice *dev = dwc->dev;
492 u32 cfg;
493
494 if (!dwc->incrx_size)
495 return;
496
497 cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0);
498
499 /* Enable Undefined Length INCR Burst and Enable INCRx Burst */
500 cfg &= ~DWC3_GSBUSCFG0_INCRBRST_MASK;
501 if (dwc->incrx_mode)
502 cfg |= DWC3_GSBUSCFG0_INCRBRSTENA;
503 switch (dwc->incrx_size) {
504 case 256:
505 cfg |= DWC3_GSBUSCFG0_INCR256BRSTENA;
506 break;
507 case 128:
508 cfg |= DWC3_GSBUSCFG0_INCR128BRSTENA;
509 break;
510 case 64:
511 cfg |= DWC3_GSBUSCFG0_INCR64BRSTENA;
512 break;
513 case 32:
514 cfg |= DWC3_GSBUSCFG0_INCR32BRSTENA;
515 break;
516 case 16:
517 cfg |= DWC3_GSBUSCFG0_INCR16BRSTENA;
518 break;
519 case 8:
520 cfg |= DWC3_GSBUSCFG0_INCR8BRSTENA;
521 break;
522 case 4:
523 cfg |= DWC3_GSBUSCFG0_INCR4BRSTENA;
524 break;
525 case 1:
526 break;
527 default:
528 dev_err(dev, "Invalid property\n");
529 break;
530 }
531
532 dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg);
533}
534
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530535/**
536 * dwc3_core_init - Low-level initialization of DWC3 Core
537 * @dwc: Pointer to our controller context structure
538 *
539 * Returns 0 on success otherwise negative errno.
540 */
541static int dwc3_core_init(struct dwc3 *dwc)
542{
543 unsigned long timeout;
544 u32 hwparams4 = dwc->hwparams.hwparams4;
545 u32 reg;
546 int ret;
547
548 reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
549 /* This should read as U3 followed by revision number */
550 if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
551 dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
552 ret = -ENODEV;
553 goto err0;
554 }
555 dwc->revision = reg;
556
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530557 /* Handle USB2.0-only core configuration */
558 if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
559 DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
560 if (dwc->maximum_speed == USB_SPEED_SUPER)
561 dwc->maximum_speed = USB_SPEED_HIGH;
562 }
563
564 /* issue device SoftReset too */
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530565 timeout = 5000;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530566 dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530567 while (timeout--) {
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530568 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
569 if (!(reg & DWC3_DCTL_CSFTRST))
570 break;
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530571 };
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530572
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530573 if (!timeout) {
574 dev_err(dwc->dev, "Reset Timed Out\n");
575 ret = -ETIMEDOUT;
576 goto err0;
577 }
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530578
T Karthik Reddy7bb245a2019-05-01 10:14:49 +0530579 dwc3_phy_setup(dwc);
580
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530581 ret = dwc3_core_soft_reset(dwc);
582 if (ret)
583 goto err0;
584
585 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
586 reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
587
588 switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
589 case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
590 /**
591 * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
592 * issue which would cause xHCI compliance tests to fail.
593 *
594 * Because of that we cannot enable clock gating on such
595 * configurations.
596 *
597 * Refers to:
598 *
599 * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based
600 * SOF/ITP Mode Used
601 */
602 if ((dwc->dr_mode == USB_DR_MODE_HOST ||
603 dwc->dr_mode == USB_DR_MODE_OTG) &&
604 (dwc->revision >= DWC3_REVISION_210A &&
605 dwc->revision <= DWC3_REVISION_250A))
606 reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
607 else
608 reg &= ~DWC3_GCTL_DSBLCLKGTNG;
609 break;
610 case DWC3_GHWPARAMS1_EN_PWROPT_HIB:
611 /* enable hibernation here */
612 dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4);
613
614 /*
615 * REVISIT Enabling this bit so that host-mode hibernation
616 * will work. Device-mode hibernation is not yet implemented.
617 */
618 reg |= DWC3_GCTL_GBLHIBERNATIONEN;
619 break;
620 default:
621 dev_dbg(dwc->dev, "No power optimization available\n");
622 }
623
624 /* check if current dwc3 is on simulation board */
625 if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
626 dev_dbg(dwc->dev, "it is on FPGA board\n");
627 dwc->is_fpga = true;
628 }
629
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530630 if(dwc->disable_scramble_quirk && !dwc->is_fpga)
631 WARN(true,
632 "disable_scramble cannot be used on non-FPGA builds\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530633
634 if (dwc->disable_scramble_quirk && dwc->is_fpga)
635 reg |= DWC3_GCTL_DISSCRAMBLE;
636 else
637 reg &= ~DWC3_GCTL_DISSCRAMBLE;
638
639 if (dwc->u2exit_lfps_quirk)
640 reg |= DWC3_GCTL_U2EXIT_LFPS;
641
642 /*
643 * WORKAROUND: DWC3 revisions <1.90a have a bug
644 * where the device can fail to connect at SuperSpeed
645 * and falls back to high-speed mode which causes
646 * the device to enter a Connect/Disconnect loop
647 */
648 if (dwc->revision < DWC3_REVISION_190A)
649 reg |= DWC3_GCTL_U2RSTECN;
650
651 dwc3_core_num_eps(dwc);
652
653 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
654
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530655 ret = dwc3_alloc_scratch_buffers(dwc);
656 if (ret)
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530657 goto err0;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530658
659 ret = dwc3_setup_scratch_buffers(dwc);
660 if (ret)
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530661 goto err1;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530662
Michael Walle679f13c2021-10-15 15:15:21 +0200663 /* Adjust Frame Length */
664 dwc3_frame_length_adjustment(dwc, dwc->fladj);
665
Balaji Prakash J840d2192022-11-27 15:31:53 +0100666 /* Adjust Reference Clock Period */
667 dwc3_ref_clk_period(dwc);
668
Michael Walle668bdf62021-10-15 15:15:22 +0200669 dwc3_set_incr_burst_type(dwc);
670
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530671 return 0;
672
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530673err1:
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530674 dwc3_free_scratch_buffers(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530675
676err0:
677 return ret;
678}
679
680static void dwc3_core_exit(struct dwc3 *dwc)
681{
682 dwc3_free_scratch_buffers(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530683}
684
685static int dwc3_core_init_mode(struct dwc3 *dwc)
686{
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530687 int ret;
688
689 switch (dwc->dr_mode) {
690 case USB_DR_MODE_PERIPHERAL:
691 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
692 ret = dwc3_gadget_init(dwc);
693 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400694 dev_err(dwc->dev, "failed to initialize gadget\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530695 return ret;
696 }
697 break;
698 case USB_DR_MODE_HOST:
699 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
700 ret = dwc3_host_init(dwc);
701 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400702 dev_err(dwc->dev, "failed to initialize host\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530703 return ret;
704 }
705 break;
706 case USB_DR_MODE_OTG:
707 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
708 ret = dwc3_host_init(dwc);
709 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400710 dev_err(dwc->dev, "failed to initialize host\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530711 return ret;
712 }
713
714 ret = dwc3_gadget_init(dwc);
715 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400716 dev_err(dwc->dev, "failed to initialize gadget\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530717 return ret;
718 }
719 break;
720 default:
Sean Anderson2789ce82020-09-15 10:45:16 -0400721 dev_err(dwc->dev,
722 "Unsupported mode of operation %d\n", dwc->dr_mode);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530723 return -EINVAL;
724 }
725
726 return 0;
727}
728
Jean-Jacques Hiblot73a1b8b2019-09-11 11:33:45 +0200729static void dwc3_gadget_run(struct dwc3 *dwc)
730{
731 dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_RUN_STOP);
732 mdelay(100);
733}
734
Angus Ainslieeefabee2022-02-02 15:08:55 -0800735static void dwc3_core_stop(struct dwc3 *dwc)
736{
737 u32 reg;
738
739 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
740 dwc3_writel(dwc->regs, DWC3_DCTL, reg & ~(DWC3_DCTL_RUN_STOP));
741}
742
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530743static void dwc3_core_exit_mode(struct dwc3 *dwc)
744{
745 switch (dwc->dr_mode) {
746 case USB_DR_MODE_PERIPHERAL:
747 dwc3_gadget_exit(dwc);
748 break;
749 case USB_DR_MODE_HOST:
750 dwc3_host_exit(dwc);
751 break;
752 case USB_DR_MODE_OTG:
753 dwc3_host_exit(dwc);
754 dwc3_gadget_exit(dwc);
755 break;
756 default:
757 /* do nothing */
758 break;
759 }
Jean-Jacques Hiblot73a1b8b2019-09-11 11:33:45 +0200760
761 /*
762 * switch back to peripheral mode
763 * This enables the phy to enter idle and then, if enabled, suspend.
764 */
765 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
766 dwc3_gadget_run(dwc);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530767}
768
769#define DWC3_ALIGN_MASK (16 - 1)
770
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530771/**
772 * dwc3_uboot_init - dwc3 core uboot initialization code
773 * @dwc3_dev: struct dwc3_device containing initialization data
774 *
775 * Entry point for dwc3 driver (equivalent to dwc3_probe in linux
776 * kernel driver). Pointer to dwc3_device should be passed containing
777 * base address and other initialization data. Returns '0' on success and
778 * a negative value on failure.
779 *
780 * Generally called from board_usb_init() implemented in board file.
781 */
782int dwc3_uboot_init(struct dwc3_device *dwc3_dev)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530783{
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530784 struct dwc3 *dwc;
Felipe Balbi424305f2015-10-01 14:22:18 -0500785 struct device *dev = NULL;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530786 u8 lpm_nyet_threshold;
787 u8 tx_de_emphasis;
788 u8 hird_threshold;
789
790 int ret;
791
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530792 void *mem;
793
Mugunthan V N121f93c2018-05-18 13:10:27 +0200794 mem = devm_kzalloc((struct udevice *)dev,
795 sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530796 if (!mem)
797 return -ENOMEM;
798
799 dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
800 dwc->mem = mem;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530801
Michal Simek698cd6f2015-10-30 16:24:06 +0100802 dwc->regs = (void *)(uintptr_t)(dwc3_dev->base +
803 DWC3_GLOBALS_REGS_START);
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530804
805 /* default to highest possible threshold */
806 lpm_nyet_threshold = 0xff;
807
808 /* default to -3.5dB de-emphasis */
809 tx_de_emphasis = 1;
810
811 /*
812 * default to assert utmi_sleep_n and use maximum allowed HIRD
813 * threshold value of 0b1100
814 */
815 hird_threshold = 12;
816
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530817 dwc->maximum_speed = dwc3_dev->maximum_speed;
818 dwc->has_lpm_erratum = dwc3_dev->has_lpm_erratum;
819 if (dwc3_dev->lpm_nyet_threshold)
820 lpm_nyet_threshold = dwc3_dev->lpm_nyet_threshold;
821 dwc->is_utmi_l1_suspend = dwc3_dev->is_utmi_l1_suspend;
822 if (dwc3_dev->hird_threshold)
823 hird_threshold = dwc3_dev->hird_threshold;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530824
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530825 dwc->needs_fifo_resize = dwc3_dev->tx_fifo_resize;
826 dwc->dr_mode = dwc3_dev->dr_mode;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530827
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530828 dwc->disable_scramble_quirk = dwc3_dev->disable_scramble_quirk;
829 dwc->u2exit_lfps_quirk = dwc3_dev->u2exit_lfps_quirk;
830 dwc->u2ss_inp3_quirk = dwc3_dev->u2ss_inp3_quirk;
831 dwc->req_p1p2p3_quirk = dwc3_dev->req_p1p2p3_quirk;
832 dwc->del_p1p2p3_quirk = dwc3_dev->del_p1p2p3_quirk;
833 dwc->del_phy_power_chg_quirk = dwc3_dev->del_phy_power_chg_quirk;
834 dwc->lfps_filter_quirk = dwc3_dev->lfps_filter_quirk;
835 dwc->rx_detect_poll_quirk = dwc3_dev->rx_detect_poll_quirk;
836 dwc->dis_u3_susphy_quirk = dwc3_dev->dis_u3_susphy_quirk;
837 dwc->dis_u2_susphy_quirk = dwc3_dev->dis_u2_susphy_quirk;
Jagan Tekic1157dc2020-05-06 13:20:25 +0530838 dwc->dis_del_phy_power_chg_quirk = dwc3_dev->dis_del_phy_power_chg_quirk;
Jagan Teki0ece2f72020-05-26 11:33:48 +0800839 dwc->dis_tx_ipgap_linecheck_quirk = dwc3_dev->dis_tx_ipgap_linecheck_quirk;
Frank Wang0c3b6f52020-05-26 11:33:46 +0800840 dwc->dis_enblslpm_quirk = dwc3_dev->dis_enblslpm_quirk;
Frank Wangb29bcd72020-05-26 11:33:47 +0800841 dwc->dis_u2_freeclk_exists_quirk = dwc3_dev->dis_u2_freeclk_exists_quirk;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530842
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530843 dwc->tx_de_emphasis_quirk = dwc3_dev->tx_de_emphasis_quirk;
844 if (dwc3_dev->tx_de_emphasis)
845 tx_de_emphasis = dwc3_dev->tx_de_emphasis;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530846
847 /* default to superspeed if no maximum_speed passed */
848 if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
849 dwc->maximum_speed = USB_SPEED_SUPER;
850
851 dwc->lpm_nyet_threshold = lpm_nyet_threshold;
852 dwc->tx_de_emphasis = tx_de_emphasis;
853
854 dwc->hird_threshold = hird_threshold
855 | (dwc->is_utmi_l1_suspend << 4);
856
Frank Wanga4a29122020-05-26 11:34:30 +0800857 dwc->hsphy_mode = dwc3_dev->hsphy_mode;
858
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530859 dwc->index = dwc3_dev->index;
860
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530861 dwc3_cache_hwparams(dwc);
862
863 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
864 if (ret) {
865 dev_err(dwc->dev, "failed to allocate event buffers\n");
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530866 return -ENOMEM;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530867 }
868
Jean-Jacques Hiblot731a2a32019-09-11 11:33:53 +0200869 if (!IS_ENABLED(CONFIG_USB_DWC3_GADGET))
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530870 dwc->dr_mode = USB_DR_MODE_HOST;
Jean-Jacques Hiblot731a2a32019-09-11 11:33:53 +0200871 else if (!IS_ENABLED(CONFIG_USB_HOST))
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530872 dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
873
874 if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
875 dwc->dr_mode = USB_DR_MODE_OTG;
876
877 ret = dwc3_core_init(dwc);
878 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -0400879 dev_err(dwc->dev, "failed to initialize core\n");
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530880 goto err0;
881 }
882
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530883 ret = dwc3_event_buffers_setup(dwc);
884 if (ret) {
885 dev_err(dwc->dev, "failed to setup event buffers\n");
Kishon Vijay Abraham I99030d72015-02-23 18:40:02 +0530886 goto err1;
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530887 }
888
889 ret = dwc3_core_init_mode(dwc);
890 if (ret)
891 goto err2;
892
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530893 list_add_tail(&dwc->list, &dwc3_list);
894
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530895 return 0;
896
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530897err2:
898 dwc3_event_buffers_cleanup(dwc);
899
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530900err1:
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530901 dwc3_core_exit(dwc);
902
903err0:
904 dwc3_free_event_buffers(dwc);
905
906 return ret;
907}
908
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530909/**
910 * dwc3_uboot_exit - dwc3 core uboot cleanup code
911 * @index: index of this controller
912 *
913 * Performs cleanup of memory allocated in dwc3_uboot_init and other misc
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530914 * cleanups (equivalent to dwc3_remove in linux). index of _this_ controller
915 * should be passed and should match with the index passed in
916 * dwc3_device during init.
Kishon Vijay Abraham Ibfbf05d2015-02-23 18:40:04 +0530917 *
918 * Generally called from board file.
919 */
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530920void dwc3_uboot_exit(int index)
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530921{
Kishon Vijay Abraham Idc5c6532015-02-23 18:40:05 +0530922 struct dwc3 *dwc;
923
924 list_for_each_entry(dwc, &dwc3_list, list) {
925 if (dwc->index != index)
926 continue;
927
928 dwc3_core_exit_mode(dwc);
929 dwc3_event_buffers_cleanup(dwc);
930 dwc3_free_event_buffers(dwc);
931 dwc3_core_exit(dwc);
932 list_del(&dwc->list);
933 kfree(dwc->mem);
934 break;
935 }
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530936}
937
Kishon Vijay Abraham I1cee7b12015-02-23 18:40:06 +0530938/**
939 * dwc3_uboot_handle_interrupt - handle dwc3 core interrupt
940 * @index: index of this controller
941 *
942 * Invokes dwc3 gadget interrupts.
943 *
944 * Generally called from board file.
945 */
946void dwc3_uboot_handle_interrupt(int index)
947{
948 struct dwc3 *dwc = NULL;
949
950 list_for_each_entry(dwc, &dwc3_list, list) {
951 if (dwc->index != index)
952 continue;
953
954 dwc3_gadget_uboot_handle_interrupt(dwc);
955 break;
956 }
957}
958
Kishon Vijay Abraham I1530fe32015-02-23 18:39:50 +0530959MODULE_ALIAS("platform:dwc3");
960MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
961MODULE_LICENSE("GPL v2");
962MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
Mugunthan V N5f7ff712018-05-18 13:15:04 +0200963
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100964#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB)
developerf8bced12020-05-02 11:35:13 +0200965int dwc3_setup_phy(struct udevice *dev, struct phy_bulk *phys)
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100966{
developerf8bced12020-05-02 11:35:13 +0200967 int ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100968
developerf8bced12020-05-02 11:35:13 +0200969 ret = generic_phy_get_bulk(dev, phys);
970 if (ret)
971 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100972
developerf8bced12020-05-02 11:35:13 +0200973 ret = generic_phy_init_bulk(phys);
974 if (ret)
975 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100976
developerf8bced12020-05-02 11:35:13 +0200977 ret = generic_phy_power_on_bulk(phys);
978 if (ret)
979 generic_phy_exit_bulk(phys);
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100980
981 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100982}
983
developerf8bced12020-05-02 11:35:13 +0200984int dwc3_shutdown_phy(struct udevice *dev, struct phy_bulk *phys)
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100985{
developerf8bced12020-05-02 11:35:13 +0200986 int ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100987
developerf8bced12020-05-02 11:35:13 +0200988 ret = generic_phy_power_off_bulk(phys);
989 ret |= generic_phy_exit_bulk(phys);
990 return ret;
Jean-Jacques Hiblot3de978a2018-11-29 10:52:45 +0100991}
992#endif
993
Jean-Jacques Hiblot175cd7c2019-09-11 11:33:50 +0200994#if CONFIG_IS_ENABLED(DM_USB)
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +0200995void dwc3_of_parse(struct dwc3 *dwc)
996{
997 const u8 *tmp;
998 struct udevice *dev = dwc->dev;
999 u8 lpm_nyet_threshold;
1000 u8 tx_de_emphasis;
1001 u8 hird_threshold;
Michael Walle668bdf62021-10-15 15:15:22 +02001002 u32 val;
1003 int i;
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001004
1005 /* default to highest possible threshold */
1006 lpm_nyet_threshold = 0xff;
1007
1008 /* default to -3.5dB de-emphasis */
1009 tx_de_emphasis = 1;
1010
1011 /*
1012 * default to assert utmi_sleep_n and use maximum allowed HIRD
1013 * threshold value of 0b1100
1014 */
1015 hird_threshold = 12;
1016
Simon Glassa7ece582020-12-19 10:40:14 -07001017 dwc->hsphy_mode = usb_get_phy_mode(dev_ofnode(dev));
Frank Wanga4a29122020-05-26 11:34:30 +08001018
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001019 dwc->has_lpm_erratum = dev_read_bool(dev,
1020 "snps,has-lpm-erratum");
1021 tmp = dev_read_u8_array_ptr(dev, "snps,lpm-nyet-threshold", 1);
1022 if (tmp)
1023 lpm_nyet_threshold = *tmp;
1024
1025 dwc->is_utmi_l1_suspend = dev_read_bool(dev,
1026 "snps,is-utmi-l1-suspend");
1027 tmp = dev_read_u8_array_ptr(dev, "snps,hird-threshold", 1);
1028 if (tmp)
1029 hird_threshold = *tmp;
1030
1031 dwc->disable_scramble_quirk = dev_read_bool(dev,
1032 "snps,disable_scramble_quirk");
1033 dwc->u2exit_lfps_quirk = dev_read_bool(dev,
1034 "snps,u2exit_lfps_quirk");
1035 dwc->u2ss_inp3_quirk = dev_read_bool(dev,
1036 "snps,u2ss_inp3_quirk");
1037 dwc->req_p1p2p3_quirk = dev_read_bool(dev,
1038 "snps,req_p1p2p3_quirk");
1039 dwc->del_p1p2p3_quirk = dev_read_bool(dev,
1040 "snps,del_p1p2p3_quirk");
1041 dwc->del_phy_power_chg_quirk = dev_read_bool(dev,
1042 "snps,del_phy_power_chg_quirk");
1043 dwc->lfps_filter_quirk = dev_read_bool(dev,
1044 "snps,lfps_filter_quirk");
1045 dwc->rx_detect_poll_quirk = dev_read_bool(dev,
1046 "snps,rx_detect_poll_quirk");
1047 dwc->dis_u3_susphy_quirk = dev_read_bool(dev,
1048 "snps,dis_u3_susphy_quirk");
1049 dwc->dis_u2_susphy_quirk = dev_read_bool(dev,
1050 "snps,dis_u2_susphy_quirk");
Jagan Tekic1157dc2020-05-06 13:20:25 +05301051 dwc->dis_del_phy_power_chg_quirk = dev_read_bool(dev,
1052 "snps,dis-del-phy-power-chg-quirk");
Jagan Teki0ece2f72020-05-26 11:33:48 +08001053 dwc->dis_tx_ipgap_linecheck_quirk = dev_read_bool(dev,
1054 "snps,dis-tx-ipgap-linecheck-quirk");
Frank Wang0c3b6f52020-05-26 11:33:46 +08001055 dwc->dis_enblslpm_quirk = dev_read_bool(dev,
1056 "snps,dis_enblslpm_quirk");
Frank Wangb29bcd72020-05-26 11:33:47 +08001057 dwc->dis_u2_freeclk_exists_quirk = dev_read_bool(dev,
1058 "snps,dis-u2-freeclk-exists-quirk");
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001059 dwc->tx_de_emphasis_quirk = dev_read_bool(dev,
1060 "snps,tx_de_emphasis_quirk");
1061 tmp = dev_read_u8_array_ptr(dev, "snps,tx_de_emphasis", 1);
1062 if (tmp)
1063 tx_de_emphasis = *tmp;
1064
1065 dwc->lpm_nyet_threshold = lpm_nyet_threshold;
1066 dwc->tx_de_emphasis = tx_de_emphasis;
1067
1068 dwc->hird_threshold = hird_threshold
1069 | (dwc->is_utmi_l1_suspend << 4);
Michael Walle679f13c2021-10-15 15:15:21 +02001070
1071 dev_read_u32(dev, "snps,quirk-frame-length-adjustment", &dwc->fladj);
Balaji Prakash J840d2192022-11-27 15:31:53 +01001072 dev_read_u32(dev, "snps,ref-clock-period-ns", &dwc->ref_clk_per);
Michael Walle668bdf62021-10-15 15:15:22 +02001073
1074 /*
1075 * Handle property "snps,incr-burst-type-adjustment".
1076 * Get the number of value from this property:
1077 * result <= 0, means this property is not supported.
1078 * result = 1, means INCRx burst mode supported.
1079 * result > 1, means undefined length burst mode supported.
1080 */
1081 dwc->incrx_mode = INCRX_BURST_MODE;
1082 dwc->incrx_size = 0;
1083 for (i = 0; i < 8; i++) {
1084 if (dev_read_u32_index(dev, "snps,incr-burst-type-adjustment",
1085 i, &val))
1086 break;
1087
1088 dwc->incrx_mode = INCRX_UNDEF_LENGTH_BURST_MODE;
1089 dwc->incrx_size = max(dwc->incrx_size, val);
1090 }
Jean-Jacques Hiblotce868d02019-09-11 11:33:52 +02001091}
1092
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001093int dwc3_init(struct dwc3 *dwc)
1094{
1095 int ret;
Jagan Teki0ece2f72020-05-26 11:33:48 +08001096 u32 reg;
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001097
1098 dwc3_cache_hwparams(dwc);
1099
1100 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
1101 if (ret) {
1102 dev_err(dwc->dev, "failed to allocate event buffers\n");
1103 return -ENOMEM;
1104 }
1105
1106 ret = dwc3_core_init(dwc);
1107 if (ret) {
Sean Anderson2789ce82020-09-15 10:45:16 -04001108 dev_err(dwc->dev, "failed to initialize core\n");
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001109 goto core_fail;
1110 }
1111
1112 ret = dwc3_event_buffers_setup(dwc);
1113 if (ret) {
1114 dev_err(dwc->dev, "failed to setup event buffers\n");
1115 goto event_fail;
1116 }
1117
Jagan Teki0ece2f72020-05-26 11:33:48 +08001118 if (dwc->revision >= DWC3_REVISION_250A) {
1119 reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
1120
1121 /*
1122 * Enable hardware control of sending remote wakeup
1123 * in HS when the device is in the L1 state.
1124 */
1125 if (dwc->revision >= DWC3_REVISION_290A)
1126 reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
1127
1128 if (dwc->dis_tx_ipgap_linecheck_quirk)
1129 reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
1130
1131 dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
1132 }
1133
Jagan Teki461409b2020-05-26 11:34:29 +08001134 if (dwc->dr_mode == USB_DR_MODE_HOST ||
1135 dwc->dr_mode == USB_DR_MODE_OTG) {
1136 reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
1137
1138 reg |= DWC3_GUCTL_HSTINAUTORETRY;
1139
1140 dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
1141 }
1142
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001143 ret = dwc3_core_init_mode(dwc);
1144 if (ret)
1145 goto mode_fail;
1146
1147 return 0;
1148
1149mode_fail:
1150 dwc3_event_buffers_cleanup(dwc);
1151
1152event_fail:
1153 dwc3_core_exit(dwc);
1154
1155core_fail:
1156 dwc3_free_event_buffers(dwc);
1157
1158 return ret;
1159}
1160
1161void dwc3_remove(struct dwc3 *dwc)
1162{
1163 dwc3_core_exit_mode(dwc);
1164 dwc3_event_buffers_cleanup(dwc);
1165 dwc3_free_event_buffers(dwc);
Angus Ainslieeefabee2022-02-02 15:08:55 -08001166 dwc3_core_stop(dwc);
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001167 dwc3_core_exit(dwc);
1168 kfree(dwc->mem);
1169}
Mugunthan V N5f7ff712018-05-18 13:15:04 +02001170#endif