Commit | Line | Data |
---|---|---|
5fd54ace | 1 | // SPDX-License-Identifier: GPL-2.0 |
27088e00 | 2 | /* |
72246da4 FB |
3 | * debugfs.c - DesignWare USB3 DRD Controller DebugFS file |
4 | * | |
10623b87 | 5 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com |
72246da4 FB |
6 | * |
7 | * Authors: Felipe Balbi <balbi@ti.com>, | |
8 | * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | |
72246da4 FB |
9 | */ |
10 | ||
11 | #include <linux/kernel.h> | |
12 | #include <linux/slab.h> | |
13 | #include <linux/ptrace.h> | |
14 | #include <linux/types.h> | |
15 | #include <linux/spinlock.h> | |
16 | #include <linux/debugfs.h> | |
17 | #include <linux/seq_file.h> | |
18 | #include <linux/delay.h> | |
25b8ff68 | 19 | #include <linux/uaccess.h> |
72246da4 | 20 | |
080d921f FB |
21 | #include <linux/usb/ch9.h> |
22 | ||
72246da4 FB |
23 | #include "core.h" |
24 | #include "gadget.h" | |
25 | #include "io.h" | |
8becf270 | 26 | #include "debug.h" |
72246da4 | 27 | |
62ba09d6 TN |
28 | #define DWC3_LSP_MUX_UNSELECTED 0xfffff |
29 | ||
72246da4 FB |
30 | #define dump_register(nm) \ |
31 | { \ | |
32 | .name = __stringify(nm), \ | |
2eb88016 | 33 | .offset = DWC3_ ##nm, \ |
72246da4 FB |
34 | } |
35 | ||
2eb88016 FB |
36 | #define dump_ep_register_set(n) \ |
37 | { \ | |
38 | .name = "DEPCMDPAR2("__stringify(n)")", \ | |
39 | .offset = DWC3_DEP_BASE(n) + \ | |
40 | DWC3_DEPCMDPAR2, \ | |
41 | }, \ | |
42 | { \ | |
43 | .name = "DEPCMDPAR1("__stringify(n)")", \ | |
44 | .offset = DWC3_DEP_BASE(n) + \ | |
45 | DWC3_DEPCMDPAR1, \ | |
46 | }, \ | |
47 | { \ | |
48 | .name = "DEPCMDPAR0("__stringify(n)")", \ | |
49 | .offset = DWC3_DEP_BASE(n) + \ | |
50 | DWC3_DEPCMDPAR0, \ | |
51 | }, \ | |
52 | { \ | |
53 | .name = "DEPCMD("__stringify(n)")", \ | |
54 | .offset = DWC3_DEP_BASE(n) + \ | |
55 | DWC3_DEPCMD, \ | |
56 | } | |
57 | ||
58 | ||
4ec0ddb1 | 59 | static const struct debugfs_reg32 dwc3_regs[] = { |
72246da4 FB |
60 | dump_register(GSBUSCFG0), |
61 | dump_register(GSBUSCFG1), | |
62 | dump_register(GTXTHRCFG), | |
63 | dump_register(GRXTHRCFG), | |
64 | dump_register(GCTL), | |
65 | dump_register(GEVTEN), | |
66 | dump_register(GSTS), | |
475c8beb | 67 | dump_register(GUCTL1), |
72246da4 FB |
68 | dump_register(GSNPSID), |
69 | dump_register(GGPIO), | |
70 | dump_register(GUID), | |
71 | dump_register(GUCTL), | |
72 | dump_register(GBUSERRADDR0), | |
73 | dump_register(GBUSERRADDR1), | |
74 | dump_register(GPRTBIMAP0), | |
75 | dump_register(GPRTBIMAP1), | |
76 | dump_register(GHWPARAMS0), | |
77 | dump_register(GHWPARAMS1), | |
78 | dump_register(GHWPARAMS2), | |
79 | dump_register(GHWPARAMS3), | |
80 | dump_register(GHWPARAMS4), | |
81 | dump_register(GHWPARAMS5), | |
82 | dump_register(GHWPARAMS6), | |
83 | dump_register(GHWPARAMS7), | |
84 | dump_register(GDBGFIFOSPACE), | |
85 | dump_register(GDBGLTSSM), | |
80b77634 | 86 | dump_register(GDBGBMU), |
72246da4 FB |
87 | dump_register(GPRTBIMAP_HS0), |
88 | dump_register(GPRTBIMAP_HS1), | |
89 | dump_register(GPRTBIMAP_FS0), | |
90 | dump_register(GPRTBIMAP_FS1), | |
8c4853c4 LJ |
91 | dump_register(GUCTL2), |
92 | dump_register(VER_NUMBER), | |
93 | dump_register(VER_TYPE), | |
72246da4 FB |
94 | |
95 | dump_register(GUSB2PHYCFG(0)), | |
96 | dump_register(GUSB2PHYCFG(1)), | |
97 | dump_register(GUSB2PHYCFG(2)), | |
98 | dump_register(GUSB2PHYCFG(3)), | |
99 | dump_register(GUSB2PHYCFG(4)), | |
100 | dump_register(GUSB2PHYCFG(5)), | |
101 | dump_register(GUSB2PHYCFG(6)), | |
102 | dump_register(GUSB2PHYCFG(7)), | |
103 | dump_register(GUSB2PHYCFG(8)), | |
104 | dump_register(GUSB2PHYCFG(9)), | |
105 | dump_register(GUSB2PHYCFG(10)), | |
106 | dump_register(GUSB2PHYCFG(11)), | |
107 | dump_register(GUSB2PHYCFG(12)), | |
108 | dump_register(GUSB2PHYCFG(13)), | |
109 | dump_register(GUSB2PHYCFG(14)), | |
110 | dump_register(GUSB2PHYCFG(15)), | |
111 | ||
112 | dump_register(GUSB2I2CCTL(0)), | |
113 | dump_register(GUSB2I2CCTL(1)), | |
114 | dump_register(GUSB2I2CCTL(2)), | |
115 | dump_register(GUSB2I2CCTL(3)), | |
116 | dump_register(GUSB2I2CCTL(4)), | |
117 | dump_register(GUSB2I2CCTL(5)), | |
118 | dump_register(GUSB2I2CCTL(6)), | |
119 | dump_register(GUSB2I2CCTL(7)), | |
120 | dump_register(GUSB2I2CCTL(8)), | |
121 | dump_register(GUSB2I2CCTL(9)), | |
122 | dump_register(GUSB2I2CCTL(10)), | |
123 | dump_register(GUSB2I2CCTL(11)), | |
124 | dump_register(GUSB2I2CCTL(12)), | |
125 | dump_register(GUSB2I2CCTL(13)), | |
126 | dump_register(GUSB2I2CCTL(14)), | |
127 | dump_register(GUSB2I2CCTL(15)), | |
128 | ||
129 | dump_register(GUSB2PHYACC(0)), | |
130 | dump_register(GUSB2PHYACC(1)), | |
131 | dump_register(GUSB2PHYACC(2)), | |
132 | dump_register(GUSB2PHYACC(3)), | |
133 | dump_register(GUSB2PHYACC(4)), | |
134 | dump_register(GUSB2PHYACC(5)), | |
135 | dump_register(GUSB2PHYACC(6)), | |
136 | dump_register(GUSB2PHYACC(7)), | |
137 | dump_register(GUSB2PHYACC(8)), | |
138 | dump_register(GUSB2PHYACC(9)), | |
139 | dump_register(GUSB2PHYACC(10)), | |
140 | dump_register(GUSB2PHYACC(11)), | |
141 | dump_register(GUSB2PHYACC(12)), | |
142 | dump_register(GUSB2PHYACC(13)), | |
143 | dump_register(GUSB2PHYACC(14)), | |
144 | dump_register(GUSB2PHYACC(15)), | |
145 | ||
146 | dump_register(GUSB3PIPECTL(0)), | |
147 | dump_register(GUSB3PIPECTL(1)), | |
148 | dump_register(GUSB3PIPECTL(2)), | |
149 | dump_register(GUSB3PIPECTL(3)), | |
150 | dump_register(GUSB3PIPECTL(4)), | |
151 | dump_register(GUSB3PIPECTL(5)), | |
152 | dump_register(GUSB3PIPECTL(6)), | |
153 | dump_register(GUSB3PIPECTL(7)), | |
154 | dump_register(GUSB3PIPECTL(8)), | |
155 | dump_register(GUSB3PIPECTL(9)), | |
156 | dump_register(GUSB3PIPECTL(10)), | |
157 | dump_register(GUSB3PIPECTL(11)), | |
158 | dump_register(GUSB3PIPECTL(12)), | |
159 | dump_register(GUSB3PIPECTL(13)), | |
160 | dump_register(GUSB3PIPECTL(14)), | |
161 | dump_register(GUSB3PIPECTL(15)), | |
162 | ||
163 | dump_register(GTXFIFOSIZ(0)), | |
164 | dump_register(GTXFIFOSIZ(1)), | |
165 | dump_register(GTXFIFOSIZ(2)), | |
166 | dump_register(GTXFIFOSIZ(3)), | |
167 | dump_register(GTXFIFOSIZ(4)), | |
168 | dump_register(GTXFIFOSIZ(5)), | |
169 | dump_register(GTXFIFOSIZ(6)), | |
170 | dump_register(GTXFIFOSIZ(7)), | |
171 | dump_register(GTXFIFOSIZ(8)), | |
172 | dump_register(GTXFIFOSIZ(9)), | |
173 | dump_register(GTXFIFOSIZ(10)), | |
174 | dump_register(GTXFIFOSIZ(11)), | |
175 | dump_register(GTXFIFOSIZ(12)), | |
176 | dump_register(GTXFIFOSIZ(13)), | |
177 | dump_register(GTXFIFOSIZ(14)), | |
178 | dump_register(GTXFIFOSIZ(15)), | |
179 | dump_register(GTXFIFOSIZ(16)), | |
180 | dump_register(GTXFIFOSIZ(17)), | |
181 | dump_register(GTXFIFOSIZ(18)), | |
182 | dump_register(GTXFIFOSIZ(19)), | |
183 | dump_register(GTXFIFOSIZ(20)), | |
184 | dump_register(GTXFIFOSIZ(21)), | |
185 | dump_register(GTXFIFOSIZ(22)), | |
186 | dump_register(GTXFIFOSIZ(23)), | |
187 | dump_register(GTXFIFOSIZ(24)), | |
188 | dump_register(GTXFIFOSIZ(25)), | |
189 | dump_register(GTXFIFOSIZ(26)), | |
190 | dump_register(GTXFIFOSIZ(27)), | |
191 | dump_register(GTXFIFOSIZ(28)), | |
192 | dump_register(GTXFIFOSIZ(29)), | |
193 | dump_register(GTXFIFOSIZ(30)), | |
194 | dump_register(GTXFIFOSIZ(31)), | |
195 | ||
196 | dump_register(GRXFIFOSIZ(0)), | |
197 | dump_register(GRXFIFOSIZ(1)), | |
198 | dump_register(GRXFIFOSIZ(2)), | |
199 | dump_register(GRXFIFOSIZ(3)), | |
200 | dump_register(GRXFIFOSIZ(4)), | |
201 | dump_register(GRXFIFOSIZ(5)), | |
202 | dump_register(GRXFIFOSIZ(6)), | |
203 | dump_register(GRXFIFOSIZ(7)), | |
204 | dump_register(GRXFIFOSIZ(8)), | |
205 | dump_register(GRXFIFOSIZ(9)), | |
206 | dump_register(GRXFIFOSIZ(10)), | |
207 | dump_register(GRXFIFOSIZ(11)), | |
208 | dump_register(GRXFIFOSIZ(12)), | |
209 | dump_register(GRXFIFOSIZ(13)), | |
210 | dump_register(GRXFIFOSIZ(14)), | |
211 | dump_register(GRXFIFOSIZ(15)), | |
212 | dump_register(GRXFIFOSIZ(16)), | |
213 | dump_register(GRXFIFOSIZ(17)), | |
214 | dump_register(GRXFIFOSIZ(18)), | |
215 | dump_register(GRXFIFOSIZ(19)), | |
216 | dump_register(GRXFIFOSIZ(20)), | |
217 | dump_register(GRXFIFOSIZ(21)), | |
218 | dump_register(GRXFIFOSIZ(22)), | |
219 | dump_register(GRXFIFOSIZ(23)), | |
220 | dump_register(GRXFIFOSIZ(24)), | |
221 | dump_register(GRXFIFOSIZ(25)), | |
222 | dump_register(GRXFIFOSIZ(26)), | |
223 | dump_register(GRXFIFOSIZ(27)), | |
224 | dump_register(GRXFIFOSIZ(28)), | |
225 | dump_register(GRXFIFOSIZ(29)), | |
226 | dump_register(GRXFIFOSIZ(30)), | |
227 | dump_register(GRXFIFOSIZ(31)), | |
228 | ||
229 | dump_register(GEVNTADRLO(0)), | |
230 | dump_register(GEVNTADRHI(0)), | |
231 | dump_register(GEVNTSIZ(0)), | |
232 | dump_register(GEVNTCOUNT(0)), | |
233 | ||
234 | dump_register(GHWPARAMS8), | |
8c4853c4 LJ |
235 | dump_register(GUCTL3), |
236 | dump_register(GFLADJ), | |
72246da4 FB |
237 | dump_register(DCFG), |
238 | dump_register(DCTL), | |
239 | dump_register(DEVTEN), | |
240 | dump_register(DSTS), | |
241 | dump_register(DGCMDPAR), | |
242 | dump_register(DGCMD), | |
243 | dump_register(DALEPENA), | |
244 | ||
2eb88016 FB |
245 | dump_ep_register_set(0), |
246 | dump_ep_register_set(1), | |
247 | dump_ep_register_set(2), | |
248 | dump_ep_register_set(3), | |
249 | dump_ep_register_set(4), | |
250 | dump_ep_register_set(5), | |
251 | dump_ep_register_set(6), | |
252 | dump_ep_register_set(7), | |
253 | dump_ep_register_set(8), | |
254 | dump_ep_register_set(9), | |
255 | dump_ep_register_set(10), | |
256 | dump_ep_register_set(11), | |
257 | dump_ep_register_set(12), | |
258 | dump_ep_register_set(13), | |
259 | dump_ep_register_set(14), | |
260 | dump_ep_register_set(15), | |
261 | dump_ep_register_set(16), | |
262 | dump_ep_register_set(17), | |
263 | dump_ep_register_set(18), | |
264 | dump_ep_register_set(19), | |
265 | dump_ep_register_set(20), | |
266 | dump_ep_register_set(21), | |
267 | dump_ep_register_set(22), | |
268 | dump_ep_register_set(23), | |
269 | dump_ep_register_set(24), | |
270 | dump_ep_register_set(25), | |
271 | dump_ep_register_set(26), | |
272 | dump_ep_register_set(27), | |
273 | dump_ep_register_set(28), | |
274 | dump_ep_register_set(29), | |
275 | dump_ep_register_set(30), | |
276 | dump_ep_register_set(31), | |
72246da4 FB |
277 | |
278 | dump_register(OCFG), | |
279 | dump_register(OCTL), | |
d4436c3a | 280 | dump_register(OEVT), |
72246da4 FB |
281 | dump_register(OEVTEN), |
282 | dump_register(OSTS), | |
283 | }; | |
284 | ||
62ba09d6 TN |
285 | static void dwc3_host_lsp(struct seq_file *s) |
286 | { | |
287 | struct dwc3 *dwc = s->private; | |
288 | bool dbc_enabled; | |
289 | u32 sel; | |
290 | u32 reg; | |
291 | u32 val; | |
292 | ||
293 | dbc_enabled = !!(dwc->hwparams.hwparams1 & DWC3_GHWPARAMS1_ENDBC); | |
294 | ||
295 | sel = dwc->dbg_lsp_select; | |
296 | if (sel == DWC3_LSP_MUX_UNSELECTED) { | |
297 | seq_puts(s, "Write LSP selection to print for host\n"); | |
298 | return; | |
299 | } | |
300 | ||
301 | reg = DWC3_GDBGLSPMUX_HOSTSELECT(sel); | |
302 | ||
303 | dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg); | |
304 | val = dwc3_readl(dwc->regs, DWC3_GDBGLSP); | |
305 | seq_printf(s, "GDBGLSP[%d] = 0x%08x\n", sel, val); | |
306 | ||
307 | if (dbc_enabled && sel < 256) { | |
308 | reg |= DWC3_GDBGLSPMUX_ENDBC; | |
309 | dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg); | |
310 | val = dwc3_readl(dwc->regs, DWC3_GDBGLSP); | |
311 | seq_printf(s, "GDBGLSP_DBC[%d] = 0x%08x\n", sel, val); | |
312 | } | |
313 | } | |
314 | ||
315 | static void dwc3_gadget_lsp(struct seq_file *s) | |
316 | { | |
317 | struct dwc3 *dwc = s->private; | |
318 | int i; | |
319 | u32 reg; | |
320 | ||
321 | for (i = 0; i < 16; i++) { | |
322 | reg = DWC3_GDBGLSPMUX_DEVSELECT(i); | |
323 | dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg); | |
324 | reg = dwc3_readl(dwc->regs, DWC3_GDBGLSP); | |
325 | seq_printf(s, "GDBGLSP[%d] = 0x%08x\n", i, reg); | |
326 | } | |
327 | } | |
328 | ||
329 | static int dwc3_lsp_show(struct seq_file *s, void *unused) | |
330 | { | |
331 | struct dwc3 *dwc = s->private; | |
332 | unsigned int current_mode; | |
333 | unsigned long flags; | |
334 | u32 reg; | |
614ce6a2 UG |
335 | int ret; |
336 | ||
337 | ret = pm_runtime_resume_and_get(dwc->dev); | |
338 | if (ret < 0) | |
339 | return ret; | |
62ba09d6 TN |
340 | |
341 | spin_lock_irqsave(&dwc->lock, flags); | |
342 | reg = dwc3_readl(dwc->regs, DWC3_GSTS); | |
343 | current_mode = DWC3_GSTS_CURMOD(reg); | |
344 | ||
345 | switch (current_mode) { | |
346 | case DWC3_GSTS_CURMOD_HOST: | |
347 | dwc3_host_lsp(s); | |
348 | break; | |
349 | case DWC3_GSTS_CURMOD_DEVICE: | |
350 | dwc3_gadget_lsp(s); | |
351 | break; | |
352 | default: | |
353 | seq_puts(s, "Mode is unknown, no LSP register printed\n"); | |
354 | break; | |
355 | } | |
356 | spin_unlock_irqrestore(&dwc->lock, flags); | |
357 | ||
614ce6a2 UG |
358 | pm_runtime_put_sync(dwc->dev); |
359 | ||
62ba09d6 TN |
360 | return 0; |
361 | } | |
362 | ||
363 | static int dwc3_lsp_open(struct inode *inode, struct file *file) | |
364 | { | |
365 | return single_open(file, dwc3_lsp_show, inode->i_private); | |
366 | } | |
367 | ||
368 | static ssize_t dwc3_lsp_write(struct file *file, const char __user *ubuf, | |
369 | size_t count, loff_t *ppos) | |
370 | { | |
371 | struct seq_file *s = file->private_data; | |
372 | struct dwc3 *dwc = s->private; | |
373 | unsigned long flags; | |
374 | char buf[32] = { 0 }; | |
375 | u32 sel; | |
376 | int ret; | |
377 | ||
378 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | |
379 | return -EFAULT; | |
380 | ||
381 | ret = kstrtouint(buf, 0, &sel); | |
382 | if (ret) | |
383 | return ret; | |
384 | ||
385 | spin_lock_irqsave(&dwc->lock, flags); | |
386 | dwc->dbg_lsp_select = sel; | |
387 | spin_unlock_irqrestore(&dwc->lock, flags); | |
388 | ||
389 | return count; | |
390 | } | |
391 | ||
392 | static const struct file_operations dwc3_lsp_fops = { | |
393 | .open = dwc3_lsp_open, | |
394 | .write = dwc3_lsp_write, | |
395 | .read = seq_read, | |
396 | .llseek = seq_lseek, | |
397 | .release = single_release, | |
398 | }; | |
399 | ||
0b9fe32d FB |
400 | static int dwc3_mode_show(struct seq_file *s, void *unused) |
401 | { | |
402 | struct dwc3 *dwc = s->private; | |
403 | unsigned long flags; | |
404 | u32 reg; | |
614ce6a2 UG |
405 | int ret; |
406 | ||
407 | ret = pm_runtime_resume_and_get(dwc->dev); | |
408 | if (ret < 0) | |
409 | return ret; | |
0b9fe32d FB |
410 | |
411 | spin_lock_irqsave(&dwc->lock, flags); | |
412 | reg = dwc3_readl(dwc->regs, DWC3_GCTL); | |
413 | spin_unlock_irqrestore(&dwc->lock, flags); | |
414 | ||
415 | switch (DWC3_GCTL_PRTCAP(reg)) { | |
416 | case DWC3_GCTL_PRTCAP_HOST: | |
9ae0eb45 | 417 | seq_puts(s, "host\n"); |
0b9fe32d FB |
418 | break; |
419 | case DWC3_GCTL_PRTCAP_DEVICE: | |
9ae0eb45 | 420 | seq_puts(s, "device\n"); |
0b9fe32d FB |
421 | break; |
422 | case DWC3_GCTL_PRTCAP_OTG: | |
9ae0eb45 | 423 | seq_puts(s, "otg\n"); |
0b9fe32d FB |
424 | break; |
425 | default: | |
426 | seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg)); | |
427 | } | |
428 | ||
614ce6a2 UG |
429 | pm_runtime_put_sync(dwc->dev); |
430 | ||
0b9fe32d FB |
431 | return 0; |
432 | } | |
433 | ||
434 | static int dwc3_mode_open(struct inode *inode, struct file *file) | |
435 | { | |
436 | return single_open(file, dwc3_mode_show, inode->i_private); | |
437 | } | |
438 | ||
439 | static ssize_t dwc3_mode_write(struct file *file, | |
440 | const char __user *ubuf, size_t count, loff_t *ppos) | |
441 | { | |
442 | struct seq_file *s = file->private_data; | |
443 | struct dwc3 *dwc = s->private; | |
3140e8cb | 444 | u32 mode = 0; |
0b9fe32d FB |
445 | char buf[32]; |
446 | ||
447 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | |
448 | return -EFAULT; | |
449 | ||
5bde3f02 LJ |
450 | if (dwc->dr_mode != USB_DR_MODE_OTG) |
451 | return count; | |
452 | ||
0b9fe32d | 453 | if (!strncmp(buf, "host", 4)) |
b202c42c | 454 | mode = DWC3_GCTL_PRTCAP_HOST; |
0b9fe32d FB |
455 | |
456 | if (!strncmp(buf, "device", 6)) | |
b202c42c | 457 | mode = DWC3_GCTL_PRTCAP_DEVICE; |
0b9fe32d FB |
458 | |
459 | if (!strncmp(buf, "otg", 3)) | |
b202c42c | 460 | mode = DWC3_GCTL_PRTCAP_OTG; |
0b9fe32d | 461 | |
41ce1456 RQ |
462 | dwc3_set_mode(dwc, mode); |
463 | ||
0b9fe32d FB |
464 | return count; |
465 | } | |
466 | ||
467 | static const struct file_operations dwc3_mode_fops = { | |
468 | .open = dwc3_mode_open, | |
469 | .write = dwc3_mode_write, | |
470 | .read = seq_read, | |
471 | .llseek = seq_lseek, | |
472 | .release = single_release, | |
473 | }; | |
474 | ||
080d921f FB |
475 | static int dwc3_testmode_show(struct seq_file *s, void *unused) |
476 | { | |
477 | struct dwc3 *dwc = s->private; | |
478 | unsigned long flags; | |
479 | u32 reg; | |
614ce6a2 UG |
480 | int ret; |
481 | ||
482 | ret = pm_runtime_resume_and_get(dwc->dev); | |
483 | if (ret < 0) | |
484 | return ret; | |
080d921f FB |
485 | |
486 | spin_lock_irqsave(&dwc->lock, flags); | |
487 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); | |
488 | reg &= DWC3_DCTL_TSTCTRL_MASK; | |
489 | reg >>= 1; | |
490 | spin_unlock_irqrestore(&dwc->lock, flags); | |
491 | ||
492 | switch (reg) { | |
493 | case 0: | |
9ae0eb45 | 494 | seq_puts(s, "no test\n"); |
080d921f | 495 | break; |
62fb45d3 | 496 | case USB_TEST_J: |
9ae0eb45 | 497 | seq_puts(s, "test_j\n"); |
080d921f | 498 | break; |
62fb45d3 | 499 | case USB_TEST_K: |
9ae0eb45 | 500 | seq_puts(s, "test_k\n"); |
080d921f | 501 | break; |
62fb45d3 | 502 | case USB_TEST_SE0_NAK: |
9ae0eb45 | 503 | seq_puts(s, "test_se0_nak\n"); |
080d921f | 504 | break; |
62fb45d3 | 505 | case USB_TEST_PACKET: |
9ae0eb45 | 506 | seq_puts(s, "test_packet\n"); |
080d921f | 507 | break; |
62fb45d3 | 508 | case USB_TEST_FORCE_ENABLE: |
9ae0eb45 | 509 | seq_puts(s, "test_force_enable\n"); |
080d921f FB |
510 | break; |
511 | default: | |
512 | seq_printf(s, "UNKNOWN %d\n", reg); | |
513 | } | |
514 | ||
614ce6a2 UG |
515 | pm_runtime_put_sync(dwc->dev); |
516 | ||
080d921f FB |
517 | return 0; |
518 | } | |
519 | ||
520 | static int dwc3_testmode_open(struct inode *inode, struct file *file) | |
521 | { | |
522 | return single_open(file, dwc3_testmode_show, inode->i_private); | |
523 | } | |
524 | ||
525 | static ssize_t dwc3_testmode_write(struct file *file, | |
526 | const char __user *ubuf, size_t count, loff_t *ppos) | |
527 | { | |
528 | struct seq_file *s = file->private_data; | |
529 | struct dwc3 *dwc = s->private; | |
530 | unsigned long flags; | |
531 | u32 testmode = 0; | |
532 | char buf[32]; | |
614ce6a2 | 533 | int ret; |
080d921f FB |
534 | |
535 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | |
536 | return -EFAULT; | |
537 | ||
538 | if (!strncmp(buf, "test_j", 6)) | |
62fb45d3 | 539 | testmode = USB_TEST_J; |
080d921f | 540 | else if (!strncmp(buf, "test_k", 6)) |
62fb45d3 | 541 | testmode = USB_TEST_K; |
09072543 | 542 | else if (!strncmp(buf, "test_se0_nak", 12)) |
62fb45d3 | 543 | testmode = USB_TEST_SE0_NAK; |
09072543 | 544 | else if (!strncmp(buf, "test_packet", 11)) |
62fb45d3 | 545 | testmode = USB_TEST_PACKET; |
09072543 | 546 | else if (!strncmp(buf, "test_force_enable", 17)) |
62fb45d3 | 547 | testmode = USB_TEST_FORCE_ENABLE; |
080d921f FB |
548 | else |
549 | testmode = 0; | |
550 | ||
614ce6a2 UG |
551 | ret = pm_runtime_resume_and_get(dwc->dev); |
552 | if (ret < 0) | |
553 | return ret; | |
554 | ||
080d921f FB |
555 | spin_lock_irqsave(&dwc->lock, flags); |
556 | dwc3_gadget_set_test_mode(dwc, testmode); | |
557 | spin_unlock_irqrestore(&dwc->lock, flags); | |
558 | ||
614ce6a2 UG |
559 | pm_runtime_put_sync(dwc->dev); |
560 | ||
080d921f FB |
561 | return count; |
562 | } | |
563 | ||
564 | static const struct file_operations dwc3_testmode_fops = { | |
565 | .open = dwc3_testmode_open, | |
566 | .write = dwc3_testmode_write, | |
567 | .read = seq_read, | |
568 | .llseek = seq_lseek, | |
569 | .release = single_release, | |
570 | }; | |
571 | ||
138801aa FB |
572 | static int dwc3_link_state_show(struct seq_file *s, void *unused) |
573 | { | |
574 | struct dwc3 *dwc = s->private; | |
575 | unsigned long flags; | |
576 | enum dwc3_link_state state; | |
577 | u32 reg; | |
0d36dede | 578 | u8 speed; |
614ce6a2 UG |
579 | int ret; |
580 | ||
581 | ret = pm_runtime_resume_and_get(dwc->dev); | |
582 | if (ret < 0) | |
583 | return ret; | |
138801aa FB |
584 | |
585 | spin_lock_irqsave(&dwc->lock, flags); | |
d102444c TN |
586 | reg = dwc3_readl(dwc->regs, DWC3_GSTS); |
587 | if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) { | |
588 | seq_puts(s, "Not available\n"); | |
589 | spin_unlock_irqrestore(&dwc->lock, flags); | |
614ce6a2 | 590 | pm_runtime_put_sync(dwc->dev); |
d102444c TN |
591 | return 0; |
592 | } | |
593 | ||
138801aa FB |
594 | reg = dwc3_readl(dwc->regs, DWC3_DSTS); |
595 | state = DWC3_DSTS_USBLNKST(reg); | |
0d36dede | 596 | speed = reg & DWC3_DSTS_CONNECTSPD; |
138801aa | 597 | |
0d36dede TN |
598 | seq_printf(s, "%s\n", (speed >= DWC3_DSTS_SUPERSPEED) ? |
599 | dwc3_gadget_link_string(state) : | |
600 | dwc3_gadget_hs_link_string(state)); | |
601 | spin_unlock_irqrestore(&dwc->lock, flags); | |
138801aa | 602 | |
614ce6a2 UG |
603 | pm_runtime_put_sync(dwc->dev); |
604 | ||
138801aa FB |
605 | return 0; |
606 | } | |
607 | ||
608 | static int dwc3_link_state_open(struct inode *inode, struct file *file) | |
609 | { | |
610 | return single_open(file, dwc3_link_state_show, inode->i_private); | |
611 | } | |
612 | ||
613 | static ssize_t dwc3_link_state_write(struct file *file, | |
614 | const char __user *ubuf, size_t count, loff_t *ppos) | |
615 | { | |
616 | struct seq_file *s = file->private_data; | |
617 | struct dwc3 *dwc = s->private; | |
618 | unsigned long flags; | |
619 | enum dwc3_link_state state = 0; | |
620 | char buf[32]; | |
0d36dede TN |
621 | u32 reg; |
622 | u8 speed; | |
614ce6a2 | 623 | int ret; |
138801aa FB |
624 | |
625 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | |
626 | return -EFAULT; | |
627 | ||
628 | if (!strncmp(buf, "SS.Disabled", 11)) | |
629 | state = DWC3_LINK_STATE_SS_DIS; | |
630 | else if (!strncmp(buf, "Rx.Detect", 9)) | |
631 | state = DWC3_LINK_STATE_RX_DET; | |
632 | else if (!strncmp(buf, "SS.Inactive", 11)) | |
633 | state = DWC3_LINK_STATE_SS_INACT; | |
634 | else if (!strncmp(buf, "Recovery", 8)) | |
635 | state = DWC3_LINK_STATE_RECOV; | |
636 | else if (!strncmp(buf, "Compliance", 10)) | |
637 | state = DWC3_LINK_STATE_CMPLY; | |
638 | else if (!strncmp(buf, "Loopback", 8)) | |
639 | state = DWC3_LINK_STATE_LPBK; | |
640 | else | |
641 | return -EINVAL; | |
642 | ||
614ce6a2 UG |
643 | ret = pm_runtime_resume_and_get(dwc->dev); |
644 | if (ret < 0) | |
645 | return ret; | |
646 | ||
138801aa | 647 | spin_lock_irqsave(&dwc->lock, flags); |
d102444c TN |
648 | reg = dwc3_readl(dwc->regs, DWC3_GSTS); |
649 | if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) { | |
650 | spin_unlock_irqrestore(&dwc->lock, flags); | |
614ce6a2 | 651 | pm_runtime_put_sync(dwc->dev); |
d102444c TN |
652 | return -EINVAL; |
653 | } | |
654 | ||
0d36dede TN |
655 | reg = dwc3_readl(dwc->regs, DWC3_DSTS); |
656 | speed = reg & DWC3_DSTS_CONNECTSPD; | |
657 | ||
658 | if (speed < DWC3_DSTS_SUPERSPEED && | |
659 | state != DWC3_LINK_STATE_RECOV) { | |
660 | spin_unlock_irqrestore(&dwc->lock, flags); | |
614ce6a2 | 661 | pm_runtime_put_sync(dwc->dev); |
0d36dede TN |
662 | return -EINVAL; |
663 | } | |
664 | ||
138801aa FB |
665 | dwc3_gadget_set_link_state(dwc, state); |
666 | spin_unlock_irqrestore(&dwc->lock, flags); | |
667 | ||
614ce6a2 UG |
668 | pm_runtime_put_sync(dwc->dev); |
669 | ||
138801aa FB |
670 | return count; |
671 | } | |
672 | ||
673 | static const struct file_operations dwc3_link_state_fops = { | |
674 | .open = dwc3_link_state_open, | |
675 | .write = dwc3_link_state_write, | |
676 | .read = seq_read, | |
677 | .llseek = seq_lseek, | |
678 | .release = single_release, | |
679 | }; | |
680 | ||
818ec3ab | 681 | struct dwc3_ep_file_map { |
6d5b53c1 FB |
682 | const char name[25]; |
683 | const struct file_operations *const fops; | |
818ec3ab FB |
684 | }; |
685 | ||
2c85a181 | 686 | static int dwc3_tx_fifo_size_show(struct seq_file *s, void *unused) |
818ec3ab FB |
687 | { |
688 | struct dwc3_ep *dep = s->private; | |
689 | struct dwc3 *dwc = dep->dwc; | |
690 | unsigned long flags; | |
d00be779 | 691 | u32 mdwidth; |
818ec3ab | 692 | u32 val; |
614ce6a2 UG |
693 | int ret; |
694 | ||
695 | ret = pm_runtime_resume_and_get(dwc->dev); | |
696 | if (ret < 0) | |
697 | return ret; | |
818ec3ab FB |
698 | |
699 | spin_lock_irqsave(&dwc->lock, flags); | |
2c85a181 | 700 | val = dwc3_core_fifo_space(dep, DWC3_TXFIFO); |
0f874f79 TN |
701 | |
702 | /* Convert to bytes */ | |
d00be779 | 703 | mdwidth = dwc3_mdwidth(dwc); |
4244ba02 TN |
704 | |
705 | val *= mdwidth; | |
0f874f79 | 706 | val >>= 3; |
818ec3ab FB |
707 | seq_printf(s, "%u\n", val); |
708 | spin_unlock_irqrestore(&dwc->lock, flags); | |
709 | ||
614ce6a2 UG |
710 | pm_runtime_put_sync(dwc->dev); |
711 | ||
818ec3ab FB |
712 | return 0; |
713 | } | |
714 | ||
2c85a181 | 715 | static int dwc3_rx_fifo_size_show(struct seq_file *s, void *unused) |
818ec3ab FB |
716 | { |
717 | struct dwc3_ep *dep = s->private; | |
718 | struct dwc3 *dwc = dep->dwc; | |
719 | unsigned long flags; | |
d00be779 | 720 | u32 mdwidth; |
818ec3ab | 721 | u32 val; |
614ce6a2 UG |
722 | int ret; |
723 | ||
724 | ret = pm_runtime_resume_and_get(dwc->dev); | |
725 | if (ret < 0) | |
726 | return ret; | |
818ec3ab FB |
727 | |
728 | spin_lock_irqsave(&dwc->lock, flags); | |
2c85a181 | 729 | val = dwc3_core_fifo_space(dep, DWC3_RXFIFO); |
0f874f79 TN |
730 | |
731 | /* Convert to bytes */ | |
d00be779 | 732 | mdwidth = dwc3_mdwidth(dwc); |
4244ba02 TN |
733 | |
734 | val *= mdwidth; | |
0f874f79 | 735 | val >>= 3; |
818ec3ab FB |
736 | seq_printf(s, "%u\n", val); |
737 | spin_unlock_irqrestore(&dwc->lock, flags); | |
738 | ||
614ce6a2 UG |
739 | pm_runtime_put_sync(dwc->dev); |
740 | ||
818ec3ab FB |
741 | return 0; |
742 | } | |
743 | ||
744 | static int dwc3_tx_request_queue_show(struct seq_file *s, void *unused) | |
745 | { | |
746 | struct dwc3_ep *dep = s->private; | |
747 | struct dwc3 *dwc = dep->dwc; | |
748 | unsigned long flags; | |
749 | u32 val; | |
614ce6a2 UG |
750 | int ret; |
751 | ||
752 | ret = pm_runtime_resume_and_get(dwc->dev); | |
753 | if (ret < 0) | |
754 | return ret; | |
818ec3ab FB |
755 | |
756 | spin_lock_irqsave(&dwc->lock, flags); | |
757 | val = dwc3_core_fifo_space(dep, DWC3_TXREQQ); | |
758 | seq_printf(s, "%u\n", val); | |
759 | spin_unlock_irqrestore(&dwc->lock, flags); | |
760 | ||
614ce6a2 UG |
761 | pm_runtime_put_sync(dwc->dev); |
762 | ||
818ec3ab FB |
763 | return 0; |
764 | } | |
765 | ||
766 | static int dwc3_rx_request_queue_show(struct seq_file *s, void *unused) | |
767 | { | |
768 | struct dwc3_ep *dep = s->private; | |
769 | struct dwc3 *dwc = dep->dwc; | |
770 | unsigned long flags; | |
771 | u32 val; | |
614ce6a2 UG |
772 | int ret; |
773 | ||
774 | ret = pm_runtime_resume_and_get(dwc->dev); | |
775 | if (ret < 0) | |
776 | return ret; | |
818ec3ab FB |
777 | |
778 | spin_lock_irqsave(&dwc->lock, flags); | |
779 | val = dwc3_core_fifo_space(dep, DWC3_RXREQQ); | |
780 | seq_printf(s, "%u\n", val); | |
781 | spin_unlock_irqrestore(&dwc->lock, flags); | |
782 | ||
614ce6a2 UG |
783 | pm_runtime_put_sync(dwc->dev); |
784 | ||
818ec3ab FB |
785 | return 0; |
786 | } | |
787 | ||
788 | static int dwc3_rx_info_queue_show(struct seq_file *s, void *unused) | |
789 | { | |
790 | struct dwc3_ep *dep = s->private; | |
791 | struct dwc3 *dwc = dep->dwc; | |
792 | unsigned long flags; | |
793 | u32 val; | |
614ce6a2 UG |
794 | int ret; |
795 | ||
796 | ret = pm_runtime_resume_and_get(dwc->dev); | |
797 | if (ret < 0) | |
798 | return ret; | |
818ec3ab FB |
799 | |
800 | spin_lock_irqsave(&dwc->lock, flags); | |
801 | val = dwc3_core_fifo_space(dep, DWC3_RXINFOQ); | |
802 | seq_printf(s, "%u\n", val); | |
803 | spin_unlock_irqrestore(&dwc->lock, flags); | |
804 | ||
614ce6a2 UG |
805 | pm_runtime_put_sync(dwc->dev); |
806 | ||
818ec3ab FB |
807 | return 0; |
808 | } | |
809 | ||
810 | static int dwc3_descriptor_fetch_queue_show(struct seq_file *s, void *unused) | |
811 | { | |
812 | struct dwc3_ep *dep = s->private; | |
813 | struct dwc3 *dwc = dep->dwc; | |
814 | unsigned long flags; | |
815 | u32 val; | |
614ce6a2 UG |
816 | int ret; |
817 | ||
818 | ret = pm_runtime_resume_and_get(dwc->dev); | |
819 | if (ret < 0) | |
820 | return ret; | |
818ec3ab FB |
821 | |
822 | spin_lock_irqsave(&dwc->lock, flags); | |
823 | val = dwc3_core_fifo_space(dep, DWC3_DESCFETCHQ); | |
824 | seq_printf(s, "%u\n", val); | |
825 | spin_unlock_irqrestore(&dwc->lock, flags); | |
826 | ||
614ce6a2 UG |
827 | pm_runtime_put_sync(dwc->dev); |
828 | ||
818ec3ab FB |
829 | return 0; |
830 | } | |
831 | ||
832 | static int dwc3_event_queue_show(struct seq_file *s, void *unused) | |
833 | { | |
834 | struct dwc3_ep *dep = s->private; | |
835 | struct dwc3 *dwc = dep->dwc; | |
836 | unsigned long flags; | |
837 | u32 val; | |
614ce6a2 UG |
838 | int ret; |
839 | ||
840 | ret = pm_runtime_resume_and_get(dwc->dev); | |
841 | if (ret < 0) | |
842 | return ret; | |
818ec3ab FB |
843 | |
844 | spin_lock_irqsave(&dwc->lock, flags); | |
845 | val = dwc3_core_fifo_space(dep, DWC3_EVENTQ); | |
846 | seq_printf(s, "%u\n", val); | |
847 | spin_unlock_irqrestore(&dwc->lock, flags); | |
848 | ||
614ce6a2 UG |
849 | pm_runtime_put_sync(dwc->dev); |
850 | ||
818ec3ab FB |
851 | return 0; |
852 | } | |
853 | ||
6d5b53c1 | 854 | static int dwc3_transfer_type_show(struct seq_file *s, void *unused) |
818ec3ab FB |
855 | { |
856 | struct dwc3_ep *dep = s->private; | |
857 | struct dwc3 *dwc = dep->dwc; | |
858 | unsigned long flags; | |
859 | ||
860 | spin_lock_irqsave(&dwc->lock, flags); | |
9ae0eb45 FB |
861 | if (!(dep->flags & DWC3_EP_ENABLED) || !dep->endpoint.desc) { |
862 | seq_puts(s, "--\n"); | |
818ec3ab FB |
863 | goto out; |
864 | } | |
865 | ||
866 | switch (usb_endpoint_type(dep->endpoint.desc)) { | |
867 | case USB_ENDPOINT_XFER_CONTROL: | |
9ae0eb45 | 868 | seq_puts(s, "control\n"); |
818ec3ab FB |
869 | break; |
870 | case USB_ENDPOINT_XFER_ISOC: | |
9ae0eb45 | 871 | seq_puts(s, "isochronous\n"); |
818ec3ab FB |
872 | break; |
873 | case USB_ENDPOINT_XFER_BULK: | |
9ae0eb45 | 874 | seq_puts(s, "bulk\n"); |
818ec3ab FB |
875 | break; |
876 | case USB_ENDPOINT_XFER_INT: | |
9ae0eb45 | 877 | seq_puts(s, "interrupt\n"); |
818ec3ab FB |
878 | break; |
879 | default: | |
9ae0eb45 | 880 | seq_puts(s, "--\n"); |
818ec3ab FB |
881 | } |
882 | ||
883 | out: | |
884 | spin_unlock_irqrestore(&dwc->lock, flags); | |
885 | ||
886 | return 0; | |
887 | } | |
888 | ||
6d5b53c1 | 889 | static int dwc3_trb_ring_show(struct seq_file *s, void *unused) |
818ec3ab FB |
890 | { |
891 | struct dwc3_ep *dep = s->private; | |
892 | struct dwc3 *dwc = dep->dwc; | |
893 | unsigned long flags; | |
894 | int i; | |
614ce6a2 UG |
895 | int ret; |
896 | ||
897 | ret = pm_runtime_resume_and_get(dwc->dev); | |
898 | if (ret < 0) | |
899 | return ret; | |
818ec3ab FB |
900 | |
901 | spin_lock_irqsave(&dwc->lock, flags); | |
902 | if (dep->number <= 1) { | |
9ae0eb45 | 903 | seq_puts(s, "--\n"); |
818ec3ab FB |
904 | goto out; |
905 | } | |
906 | ||
9ae0eb45 | 907 | seq_puts(s, "buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo\n"); |
818ec3ab FB |
908 | |
909 | for (i = 0; i < DWC3_TRB_NUM; i++) { | |
910 | struct dwc3_trb *trb = &dep->trb_pool[i]; | |
b5c7ed5c | 911 | unsigned int type = DWC3_TRBCTL_TYPE(trb->ctrl); |
818ec3ab | 912 | |
436841d5 | 913 | seq_printf(s, "%08x%08x,%d,%s,%d,%d,%d,%d,%d,%d %c%c\n", |
818ec3ab | 914 | trb->bph, trb->bpl, trb->size, |
b5c7ed5c | 915 | dwc3_trb_type_string(type), |
818ec3ab FB |
916 | !!(trb->ctrl & DWC3_TRB_CTRL_IOC), |
917 | !!(trb->ctrl & DWC3_TRB_CTRL_ISP_IMI), | |
918 | !!(trb->ctrl & DWC3_TRB_CTRL_CSP), | |
919 | !!(trb->ctrl & DWC3_TRB_CTRL_CHN), | |
920 | !!(trb->ctrl & DWC3_TRB_CTRL_LST), | |
436841d5 FB |
921 | !!(trb->ctrl & DWC3_TRB_CTRL_HWO), |
922 | dep->trb_enqueue == i ? 'E' : ' ', | |
923 | dep->trb_dequeue == i ? 'D' : ' '); | |
818ec3ab FB |
924 | } |
925 | ||
926 | out: | |
927 | spin_unlock_irqrestore(&dwc->lock, flags); | |
928 | ||
614ce6a2 UG |
929 | pm_runtime_put_sync(dwc->dev); |
930 | ||
818ec3ab FB |
931 | return 0; |
932 | } | |
933 | ||
62ba09d6 TN |
934 | static int dwc3_ep_info_register_show(struct seq_file *s, void *unused) |
935 | { | |
936 | struct dwc3_ep *dep = s->private; | |
937 | struct dwc3 *dwc = dep->dwc; | |
938 | unsigned long flags; | |
939 | u64 ep_info; | |
940 | u32 lower_32_bits; | |
941 | u32 upper_32_bits; | |
942 | u32 reg; | |
614ce6a2 UG |
943 | int ret; |
944 | ||
945 | ret = pm_runtime_resume_and_get(dwc->dev); | |
946 | if (ret < 0) | |
947 | return ret; | |
62ba09d6 TN |
948 | |
949 | spin_lock_irqsave(&dwc->lock, flags); | |
950 | reg = DWC3_GDBGLSPMUX_EPSELECT(dep->number); | |
951 | dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg); | |
952 | ||
953 | lower_32_bits = dwc3_readl(dwc->regs, DWC3_GDBGEPINFO0); | |
954 | upper_32_bits = dwc3_readl(dwc->regs, DWC3_GDBGEPINFO1); | |
955 | ||
956 | ep_info = ((u64)upper_32_bits << 32) | lower_32_bits; | |
957 | seq_printf(s, "0x%016llx\n", ep_info); | |
958 | spin_unlock_irqrestore(&dwc->lock, flags); | |
959 | ||
614ce6a2 UG |
960 | pm_runtime_put_sync(dwc->dev); |
961 | ||
62ba09d6 TN |
962 | return 0; |
963 | } | |
964 | ||
2c85a181 TN |
965 | DEFINE_SHOW_ATTRIBUTE(dwc3_tx_fifo_size); |
966 | DEFINE_SHOW_ATTRIBUTE(dwc3_rx_fifo_size); | |
6d5b53c1 FB |
967 | DEFINE_SHOW_ATTRIBUTE(dwc3_tx_request_queue); |
968 | DEFINE_SHOW_ATTRIBUTE(dwc3_rx_request_queue); | |
969 | DEFINE_SHOW_ATTRIBUTE(dwc3_rx_info_queue); | |
970 | DEFINE_SHOW_ATTRIBUTE(dwc3_descriptor_fetch_queue); | |
971 | DEFINE_SHOW_ATTRIBUTE(dwc3_event_queue); | |
972 | DEFINE_SHOW_ATTRIBUTE(dwc3_transfer_type); | |
973 | DEFINE_SHOW_ATTRIBUTE(dwc3_trb_ring); | |
62ba09d6 | 974 | DEFINE_SHOW_ATTRIBUTE(dwc3_ep_info_register); |
6d5b53c1 FB |
975 | |
976 | static const struct dwc3_ep_file_map dwc3_ep_file_map[] = { | |
2c85a181 TN |
977 | { "tx_fifo_size", &dwc3_tx_fifo_size_fops, }, |
978 | { "rx_fifo_size", &dwc3_rx_fifo_size_fops, }, | |
6d5b53c1 FB |
979 | { "tx_request_queue", &dwc3_tx_request_queue_fops, }, |
980 | { "rx_request_queue", &dwc3_rx_request_queue_fops, }, | |
981 | { "rx_info_queue", &dwc3_rx_info_queue_fops, }, | |
982 | { "descriptor_fetch_queue", &dwc3_descriptor_fetch_queue_fops, }, | |
983 | { "event_queue", &dwc3_event_queue_fops, }, | |
984 | { "transfer_type", &dwc3_transfer_type_fops, }, | |
985 | { "trb_ring", &dwc3_trb_ring_fops, }, | |
62ba09d6 | 986 | { "GDBGEPINFO", &dwc3_ep_info_register_fops, }, |
818ec3ab FB |
987 | }; |
988 | ||
be308d68 | 989 | void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep) |
818ec3ab | 990 | { |
be308d68 | 991 | struct dentry *dir; |
818ec3ab FB |
992 | int i; |
993 | ||
be308d68 | 994 | dir = debugfs_create_dir(dep->name, dep->dwc->debug_root); |
6d5b53c1 FB |
995 | for (i = 0; i < ARRAY_SIZE(dwc3_ep_file_map); i++) { |
996 | const struct file_operations *fops = dwc3_ep_file_map[i].fops; | |
997 | const char *name = dwc3_ep_file_map[i].name; | |
998 | ||
be308d68 | 999 | debugfs_create_file(name, 0444, dir, dep, fops); |
6d5b53c1 | 1000 | } |
818ec3ab FB |
1001 | } |
1002 | ||
be308d68 | 1003 | void dwc3_debugfs_remove_endpoint_dir(struct dwc3_ep *dep) |
818ec3ab | 1004 | { |
be308d68 | 1005 | debugfs_lookup_and_remove(dep->name, dep->dwc->debug_root); |
818ec3ab FB |
1006 | } |
1007 | ||
4e9f3118 | 1008 | void dwc3_debugfs_init(struct dwc3 *dwc) |
72246da4 FB |
1009 | { |
1010 | struct dentry *root; | |
72246da4 | 1011 | |
d7668024 | 1012 | dwc->regset = kzalloc(sizeof(*dwc->regset), GFP_KERNEL); |
535c8dc5 | 1013 | if (!dwc->regset) |
4e9f3118 | 1014 | return; |
d7668024 | 1015 | |
62ba09d6 TN |
1016 | dwc->dbg_lsp_select = DWC3_LSP_MUX_UNSELECTED; |
1017 | ||
d7668024 FB |
1018 | dwc->regset->regs = dwc3_regs; |
1019 | dwc->regset->nregs = ARRAY_SIZE(dwc3_regs); | |
2eb88016 | 1020 | dwc->regset->base = dwc->regs - DWC3_GLOBALS_REGS_START; |
614ce6a2 | 1021 | dwc->regset->dev = dwc->dev; |
d7668024 | 1022 | |
dcf5a2c3 | 1023 | root = debugfs_create_dir(dev_name(dwc->dev), usb_debug_root); |
be308d68 | 1024 | dwc->debug_root = root; |
9ae0eb45 FB |
1025 | debugfs_create_regset32("regdump", 0444, root, dwc->regset); |
1026 | debugfs_create_file("lsp_dump", 0644, root, dwc, &dwc3_lsp_fops); | |
0b9fe32d | 1027 | |
9ae0eb45 FB |
1028 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) |
1029 | debugfs_create_file("mode", 0644, root, dwc, | |
535c8dc5 | 1030 | &dwc3_mode_fops); |
0b9fe32d | 1031 | |
dbfff05d FB |
1032 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) || |
1033 | IS_ENABLED(CONFIG_USB_DWC3_GADGET)) { | |
9ae0eb45 FB |
1034 | debugfs_create_file("testmode", 0644, root, dwc, |
1035 | &dwc3_testmode_fops); | |
1036 | debugfs_create_file("link_state", 0644, root, dwc, | |
535c8dc5 | 1037 | &dwc3_link_state_fops); |
4e9f3118 | 1038 | } |
72246da4 FB |
1039 | } |
1040 | ||
fb4e98ab | 1041 | void dwc3_debugfs_exit(struct dwc3 *dwc) |
72246da4 | 1042 | { |
be308d68 | 1043 | debugfs_lookup_and_remove(dev_name(dwc->dev), usb_debug_root); |
e6bdf819 | 1044 | kfree(dwc->regset); |
72246da4 | 1045 | } |