blob: b104a878689650ac79b62d7e619ec98d93fa583d [file] [log] [blame]
Greg Kroah-Hartman5fd54ac2017-11-03 11:28:30 +01001// SPDX-License-Identifier: GPL-2.0
Felipe Balbi72246da2011-08-19 18:10:58 +03002/**
3 * debugfs.c - DesignWare USB3 DRD Controller DebugFS file
4 *
5 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
Felipe Balbi72246da2011-08-19 18:10:58 +03006 *
7 * Authors: Felipe Balbi <balbi@ti.com>,
8 * Sebastian Andrzej Siewior <bigeasy@linutronix.de>
9 *
Felipe Balbi5945f782013-06-30 14:15:11 +030010 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 of
12 * the License as published by the Free Software Foundation.
Felipe Balbi72246da2011-08-19 18:10:58 +030013 *
Felipe Balbi5945f782013-06-30 14:15:11 +030014 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
Felipe Balbi72246da2011-08-19 18:10:58 +030018 */
19
20#include <linux/kernel.h>
21#include <linux/slab.h>
22#include <linux/ptrace.h>
23#include <linux/types.h>
24#include <linux/spinlock.h>
25#include <linux/debugfs.h>
26#include <linux/seq_file.h>
27#include <linux/delay.h>
Felipe Balbi25b8ff62011-11-04 12:32:47 +020028#include <linux/uaccess.h>
Felipe Balbi72246da2011-08-19 18:10:58 +030029
Felipe Balbi080d9212012-01-02 18:38:30 +020030#include <linux/usb/ch9.h>
31
Felipe Balbi72246da2011-08-19 18:10:58 +030032#include "core.h"
33#include "gadget.h"
34#include "io.h"
Felipe Balbi8becf272011-11-04 12:40:05 +020035#include "debug.h"
Felipe Balbi72246da2011-08-19 18:10:58 +030036
Felipe Balbi72246da2011-08-19 18:10:58 +030037#define dump_register(nm) \
38{ \
39 .name = __stringify(nm), \
Felipe Balbi2eb88012016-04-12 16:53:39 +030040 .offset = DWC3_ ##nm, \
Felipe Balbi72246da2011-08-19 18:10:58 +030041}
42
Felipe Balbi2eb88012016-04-12 16:53:39 +030043#define dump_ep_register_set(n) \
44 { \
45 .name = "DEPCMDPAR2("__stringify(n)")", \
46 .offset = DWC3_DEP_BASE(n) + \
47 DWC3_DEPCMDPAR2, \
48 }, \
49 { \
50 .name = "DEPCMDPAR1("__stringify(n)")", \
51 .offset = DWC3_DEP_BASE(n) + \
52 DWC3_DEPCMDPAR1, \
53 }, \
54 { \
55 .name = "DEPCMDPAR0("__stringify(n)")", \
56 .offset = DWC3_DEP_BASE(n) + \
57 DWC3_DEPCMDPAR0, \
58 }, \
59 { \
60 .name = "DEPCMD("__stringify(n)")", \
61 .offset = DWC3_DEP_BASE(n) + \
62 DWC3_DEPCMD, \
63 }
64
65
Felipe Balbi4ec0ddb2013-02-22 16:17:31 +020066static const struct debugfs_reg32 dwc3_regs[] = {
Felipe Balbi72246da2011-08-19 18:10:58 +030067 dump_register(GSBUSCFG0),
68 dump_register(GSBUSCFG1),
69 dump_register(GTXTHRCFG),
70 dump_register(GRXTHRCFG),
71 dump_register(GCTL),
72 dump_register(GEVTEN),
73 dump_register(GSTS),
William Wu475c8be2016-05-13 18:13:46 +080074 dump_register(GUCTL1),
Felipe Balbi72246da2011-08-19 18:10:58 +030075 dump_register(GSNPSID),
76 dump_register(GGPIO),
77 dump_register(GUID),
78 dump_register(GUCTL),
79 dump_register(GBUSERRADDR0),
80 dump_register(GBUSERRADDR1),
81 dump_register(GPRTBIMAP0),
82 dump_register(GPRTBIMAP1),
83 dump_register(GHWPARAMS0),
84 dump_register(GHWPARAMS1),
85 dump_register(GHWPARAMS2),
86 dump_register(GHWPARAMS3),
87 dump_register(GHWPARAMS4),
88 dump_register(GHWPARAMS5),
89 dump_register(GHWPARAMS6),
90 dump_register(GHWPARAMS7),
91 dump_register(GDBGFIFOSPACE),
92 dump_register(GDBGLTSSM),
93 dump_register(GPRTBIMAP_HS0),
94 dump_register(GPRTBIMAP_HS1),
95 dump_register(GPRTBIMAP_FS0),
96 dump_register(GPRTBIMAP_FS1),
97
98 dump_register(GUSB2PHYCFG(0)),
99 dump_register(GUSB2PHYCFG(1)),
100 dump_register(GUSB2PHYCFG(2)),
101 dump_register(GUSB2PHYCFG(3)),
102 dump_register(GUSB2PHYCFG(4)),
103 dump_register(GUSB2PHYCFG(5)),
104 dump_register(GUSB2PHYCFG(6)),
105 dump_register(GUSB2PHYCFG(7)),
106 dump_register(GUSB2PHYCFG(8)),
107 dump_register(GUSB2PHYCFG(9)),
108 dump_register(GUSB2PHYCFG(10)),
109 dump_register(GUSB2PHYCFG(11)),
110 dump_register(GUSB2PHYCFG(12)),
111 dump_register(GUSB2PHYCFG(13)),
112 dump_register(GUSB2PHYCFG(14)),
113 dump_register(GUSB2PHYCFG(15)),
114
115 dump_register(GUSB2I2CCTL(0)),
116 dump_register(GUSB2I2CCTL(1)),
117 dump_register(GUSB2I2CCTL(2)),
118 dump_register(GUSB2I2CCTL(3)),
119 dump_register(GUSB2I2CCTL(4)),
120 dump_register(GUSB2I2CCTL(5)),
121 dump_register(GUSB2I2CCTL(6)),
122 dump_register(GUSB2I2CCTL(7)),
123 dump_register(GUSB2I2CCTL(8)),
124 dump_register(GUSB2I2CCTL(9)),
125 dump_register(GUSB2I2CCTL(10)),
126 dump_register(GUSB2I2CCTL(11)),
127 dump_register(GUSB2I2CCTL(12)),
128 dump_register(GUSB2I2CCTL(13)),
129 dump_register(GUSB2I2CCTL(14)),
130 dump_register(GUSB2I2CCTL(15)),
131
132 dump_register(GUSB2PHYACC(0)),
133 dump_register(GUSB2PHYACC(1)),
134 dump_register(GUSB2PHYACC(2)),
135 dump_register(GUSB2PHYACC(3)),
136 dump_register(GUSB2PHYACC(4)),
137 dump_register(GUSB2PHYACC(5)),
138 dump_register(GUSB2PHYACC(6)),
139 dump_register(GUSB2PHYACC(7)),
140 dump_register(GUSB2PHYACC(8)),
141 dump_register(GUSB2PHYACC(9)),
142 dump_register(GUSB2PHYACC(10)),
143 dump_register(GUSB2PHYACC(11)),
144 dump_register(GUSB2PHYACC(12)),
145 dump_register(GUSB2PHYACC(13)),
146 dump_register(GUSB2PHYACC(14)),
147 dump_register(GUSB2PHYACC(15)),
148
149 dump_register(GUSB3PIPECTL(0)),
150 dump_register(GUSB3PIPECTL(1)),
151 dump_register(GUSB3PIPECTL(2)),
152 dump_register(GUSB3PIPECTL(3)),
153 dump_register(GUSB3PIPECTL(4)),
154 dump_register(GUSB3PIPECTL(5)),
155 dump_register(GUSB3PIPECTL(6)),
156 dump_register(GUSB3PIPECTL(7)),
157 dump_register(GUSB3PIPECTL(8)),
158 dump_register(GUSB3PIPECTL(9)),
159 dump_register(GUSB3PIPECTL(10)),
160 dump_register(GUSB3PIPECTL(11)),
161 dump_register(GUSB3PIPECTL(12)),
162 dump_register(GUSB3PIPECTL(13)),
163 dump_register(GUSB3PIPECTL(14)),
164 dump_register(GUSB3PIPECTL(15)),
165
166 dump_register(GTXFIFOSIZ(0)),
167 dump_register(GTXFIFOSIZ(1)),
168 dump_register(GTXFIFOSIZ(2)),
169 dump_register(GTXFIFOSIZ(3)),
170 dump_register(GTXFIFOSIZ(4)),
171 dump_register(GTXFIFOSIZ(5)),
172 dump_register(GTXFIFOSIZ(6)),
173 dump_register(GTXFIFOSIZ(7)),
174 dump_register(GTXFIFOSIZ(8)),
175 dump_register(GTXFIFOSIZ(9)),
176 dump_register(GTXFIFOSIZ(10)),
177 dump_register(GTXFIFOSIZ(11)),
178 dump_register(GTXFIFOSIZ(12)),
179 dump_register(GTXFIFOSIZ(13)),
180 dump_register(GTXFIFOSIZ(14)),
181 dump_register(GTXFIFOSIZ(15)),
182 dump_register(GTXFIFOSIZ(16)),
183 dump_register(GTXFIFOSIZ(17)),
184 dump_register(GTXFIFOSIZ(18)),
185 dump_register(GTXFIFOSIZ(19)),
186 dump_register(GTXFIFOSIZ(20)),
187 dump_register(GTXFIFOSIZ(21)),
188 dump_register(GTXFIFOSIZ(22)),
189 dump_register(GTXFIFOSIZ(23)),
190 dump_register(GTXFIFOSIZ(24)),
191 dump_register(GTXFIFOSIZ(25)),
192 dump_register(GTXFIFOSIZ(26)),
193 dump_register(GTXFIFOSIZ(27)),
194 dump_register(GTXFIFOSIZ(28)),
195 dump_register(GTXFIFOSIZ(29)),
196 dump_register(GTXFIFOSIZ(30)),
197 dump_register(GTXFIFOSIZ(31)),
198
199 dump_register(GRXFIFOSIZ(0)),
200 dump_register(GRXFIFOSIZ(1)),
201 dump_register(GRXFIFOSIZ(2)),
202 dump_register(GRXFIFOSIZ(3)),
203 dump_register(GRXFIFOSIZ(4)),
204 dump_register(GRXFIFOSIZ(5)),
205 dump_register(GRXFIFOSIZ(6)),
206 dump_register(GRXFIFOSIZ(7)),
207 dump_register(GRXFIFOSIZ(8)),
208 dump_register(GRXFIFOSIZ(9)),
209 dump_register(GRXFIFOSIZ(10)),
210 dump_register(GRXFIFOSIZ(11)),
211 dump_register(GRXFIFOSIZ(12)),
212 dump_register(GRXFIFOSIZ(13)),
213 dump_register(GRXFIFOSIZ(14)),
214 dump_register(GRXFIFOSIZ(15)),
215 dump_register(GRXFIFOSIZ(16)),
216 dump_register(GRXFIFOSIZ(17)),
217 dump_register(GRXFIFOSIZ(18)),
218 dump_register(GRXFIFOSIZ(19)),
219 dump_register(GRXFIFOSIZ(20)),
220 dump_register(GRXFIFOSIZ(21)),
221 dump_register(GRXFIFOSIZ(22)),
222 dump_register(GRXFIFOSIZ(23)),
223 dump_register(GRXFIFOSIZ(24)),
224 dump_register(GRXFIFOSIZ(25)),
225 dump_register(GRXFIFOSIZ(26)),
226 dump_register(GRXFIFOSIZ(27)),
227 dump_register(GRXFIFOSIZ(28)),
228 dump_register(GRXFIFOSIZ(29)),
229 dump_register(GRXFIFOSIZ(30)),
230 dump_register(GRXFIFOSIZ(31)),
231
232 dump_register(GEVNTADRLO(0)),
233 dump_register(GEVNTADRHI(0)),
234 dump_register(GEVNTSIZ(0)),
235 dump_register(GEVNTCOUNT(0)),
236
237 dump_register(GHWPARAMS8),
238 dump_register(DCFG),
239 dump_register(DCTL),
240 dump_register(DEVTEN),
241 dump_register(DSTS),
242 dump_register(DGCMDPAR),
243 dump_register(DGCMD),
244 dump_register(DALEPENA),
245
Felipe Balbi2eb88012016-04-12 16:53:39 +0300246 dump_ep_register_set(0),
247 dump_ep_register_set(1),
248 dump_ep_register_set(2),
249 dump_ep_register_set(3),
250 dump_ep_register_set(4),
251 dump_ep_register_set(5),
252 dump_ep_register_set(6),
253 dump_ep_register_set(7),
254 dump_ep_register_set(8),
255 dump_ep_register_set(9),
256 dump_ep_register_set(10),
257 dump_ep_register_set(11),
258 dump_ep_register_set(12),
259 dump_ep_register_set(13),
260 dump_ep_register_set(14),
261 dump_ep_register_set(15),
262 dump_ep_register_set(16),
263 dump_ep_register_set(17),
264 dump_ep_register_set(18),
265 dump_ep_register_set(19),
266 dump_ep_register_set(20),
267 dump_ep_register_set(21),
268 dump_ep_register_set(22),
269 dump_ep_register_set(23),
270 dump_ep_register_set(24),
271 dump_ep_register_set(25),
272 dump_ep_register_set(26),
273 dump_ep_register_set(27),
274 dump_ep_register_set(28),
275 dump_ep_register_set(29),
276 dump_ep_register_set(30),
277 dump_ep_register_set(31),
Felipe Balbi72246da2011-08-19 18:10:58 +0300278
279 dump_register(OCFG),
280 dump_register(OCTL),
George Cheriand4436c32013-03-14 16:05:24 +0530281 dump_register(OEVT),
Felipe Balbi72246da2011-08-19 18:10:58 +0300282 dump_register(OEVTEN),
283 dump_register(OSTS),
284};
285
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300286static int dwc3_mode_show(struct seq_file *s, void *unused)
287{
288 struct dwc3 *dwc = s->private;
289 unsigned long flags;
290 u32 reg;
291
292 spin_lock_irqsave(&dwc->lock, flags);
293 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
294 spin_unlock_irqrestore(&dwc->lock, flags);
295
296 switch (DWC3_GCTL_PRTCAP(reg)) {
297 case DWC3_GCTL_PRTCAP_HOST:
298 seq_printf(s, "host\n");
299 break;
300 case DWC3_GCTL_PRTCAP_DEVICE:
301 seq_printf(s, "device\n");
302 break;
303 case DWC3_GCTL_PRTCAP_OTG:
Felipe Balbi2df301c2017-03-31 14:10:40 +0300304 seq_printf(s, "otg\n");
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300305 break;
306 default:
307 seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg));
308 }
309
310 return 0;
311}
312
313static int dwc3_mode_open(struct inode *inode, struct file *file)
314{
315 return single_open(file, dwc3_mode_show, inode->i_private);
316}
317
318static ssize_t dwc3_mode_write(struct file *file,
319 const char __user *ubuf, size_t count, loff_t *ppos)
320{
321 struct seq_file *s = file->private_data;
322 struct dwc3 *dwc = s->private;
Sebastian Andrzej Siewior3140e8cb2011-10-31 22:25:40 +0100323 u32 mode = 0;
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300324 char buf[32];
325
326 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
327 return -EFAULT;
328
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300329 if (!strncmp(buf, "host", 4))
Roger Quadrosb202c422017-04-04 11:27:57 +0300330 mode = DWC3_GCTL_PRTCAP_HOST;
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300331
332 if (!strncmp(buf, "device", 6))
Roger Quadrosb202c422017-04-04 11:27:57 +0300333 mode = DWC3_GCTL_PRTCAP_DEVICE;
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300334
335 if (!strncmp(buf, "otg", 3))
Roger Quadrosb202c422017-04-04 11:27:57 +0300336 mode = DWC3_GCTL_PRTCAP_OTG;
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300337
Roger Quadros41ce1452017-04-04 12:49:18 +0300338 dwc3_set_mode(dwc, mode);
339
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300340 return count;
341}
342
343static const struct file_operations dwc3_mode_fops = {
344 .open = dwc3_mode_open,
345 .write = dwc3_mode_write,
346 .read = seq_read,
347 .llseek = seq_lseek,
348 .release = single_release,
349};
350
Felipe Balbi080d9212012-01-02 18:38:30 +0200351static int dwc3_testmode_show(struct seq_file *s, void *unused)
352{
353 struct dwc3 *dwc = s->private;
354 unsigned long flags;
355 u32 reg;
356
357 spin_lock_irqsave(&dwc->lock, flags);
358 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
359 reg &= DWC3_DCTL_TSTCTRL_MASK;
360 reg >>= 1;
361 spin_unlock_irqrestore(&dwc->lock, flags);
362
363 switch (reg) {
364 case 0:
365 seq_printf(s, "no test\n");
366 break;
367 case TEST_J:
368 seq_printf(s, "test_j\n");
369 break;
370 case TEST_K:
371 seq_printf(s, "test_k\n");
372 break;
373 case TEST_SE0_NAK:
374 seq_printf(s, "test_se0_nak\n");
375 break;
376 case TEST_PACKET:
377 seq_printf(s, "test_packet\n");
378 break;
379 case TEST_FORCE_EN:
380 seq_printf(s, "test_force_enable\n");
381 break;
382 default:
383 seq_printf(s, "UNKNOWN %d\n", reg);
384 }
385
386 return 0;
387}
388
389static int dwc3_testmode_open(struct inode *inode, struct file *file)
390{
391 return single_open(file, dwc3_testmode_show, inode->i_private);
392}
393
394static ssize_t dwc3_testmode_write(struct file *file,
395 const char __user *ubuf, size_t count, loff_t *ppos)
396{
397 struct seq_file *s = file->private_data;
398 struct dwc3 *dwc = s->private;
399 unsigned long flags;
400 u32 testmode = 0;
401 char buf[32];
402
403 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
404 return -EFAULT;
405
406 if (!strncmp(buf, "test_j", 6))
407 testmode = TEST_J;
408 else if (!strncmp(buf, "test_k", 6))
409 testmode = TEST_K;
Gerard Cauvy09072542012-02-10 12:14:53 +0200410 else if (!strncmp(buf, "test_se0_nak", 12))
Felipe Balbi080d9212012-01-02 18:38:30 +0200411 testmode = TEST_SE0_NAK;
Gerard Cauvy09072542012-02-10 12:14:53 +0200412 else if (!strncmp(buf, "test_packet", 11))
Felipe Balbi080d9212012-01-02 18:38:30 +0200413 testmode = TEST_PACKET;
Gerard Cauvy09072542012-02-10 12:14:53 +0200414 else if (!strncmp(buf, "test_force_enable", 17))
Felipe Balbi080d9212012-01-02 18:38:30 +0200415 testmode = TEST_FORCE_EN;
416 else
417 testmode = 0;
418
419 spin_lock_irqsave(&dwc->lock, flags);
420 dwc3_gadget_set_test_mode(dwc, testmode);
421 spin_unlock_irqrestore(&dwc->lock, flags);
422
423 return count;
424}
425
426static const struct file_operations dwc3_testmode_fops = {
427 .open = dwc3_testmode_open,
428 .write = dwc3_testmode_write,
429 .read = seq_read,
430 .llseek = seq_lseek,
431 .release = single_release,
432};
433
Felipe Balbi138801a2012-01-02 19:25:16 +0200434static int dwc3_link_state_show(struct seq_file *s, void *unused)
435{
436 struct dwc3 *dwc = s->private;
437 unsigned long flags;
438 enum dwc3_link_state state;
439 u32 reg;
440
441 spin_lock_irqsave(&dwc->lock, flags);
442 reg = dwc3_readl(dwc->regs, DWC3_DSTS);
443 state = DWC3_DSTS_USBLNKST(reg);
444 spin_unlock_irqrestore(&dwc->lock, flags);
445
Felipe Balbi26c9f3e2017-03-31 14:28:33 +0300446 seq_printf(s, "%s\n", dwc3_gadget_link_string(state));
Felipe Balbi138801a2012-01-02 19:25:16 +0200447
448 return 0;
449}
450
451static int dwc3_link_state_open(struct inode *inode, struct file *file)
452{
453 return single_open(file, dwc3_link_state_show, inode->i_private);
454}
455
456static ssize_t dwc3_link_state_write(struct file *file,
457 const char __user *ubuf, size_t count, loff_t *ppos)
458{
459 struct seq_file *s = file->private_data;
460 struct dwc3 *dwc = s->private;
461 unsigned long flags;
462 enum dwc3_link_state state = 0;
463 char buf[32];
464
465 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
466 return -EFAULT;
467
468 if (!strncmp(buf, "SS.Disabled", 11))
469 state = DWC3_LINK_STATE_SS_DIS;
470 else if (!strncmp(buf, "Rx.Detect", 9))
471 state = DWC3_LINK_STATE_RX_DET;
472 else if (!strncmp(buf, "SS.Inactive", 11))
473 state = DWC3_LINK_STATE_SS_INACT;
474 else if (!strncmp(buf, "Recovery", 8))
475 state = DWC3_LINK_STATE_RECOV;
476 else if (!strncmp(buf, "Compliance", 10))
477 state = DWC3_LINK_STATE_CMPLY;
478 else if (!strncmp(buf, "Loopback", 8))
479 state = DWC3_LINK_STATE_LPBK;
480 else
481 return -EINVAL;
482
483 spin_lock_irqsave(&dwc->lock, flags);
484 dwc3_gadget_set_link_state(dwc, state);
485 spin_unlock_irqrestore(&dwc->lock, flags);
486
487 return count;
488}
489
490static const struct file_operations dwc3_link_state_fops = {
491 .open = dwc3_link_state_open,
492 .write = dwc3_link_state_write,
493 .read = seq_read,
494 .llseek = seq_lseek,
495 .release = single_release,
496};
497
Felipe Balbi818ec3a2016-04-14 14:53:44 +0300498struct dwc3_ep_file_map {
499 char name[25];
500 int (*show)(struct seq_file *s, void *unused);
501};
Felipe Balbi72246da2011-08-19 18:10:58 +0300502
Felipe Balbi818ec3a2016-04-14 14:53:44 +0300503static int dwc3_tx_fifo_queue_show(struct seq_file *s, void *unused)
504{
505 struct dwc3_ep *dep = s->private;
506 struct dwc3 *dwc = dep->dwc;
507 unsigned long flags;
508 u32 val;
509
510 spin_lock_irqsave(&dwc->lock, flags);
511 val = dwc3_core_fifo_space(dep, DWC3_TXFIFOQ);
512 seq_printf(s, "%u\n", val);
513 spin_unlock_irqrestore(&dwc->lock, flags);
514
515 return 0;
516}
517
518static int dwc3_rx_fifo_queue_show(struct seq_file *s, void *unused)
519{
520 struct dwc3_ep *dep = s->private;
521 struct dwc3 *dwc = dep->dwc;
522 unsigned long flags;
523 u32 val;
524
525 spin_lock_irqsave(&dwc->lock, flags);
526 val = dwc3_core_fifo_space(dep, DWC3_RXFIFOQ);
527 seq_printf(s, "%u\n", val);
528 spin_unlock_irqrestore(&dwc->lock, flags);
529
530 return 0;
531}
532
533static int dwc3_tx_request_queue_show(struct seq_file *s, void *unused)
534{
535 struct dwc3_ep *dep = s->private;
536 struct dwc3 *dwc = dep->dwc;
537 unsigned long flags;
538 u32 val;
539
540 spin_lock_irqsave(&dwc->lock, flags);
541 val = dwc3_core_fifo_space(dep, DWC3_TXREQQ);
542 seq_printf(s, "%u\n", val);
543 spin_unlock_irqrestore(&dwc->lock, flags);
544
545 return 0;
546}
547
548static int dwc3_rx_request_queue_show(struct seq_file *s, void *unused)
549{
550 struct dwc3_ep *dep = s->private;
551 struct dwc3 *dwc = dep->dwc;
552 unsigned long flags;
553 u32 val;
554
555 spin_lock_irqsave(&dwc->lock, flags);
556 val = dwc3_core_fifo_space(dep, DWC3_RXREQQ);
557 seq_printf(s, "%u\n", val);
558 spin_unlock_irqrestore(&dwc->lock, flags);
559
560 return 0;
561}
562
563static int dwc3_rx_info_queue_show(struct seq_file *s, void *unused)
564{
565 struct dwc3_ep *dep = s->private;
566 struct dwc3 *dwc = dep->dwc;
567 unsigned long flags;
568 u32 val;
569
570 spin_lock_irqsave(&dwc->lock, flags);
571 val = dwc3_core_fifo_space(dep, DWC3_RXINFOQ);
572 seq_printf(s, "%u\n", val);
573 spin_unlock_irqrestore(&dwc->lock, flags);
574
575 return 0;
576}
577
578static int dwc3_descriptor_fetch_queue_show(struct seq_file *s, void *unused)
579{
580 struct dwc3_ep *dep = s->private;
581 struct dwc3 *dwc = dep->dwc;
582 unsigned long flags;
583 u32 val;
584
585 spin_lock_irqsave(&dwc->lock, flags);
586 val = dwc3_core_fifo_space(dep, DWC3_DESCFETCHQ);
587 seq_printf(s, "%u\n", val);
588 spin_unlock_irqrestore(&dwc->lock, flags);
589
590 return 0;
591}
592
593static int dwc3_event_queue_show(struct seq_file *s, void *unused)
594{
595 struct dwc3_ep *dep = s->private;
596 struct dwc3 *dwc = dep->dwc;
597 unsigned long flags;
598 u32 val;
599
600 spin_lock_irqsave(&dwc->lock, flags);
601 val = dwc3_core_fifo_space(dep, DWC3_EVENTQ);
602 seq_printf(s, "%u\n", val);
603 spin_unlock_irqrestore(&dwc->lock, flags);
604
605 return 0;
606}
607
608static int dwc3_ep_transfer_type_show(struct seq_file *s, void *unused)
609{
610 struct dwc3_ep *dep = s->private;
611 struct dwc3 *dwc = dep->dwc;
612 unsigned long flags;
613
614 spin_lock_irqsave(&dwc->lock, flags);
615 if (!(dep->flags & DWC3_EP_ENABLED) ||
616 !dep->endpoint.desc) {
617 seq_printf(s, "--\n");
618 goto out;
Felipe Balbi72246da2011-08-19 18:10:58 +0300619 }
620
Felipe Balbi818ec3a2016-04-14 14:53:44 +0300621 switch (usb_endpoint_type(dep->endpoint.desc)) {
622 case USB_ENDPOINT_XFER_CONTROL:
623 seq_printf(s, "control\n");
624 break;
625 case USB_ENDPOINT_XFER_ISOC:
626 seq_printf(s, "isochronous\n");
627 break;
628 case USB_ENDPOINT_XFER_BULK:
629 seq_printf(s, "bulk\n");
630 break;
631 case USB_ENDPOINT_XFER_INT:
632 seq_printf(s, "interrupt\n");
633 break;
634 default:
635 seq_printf(s, "--\n");
636 }
637
638out:
639 spin_unlock_irqrestore(&dwc->lock, flags);
640
641 return 0;
642}
643
Felipe Balbi818ec3a2016-04-14 14:53:44 +0300644static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused)
645{
646 struct dwc3_ep *dep = s->private;
647 struct dwc3 *dwc = dep->dwc;
648 unsigned long flags;
649 int i;
650
651 spin_lock_irqsave(&dwc->lock, flags);
652 if (dep->number <= 1) {
653 seq_printf(s, "--\n");
654 goto out;
655 }
656
Felipe Balbi818ec3a2016-04-14 14:53:44 +0300657 seq_printf(s, "buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo\n");
658
659 for (i = 0; i < DWC3_TRB_NUM; i++) {
660 struct dwc3_trb *trb = &dep->trb_pool[i];
Felipe Balbib5c7ed52017-03-31 14:44:09 +0300661 unsigned int type = DWC3_TRBCTL_TYPE(trb->ctrl);
Felipe Balbi818ec3a2016-04-14 14:53:44 +0300662
Felipe Balbi436841d2017-04-20 15:21:27 +0300663 seq_printf(s, "%08x%08x,%d,%s,%d,%d,%d,%d,%d,%d %c%c\n",
Felipe Balbi818ec3a2016-04-14 14:53:44 +0300664 trb->bph, trb->bpl, trb->size,
Felipe Balbib5c7ed52017-03-31 14:44:09 +0300665 dwc3_trb_type_string(type),
Felipe Balbi818ec3a2016-04-14 14:53:44 +0300666 !!(trb->ctrl & DWC3_TRB_CTRL_IOC),
667 !!(trb->ctrl & DWC3_TRB_CTRL_ISP_IMI),
668 !!(trb->ctrl & DWC3_TRB_CTRL_CSP),
669 !!(trb->ctrl & DWC3_TRB_CTRL_CHN),
670 !!(trb->ctrl & DWC3_TRB_CTRL_LST),
Felipe Balbi436841d2017-04-20 15:21:27 +0300671 !!(trb->ctrl & DWC3_TRB_CTRL_HWO),
672 dep->trb_enqueue == i ? 'E' : ' ',
673 dep->trb_dequeue == i ? 'D' : ' ');
Felipe Balbi818ec3a2016-04-14 14:53:44 +0300674 }
675
676out:
677 spin_unlock_irqrestore(&dwc->lock, flags);
678
679 return 0;
680}
681
682static struct dwc3_ep_file_map map[] = {
683 { "tx_fifo_queue", dwc3_tx_fifo_queue_show, },
684 { "rx_fifo_queue", dwc3_rx_fifo_queue_show, },
685 { "tx_request_queue", dwc3_tx_request_queue_show, },
686 { "rx_request_queue", dwc3_rx_request_queue_show, },
687 { "rx_info_queue", dwc3_rx_info_queue_show, },
688 { "descriptor_fetch_queue", dwc3_descriptor_fetch_queue_show, },
689 { "event_queue", dwc3_event_queue_show, },
690 { "transfer_type", dwc3_ep_transfer_type_show, },
691 { "trb_ring", dwc3_ep_trb_ring_show, },
692};
693
694static int dwc3_endpoint_open(struct inode *inode, struct file *file)
695{
696 const char *file_name = file_dentry(file)->d_iname;
697 struct dwc3_ep_file_map *f_map;
698 int i;
699
700 for (i = 0; i < ARRAY_SIZE(map); i++) {
701 f_map = &map[i];
702
703 if (strcmp(f_map->name, file_name) == 0)
704 break;
705 }
706
707 return single_open(file, f_map->show, inode->i_private);
708}
709
710static const struct file_operations dwc3_endpoint_fops = {
711 .open = dwc3_endpoint_open,
712 .read = seq_read,
713 .llseek = seq_lseek,
714 .release = single_release,
715};
716
717static void dwc3_debugfs_create_endpoint_file(struct dwc3_ep *dep,
718 struct dentry *parent, int type)
719{
720 struct dentry *file;
721 struct dwc3_ep_file_map *ep_file = &map[type];
722
723 file = debugfs_create_file(ep_file->name, S_IRUGO, parent, dep,
724 &dwc3_endpoint_fops);
725}
726
727static void dwc3_debugfs_create_endpoint_files(struct dwc3_ep *dep,
728 struct dentry *parent)
729{
730 int i;
731
732 for (i = 0; i < ARRAY_SIZE(map); i++)
733 dwc3_debugfs_create_endpoint_file(dep, parent, i);
734}
735
736static void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep,
737 struct dentry *parent)
738{
739 struct dentry *dir;
740
741 dir = debugfs_create_dir(dep->name, parent);
742 if (IS_ERR_OR_NULL(dir))
743 return;
744
745 dwc3_debugfs_create_endpoint_files(dep, dir);
746}
747
748static void dwc3_debugfs_create_endpoint_dirs(struct dwc3 *dwc,
749 struct dentry *parent)
750{
751 int i;
752
Bryan O'Donoghue47d39462017-01-31 20:58:10 +0000753 for (i = 0; i < dwc->num_eps; i++) {
754 struct dwc3_ep *dep = dwc->eps[i];
Felipe Balbi818ec3a2016-04-14 14:53:44 +0300755
756 if (!dep)
757 continue;
758
759 dwc3_debugfs_create_endpoint_dir(dep, parent);
760 }
761}
762
Du, Changbin4e9f3112016-04-12 19:10:18 +0800763void dwc3_debugfs_init(struct dwc3 *dwc)
Felipe Balbi72246da2011-08-19 18:10:58 +0300764{
765 struct dentry *root;
Du, Changbin4e9f3112016-04-12 19:10:18 +0800766 struct dentry *file;
Felipe Balbi72246da2011-08-19 18:10:58 +0300767
768 root = debugfs_create_dir(dev_name(dwc->dev), NULL);
Du, Changbin4e9f3112016-04-12 19:10:18 +0800769 if (IS_ERR_OR_NULL(root)) {
770 if (!root)
771 dev_err(dwc->dev, "Can't create debugfs root\n");
772 return;
Felipe Balbi72246da2011-08-19 18:10:58 +0300773 }
Felipe Balbi72246da2011-08-19 18:10:58 +0300774 dwc->root = root;
775
Felipe Balbid76680242013-01-18 10:21:34 +0200776 dwc->regset = kzalloc(sizeof(*dwc->regset), GFP_KERNEL);
777 if (!dwc->regset) {
Du, Changbin4e9f3112016-04-12 19:10:18 +0800778 debugfs_remove_recursive(root);
779 return;
Felipe Balbid76680242013-01-18 10:21:34 +0200780 }
781
782 dwc->regset->regs = dwc3_regs;
783 dwc->regset->nregs = ARRAY_SIZE(dwc3_regs);
Felipe Balbi2eb88012016-04-12 16:53:39 +0300784 dwc->regset->base = dwc->regs - DWC3_GLOBALS_REGS_START;
Felipe Balbid76680242013-01-18 10:21:34 +0200785
786 file = debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset);
Du, Changbin4e9f3112016-04-12 19:10:18 +0800787 if (!file)
788 dev_dbg(dwc->dev, "Can't create debugfs regdump\n");
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300789
Felipe Balbidbfff052013-02-22 16:24:49 +0200790 if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) {
791 file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
792 dwc, &dwc3_mode_fops);
Du, Changbin4e9f3112016-04-12 19:10:18 +0800793 if (!file)
794 dev_dbg(dwc->dev, "Can't create debugfs mode\n");
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300795 }
796
Felipe Balbidbfff052013-02-22 16:24:49 +0200797 if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) ||
798 IS_ENABLED(CONFIG_USB_DWC3_GADGET)) {
799 file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
800 dwc, &dwc3_testmode_fops);
Du, Changbin4e9f3112016-04-12 19:10:18 +0800801 if (!file)
802 dev_dbg(dwc->dev, "Can't create debugfs testmode\n");
Felipe Balbi080d9212012-01-02 18:38:30 +0200803
Du, Changbin4e9f3112016-04-12 19:10:18 +0800804 file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR,
805 root, dwc, &dwc3_link_state_fops);
806 if (!file)
807 dev_dbg(dwc->dev, "Can't create debugfs link_state\n");
Felipe Balbi818ec3a2016-04-14 14:53:44 +0300808
809 dwc3_debugfs_create_endpoint_dirs(dwc, root);
Felipe Balbi138801a2012-01-02 19:25:16 +0200810 }
Felipe Balbi72246da2011-08-19 18:10:58 +0300811}
812
Bill Pembertonfb4e98a2012-11-19 13:26:20 -0500813void dwc3_debugfs_exit(struct dwc3 *dwc)
Felipe Balbi72246da2011-08-19 18:10:58 +0300814{
815 debugfs_remove_recursive(dwc->root);
Du, Changbine6bdf812016-04-12 16:24:34 +0800816 kfree(dwc->regset);
Felipe Balbi72246da2011-08-19 18:10:58 +0300817}