blob: eb67c47295d76a524636e27ec8c6349a935aac7a [file] [log] [blame]
Felipe Balbi72246da2011-08-19 18:10:58 +03001/**
2 * debugfs.c - DesignWare USB3 DRD Controller DebugFS file
3 *
4 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
Felipe Balbi72246da2011-08-19 18:10:58 +03005 *
6 * Authors: Felipe Balbi <balbi@ti.com>,
7 * Sebastian Andrzej Siewior <bigeasy@linutronix.de>
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions, and the following disclaimer,
14 * without modification.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The names of the above-listed copyright holders may not be used
19 * to endorse or promote products derived from this software without
20 * specific prior written permission.
21 *
22 * ALTERNATIVELY, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") version 2, as published by the Free
24 * Software Foundation.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
27 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
28 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
30 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
Vijayavardhan Vennapusaffeb26b2013-02-14 16:33:30 +053039#include <linux/module.h>
Felipe Balbi72246da2011-08-19 18:10:58 +030040#include <linux/kernel.h>
41#include <linux/slab.h>
42#include <linux/ptrace.h>
43#include <linux/types.h>
44#include <linux/spinlock.h>
45#include <linux/debugfs.h>
46#include <linux/seq_file.h>
47#include <linux/delay.h>
Felipe Balbi25b8ff62011-11-04 12:32:47 +020048#include <linux/uaccess.h>
Felipe Balbi72246da2011-08-19 18:10:58 +030049
Felipe Balbi080d9212012-01-02 18:38:30 +020050#include <linux/usb/ch9.h>
51
Felipe Balbi72246da2011-08-19 18:10:58 +030052#include "core.h"
53#include "gadget.h"
54#include "io.h"
Felipe Balbi8becf272011-11-04 12:40:05 +020055#include "debug.h"
Felipe Balbi72246da2011-08-19 18:10:58 +030056
Felipe Balbi72246da2011-08-19 18:10:58 +030057#define dump_register(nm) \
58{ \
59 .name = __stringify(nm), \
Jack Pham7bcc6b12012-12-01 20:19:48 -080060 .offset = DWC3_ ##nm - DWC3_GLOBALS_REGS_START, \
Felipe Balbi72246da2011-08-19 18:10:58 +030061}
62
Alessandro Rubinic8d2a6f2011-11-18 14:51:43 +010063static const struct debugfs_reg32 dwc3_regs[] = {
Felipe Balbi72246da2011-08-19 18:10:58 +030064 dump_register(GSBUSCFG0),
65 dump_register(GSBUSCFG1),
66 dump_register(GTXTHRCFG),
67 dump_register(GRXTHRCFG),
68 dump_register(GCTL),
69 dump_register(GEVTEN),
70 dump_register(GSTS),
71 dump_register(GSNPSID),
72 dump_register(GGPIO),
73 dump_register(GUID),
74 dump_register(GUCTL),
75 dump_register(GBUSERRADDR0),
76 dump_register(GBUSERRADDR1),
77 dump_register(GPRTBIMAP0),
78 dump_register(GPRTBIMAP1),
79 dump_register(GHWPARAMS0),
80 dump_register(GHWPARAMS1),
81 dump_register(GHWPARAMS2),
82 dump_register(GHWPARAMS3),
83 dump_register(GHWPARAMS4),
84 dump_register(GHWPARAMS5),
85 dump_register(GHWPARAMS6),
86 dump_register(GHWPARAMS7),
87 dump_register(GDBGFIFOSPACE),
88 dump_register(GDBGLTSSM),
89 dump_register(GPRTBIMAP_HS0),
90 dump_register(GPRTBIMAP_HS1),
91 dump_register(GPRTBIMAP_FS0),
92 dump_register(GPRTBIMAP_FS1),
93
94 dump_register(GUSB2PHYCFG(0)),
95 dump_register(GUSB2PHYCFG(1)),
96 dump_register(GUSB2PHYCFG(2)),
97 dump_register(GUSB2PHYCFG(3)),
98 dump_register(GUSB2PHYCFG(4)),
99 dump_register(GUSB2PHYCFG(5)),
100 dump_register(GUSB2PHYCFG(6)),
101 dump_register(GUSB2PHYCFG(7)),
102 dump_register(GUSB2PHYCFG(8)),
103 dump_register(GUSB2PHYCFG(9)),
104 dump_register(GUSB2PHYCFG(10)),
105 dump_register(GUSB2PHYCFG(11)),
106 dump_register(GUSB2PHYCFG(12)),
107 dump_register(GUSB2PHYCFG(13)),
108 dump_register(GUSB2PHYCFG(14)),
109 dump_register(GUSB2PHYCFG(15)),
110
111 dump_register(GUSB2I2CCTL(0)),
112 dump_register(GUSB2I2CCTL(1)),
113 dump_register(GUSB2I2CCTL(2)),
114 dump_register(GUSB2I2CCTL(3)),
115 dump_register(GUSB2I2CCTL(4)),
116 dump_register(GUSB2I2CCTL(5)),
117 dump_register(GUSB2I2CCTL(6)),
118 dump_register(GUSB2I2CCTL(7)),
119 dump_register(GUSB2I2CCTL(8)),
120 dump_register(GUSB2I2CCTL(9)),
121 dump_register(GUSB2I2CCTL(10)),
122 dump_register(GUSB2I2CCTL(11)),
123 dump_register(GUSB2I2CCTL(12)),
124 dump_register(GUSB2I2CCTL(13)),
125 dump_register(GUSB2I2CCTL(14)),
126 dump_register(GUSB2I2CCTL(15)),
127
128 dump_register(GUSB2PHYACC(0)),
129 dump_register(GUSB2PHYACC(1)),
130 dump_register(GUSB2PHYACC(2)),
131 dump_register(GUSB2PHYACC(3)),
132 dump_register(GUSB2PHYACC(4)),
133 dump_register(GUSB2PHYACC(5)),
134 dump_register(GUSB2PHYACC(6)),
135 dump_register(GUSB2PHYACC(7)),
136 dump_register(GUSB2PHYACC(8)),
137 dump_register(GUSB2PHYACC(9)),
138 dump_register(GUSB2PHYACC(10)),
139 dump_register(GUSB2PHYACC(11)),
140 dump_register(GUSB2PHYACC(12)),
141 dump_register(GUSB2PHYACC(13)),
142 dump_register(GUSB2PHYACC(14)),
143 dump_register(GUSB2PHYACC(15)),
144
145 dump_register(GUSB3PIPECTL(0)),
146 dump_register(GUSB3PIPECTL(1)),
147 dump_register(GUSB3PIPECTL(2)),
148 dump_register(GUSB3PIPECTL(3)),
149 dump_register(GUSB3PIPECTL(4)),
150 dump_register(GUSB3PIPECTL(5)),
151 dump_register(GUSB3PIPECTL(6)),
152 dump_register(GUSB3PIPECTL(7)),
153 dump_register(GUSB3PIPECTL(8)),
154 dump_register(GUSB3PIPECTL(9)),
155 dump_register(GUSB3PIPECTL(10)),
156 dump_register(GUSB3PIPECTL(11)),
157 dump_register(GUSB3PIPECTL(12)),
158 dump_register(GUSB3PIPECTL(13)),
159 dump_register(GUSB3PIPECTL(14)),
160 dump_register(GUSB3PIPECTL(15)),
161
162 dump_register(GTXFIFOSIZ(0)),
163 dump_register(GTXFIFOSIZ(1)),
164 dump_register(GTXFIFOSIZ(2)),
165 dump_register(GTXFIFOSIZ(3)),
166 dump_register(GTXFIFOSIZ(4)),
167 dump_register(GTXFIFOSIZ(5)),
168 dump_register(GTXFIFOSIZ(6)),
169 dump_register(GTXFIFOSIZ(7)),
170 dump_register(GTXFIFOSIZ(8)),
171 dump_register(GTXFIFOSIZ(9)),
172 dump_register(GTXFIFOSIZ(10)),
173 dump_register(GTXFIFOSIZ(11)),
174 dump_register(GTXFIFOSIZ(12)),
175 dump_register(GTXFIFOSIZ(13)),
176 dump_register(GTXFIFOSIZ(14)),
177 dump_register(GTXFIFOSIZ(15)),
178 dump_register(GTXFIFOSIZ(16)),
179 dump_register(GTXFIFOSIZ(17)),
180 dump_register(GTXFIFOSIZ(18)),
181 dump_register(GTXFIFOSIZ(19)),
182 dump_register(GTXFIFOSIZ(20)),
183 dump_register(GTXFIFOSIZ(21)),
184 dump_register(GTXFIFOSIZ(22)),
185 dump_register(GTXFIFOSIZ(23)),
186 dump_register(GTXFIFOSIZ(24)),
187 dump_register(GTXFIFOSIZ(25)),
188 dump_register(GTXFIFOSIZ(26)),
189 dump_register(GTXFIFOSIZ(27)),
190 dump_register(GTXFIFOSIZ(28)),
191 dump_register(GTXFIFOSIZ(29)),
192 dump_register(GTXFIFOSIZ(30)),
193 dump_register(GTXFIFOSIZ(31)),
194
195 dump_register(GRXFIFOSIZ(0)),
196 dump_register(GRXFIFOSIZ(1)),
197 dump_register(GRXFIFOSIZ(2)),
198 dump_register(GRXFIFOSIZ(3)),
199 dump_register(GRXFIFOSIZ(4)),
200 dump_register(GRXFIFOSIZ(5)),
201 dump_register(GRXFIFOSIZ(6)),
202 dump_register(GRXFIFOSIZ(7)),
203 dump_register(GRXFIFOSIZ(8)),
204 dump_register(GRXFIFOSIZ(9)),
205 dump_register(GRXFIFOSIZ(10)),
206 dump_register(GRXFIFOSIZ(11)),
207 dump_register(GRXFIFOSIZ(12)),
208 dump_register(GRXFIFOSIZ(13)),
209 dump_register(GRXFIFOSIZ(14)),
210 dump_register(GRXFIFOSIZ(15)),
211 dump_register(GRXFIFOSIZ(16)),
212 dump_register(GRXFIFOSIZ(17)),
213 dump_register(GRXFIFOSIZ(18)),
214 dump_register(GRXFIFOSIZ(19)),
215 dump_register(GRXFIFOSIZ(20)),
216 dump_register(GRXFIFOSIZ(21)),
217 dump_register(GRXFIFOSIZ(22)),
218 dump_register(GRXFIFOSIZ(23)),
219 dump_register(GRXFIFOSIZ(24)),
220 dump_register(GRXFIFOSIZ(25)),
221 dump_register(GRXFIFOSIZ(26)),
222 dump_register(GRXFIFOSIZ(27)),
223 dump_register(GRXFIFOSIZ(28)),
224 dump_register(GRXFIFOSIZ(29)),
225 dump_register(GRXFIFOSIZ(30)),
226 dump_register(GRXFIFOSIZ(31)),
227
228 dump_register(GEVNTADRLO(0)),
229 dump_register(GEVNTADRHI(0)),
230 dump_register(GEVNTSIZ(0)),
231 dump_register(GEVNTCOUNT(0)),
232
233 dump_register(GHWPARAMS8),
Jack Pham1b309192014-04-16 11:54:55 +0530234 dump_register(GFLADJ),
Felipe Balbi72246da2011-08-19 18:10:58 +0300235 dump_register(DCFG),
236 dump_register(DCTL),
237 dump_register(DEVTEN),
238 dump_register(DSTS),
239 dump_register(DGCMDPAR),
240 dump_register(DGCMD),
241 dump_register(DALEPENA),
242
243 dump_register(DEPCMDPAR2(0)),
244 dump_register(DEPCMDPAR2(1)),
245 dump_register(DEPCMDPAR2(2)),
246 dump_register(DEPCMDPAR2(3)),
247 dump_register(DEPCMDPAR2(4)),
248 dump_register(DEPCMDPAR2(5)),
249 dump_register(DEPCMDPAR2(6)),
250 dump_register(DEPCMDPAR2(7)),
251 dump_register(DEPCMDPAR2(8)),
252 dump_register(DEPCMDPAR2(9)),
253 dump_register(DEPCMDPAR2(10)),
254 dump_register(DEPCMDPAR2(11)),
255 dump_register(DEPCMDPAR2(12)),
256 dump_register(DEPCMDPAR2(13)),
257 dump_register(DEPCMDPAR2(14)),
258 dump_register(DEPCMDPAR2(15)),
259 dump_register(DEPCMDPAR2(16)),
260 dump_register(DEPCMDPAR2(17)),
261 dump_register(DEPCMDPAR2(18)),
262 dump_register(DEPCMDPAR2(19)),
263 dump_register(DEPCMDPAR2(20)),
264 dump_register(DEPCMDPAR2(21)),
265 dump_register(DEPCMDPAR2(22)),
266 dump_register(DEPCMDPAR2(23)),
267 dump_register(DEPCMDPAR2(24)),
268 dump_register(DEPCMDPAR2(25)),
269 dump_register(DEPCMDPAR2(26)),
270 dump_register(DEPCMDPAR2(27)),
271 dump_register(DEPCMDPAR2(28)),
272 dump_register(DEPCMDPAR2(29)),
273 dump_register(DEPCMDPAR2(30)),
274 dump_register(DEPCMDPAR2(31)),
275
276 dump_register(DEPCMDPAR1(0)),
277 dump_register(DEPCMDPAR1(1)),
278 dump_register(DEPCMDPAR1(2)),
279 dump_register(DEPCMDPAR1(3)),
280 dump_register(DEPCMDPAR1(4)),
281 dump_register(DEPCMDPAR1(5)),
282 dump_register(DEPCMDPAR1(6)),
283 dump_register(DEPCMDPAR1(7)),
284 dump_register(DEPCMDPAR1(8)),
285 dump_register(DEPCMDPAR1(9)),
286 dump_register(DEPCMDPAR1(10)),
287 dump_register(DEPCMDPAR1(11)),
288 dump_register(DEPCMDPAR1(12)),
289 dump_register(DEPCMDPAR1(13)),
290 dump_register(DEPCMDPAR1(14)),
291 dump_register(DEPCMDPAR1(15)),
292 dump_register(DEPCMDPAR1(16)),
293 dump_register(DEPCMDPAR1(17)),
294 dump_register(DEPCMDPAR1(18)),
295 dump_register(DEPCMDPAR1(19)),
296 dump_register(DEPCMDPAR1(20)),
297 dump_register(DEPCMDPAR1(21)),
298 dump_register(DEPCMDPAR1(22)),
299 dump_register(DEPCMDPAR1(23)),
300 dump_register(DEPCMDPAR1(24)),
301 dump_register(DEPCMDPAR1(25)),
302 dump_register(DEPCMDPAR1(26)),
303 dump_register(DEPCMDPAR1(27)),
304 dump_register(DEPCMDPAR1(28)),
305 dump_register(DEPCMDPAR1(29)),
306 dump_register(DEPCMDPAR1(30)),
307 dump_register(DEPCMDPAR1(31)),
308
309 dump_register(DEPCMDPAR0(0)),
310 dump_register(DEPCMDPAR0(1)),
311 dump_register(DEPCMDPAR0(2)),
312 dump_register(DEPCMDPAR0(3)),
313 dump_register(DEPCMDPAR0(4)),
314 dump_register(DEPCMDPAR0(5)),
315 dump_register(DEPCMDPAR0(6)),
316 dump_register(DEPCMDPAR0(7)),
317 dump_register(DEPCMDPAR0(8)),
318 dump_register(DEPCMDPAR0(9)),
319 dump_register(DEPCMDPAR0(10)),
320 dump_register(DEPCMDPAR0(11)),
321 dump_register(DEPCMDPAR0(12)),
322 dump_register(DEPCMDPAR0(13)),
323 dump_register(DEPCMDPAR0(14)),
324 dump_register(DEPCMDPAR0(15)),
325 dump_register(DEPCMDPAR0(16)),
326 dump_register(DEPCMDPAR0(17)),
327 dump_register(DEPCMDPAR0(18)),
328 dump_register(DEPCMDPAR0(19)),
329 dump_register(DEPCMDPAR0(20)),
330 dump_register(DEPCMDPAR0(21)),
331 dump_register(DEPCMDPAR0(22)),
332 dump_register(DEPCMDPAR0(23)),
333 dump_register(DEPCMDPAR0(24)),
334 dump_register(DEPCMDPAR0(25)),
335 dump_register(DEPCMDPAR0(26)),
336 dump_register(DEPCMDPAR0(27)),
337 dump_register(DEPCMDPAR0(28)),
338 dump_register(DEPCMDPAR0(29)),
339 dump_register(DEPCMDPAR0(30)),
340 dump_register(DEPCMDPAR0(31)),
341
342 dump_register(DEPCMD(0)),
343 dump_register(DEPCMD(1)),
344 dump_register(DEPCMD(2)),
345 dump_register(DEPCMD(3)),
346 dump_register(DEPCMD(4)),
347 dump_register(DEPCMD(5)),
348 dump_register(DEPCMD(6)),
349 dump_register(DEPCMD(7)),
350 dump_register(DEPCMD(8)),
351 dump_register(DEPCMD(9)),
352 dump_register(DEPCMD(10)),
353 dump_register(DEPCMD(11)),
354 dump_register(DEPCMD(12)),
355 dump_register(DEPCMD(13)),
356 dump_register(DEPCMD(14)),
357 dump_register(DEPCMD(15)),
358 dump_register(DEPCMD(16)),
359 dump_register(DEPCMD(17)),
360 dump_register(DEPCMD(18)),
361 dump_register(DEPCMD(19)),
362 dump_register(DEPCMD(20)),
363 dump_register(DEPCMD(21)),
364 dump_register(DEPCMD(22)),
365 dump_register(DEPCMD(23)),
366 dump_register(DEPCMD(24)),
367 dump_register(DEPCMD(25)),
368 dump_register(DEPCMD(26)),
369 dump_register(DEPCMD(27)),
370 dump_register(DEPCMD(28)),
371 dump_register(DEPCMD(29)),
372 dump_register(DEPCMD(30)),
373 dump_register(DEPCMD(31)),
374
375 dump_register(OCFG),
376 dump_register(OCTL),
377 dump_register(OEVTEN),
378 dump_register(OSTS),
379};
380
381static int dwc3_regdump_show(struct seq_file *s, void *unused)
382{
383 struct dwc3 *dwc = s->private;
Felipe Balbi72246da2011-08-19 18:10:58 +0300384
385 seq_printf(s, "DesignWare USB3 Core Register Dump\n");
Alessandro Rubinic8d2a6f2011-11-18 14:51:43 +0100386 debugfs_print_regs32(s, dwc3_regs, ARRAY_SIZE(dwc3_regs),
387 dwc->regs, "");
Felipe Balbi72246da2011-08-19 18:10:58 +0300388 return 0;
389}
390
391static int dwc3_regdump_open(struct inode *inode, struct file *file)
392{
393 return single_open(file, dwc3_regdump_show, inode->i_private);
394}
395
396static const struct file_operations dwc3_regdump_fops = {
397 .open = dwc3_regdump_open,
398 .read = seq_read,
399 .release = single_release,
400};
401
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300402static int dwc3_mode_show(struct seq_file *s, void *unused)
403{
404 struct dwc3 *dwc = s->private;
405 unsigned long flags;
406 u32 reg;
407
408 spin_lock_irqsave(&dwc->lock, flags);
409 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
410 spin_unlock_irqrestore(&dwc->lock, flags);
411
412 switch (DWC3_GCTL_PRTCAP(reg)) {
413 case DWC3_GCTL_PRTCAP_HOST:
414 seq_printf(s, "host\n");
415 break;
416 case DWC3_GCTL_PRTCAP_DEVICE:
417 seq_printf(s, "device\n");
418 break;
419 case DWC3_GCTL_PRTCAP_OTG:
420 seq_printf(s, "OTG\n");
421 break;
422 default:
423 seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg));
424 }
425
426 return 0;
427}
428
429static int dwc3_mode_open(struct inode *inode, struct file *file)
430{
431 return single_open(file, dwc3_mode_show, inode->i_private);
432}
433
434static ssize_t dwc3_mode_write(struct file *file,
435 const char __user *ubuf, size_t count, loff_t *ppos)
436{
437 struct seq_file *s = file->private_data;
438 struct dwc3 *dwc = s->private;
439 unsigned long flags;
Sebastian Andrzej Siewior3140e8c2011-10-31 22:25:40 +0100440 u32 mode = 0;
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300441 char buf[32];
442
443 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
444 return -EFAULT;
445
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300446 if (!strncmp(buf, "host", 4))
Sebastian Andrzej Siewior3140e8c2011-10-31 22:25:40 +0100447 mode |= DWC3_GCTL_PRTCAP_HOST;
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300448
449 if (!strncmp(buf, "device", 6))
Sebastian Andrzej Siewior3140e8c2011-10-31 22:25:40 +0100450 mode |= DWC3_GCTL_PRTCAP_DEVICE;
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300451
452 if (!strncmp(buf, "otg", 3))
Sebastian Andrzej Siewior3140e8c2011-10-31 22:25:40 +0100453 mode |= DWC3_GCTL_PRTCAP_OTG;
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300454
Sebastian Andrzej Siewior3140e8c2011-10-31 22:25:40 +0100455 if (mode) {
456 spin_lock_irqsave(&dwc->lock, flags);
457 dwc3_set_mode(dwc, mode);
458 spin_unlock_irqrestore(&dwc->lock, flags);
459 }
Felipe Balbi0b9fe322011-10-17 08:50:39 +0300460 return count;
461}
462
463static const struct file_operations dwc3_mode_fops = {
464 .open = dwc3_mode_open,
465 .write = dwc3_mode_write,
466 .read = seq_read,
467 .llseek = seq_lseek,
468 .release = single_release,
469};
470
Felipe Balbi080d9212012-01-02 18:38:30 +0200471static int dwc3_testmode_show(struct seq_file *s, void *unused)
472{
473 struct dwc3 *dwc = s->private;
474 unsigned long flags;
475 u32 reg;
476
477 spin_lock_irqsave(&dwc->lock, flags);
478 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
479 reg &= DWC3_DCTL_TSTCTRL_MASK;
480 reg >>= 1;
481 spin_unlock_irqrestore(&dwc->lock, flags);
482
483 switch (reg) {
484 case 0:
485 seq_printf(s, "no test\n");
486 break;
487 case TEST_J:
488 seq_printf(s, "test_j\n");
489 break;
490 case TEST_K:
491 seq_printf(s, "test_k\n");
492 break;
493 case TEST_SE0_NAK:
494 seq_printf(s, "test_se0_nak\n");
495 break;
496 case TEST_PACKET:
497 seq_printf(s, "test_packet\n");
498 break;
499 case TEST_FORCE_EN:
500 seq_printf(s, "test_force_enable\n");
501 break;
502 default:
503 seq_printf(s, "UNKNOWN %d\n", reg);
504 }
505
506 return 0;
507}
508
509static int dwc3_testmode_open(struct inode *inode, struct file *file)
510{
511 return single_open(file, dwc3_testmode_show, inode->i_private);
512}
513
514static ssize_t dwc3_testmode_write(struct file *file,
515 const char __user *ubuf, size_t count, loff_t *ppos)
516{
517 struct seq_file *s = file->private_data;
518 struct dwc3 *dwc = s->private;
519 unsigned long flags;
520 u32 testmode = 0;
521 char buf[32];
522
523 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
524 return -EFAULT;
525
526 if (!strncmp(buf, "test_j", 6))
527 testmode = TEST_J;
528 else if (!strncmp(buf, "test_k", 6))
529 testmode = TEST_K;
Gerard Cauvy09072542012-02-10 12:14:53 +0200530 else if (!strncmp(buf, "test_se0_nak", 12))
Felipe Balbi080d9212012-01-02 18:38:30 +0200531 testmode = TEST_SE0_NAK;
Gerard Cauvy09072542012-02-10 12:14:53 +0200532 else if (!strncmp(buf, "test_packet", 11))
Felipe Balbi080d9212012-01-02 18:38:30 +0200533 testmode = TEST_PACKET;
Gerard Cauvy09072542012-02-10 12:14:53 +0200534 else if (!strncmp(buf, "test_force_enable", 17))
Felipe Balbi080d9212012-01-02 18:38:30 +0200535 testmode = TEST_FORCE_EN;
536 else
537 testmode = 0;
538
539 spin_lock_irqsave(&dwc->lock, flags);
540 dwc3_gadget_set_test_mode(dwc, testmode);
541 spin_unlock_irqrestore(&dwc->lock, flags);
542
543 return count;
544}
545
546static const struct file_operations dwc3_testmode_fops = {
547 .open = dwc3_testmode_open,
548 .write = dwc3_testmode_write,
549 .read = seq_read,
550 .llseek = seq_lseek,
551 .release = single_release,
552};
553
Felipe Balbi138801a2012-01-02 19:25:16 +0200554static int dwc3_link_state_show(struct seq_file *s, void *unused)
555{
556 struct dwc3 *dwc = s->private;
557 unsigned long flags;
558 enum dwc3_link_state state;
559 u32 reg;
560
561 spin_lock_irqsave(&dwc->lock, flags);
562 reg = dwc3_readl(dwc->regs, DWC3_DSTS);
563 state = DWC3_DSTS_USBLNKST(reg);
564 spin_unlock_irqrestore(&dwc->lock, flags);
565
566 switch (state) {
567 case DWC3_LINK_STATE_U0:
568 seq_printf(s, "U0\n");
569 break;
570 case DWC3_LINK_STATE_U1:
571 seq_printf(s, "U1\n");
572 break;
573 case DWC3_LINK_STATE_U2:
574 seq_printf(s, "U2\n");
575 break;
576 case DWC3_LINK_STATE_U3:
577 seq_printf(s, "U3\n");
578 break;
579 case DWC3_LINK_STATE_SS_DIS:
580 seq_printf(s, "SS.Disabled\n");
581 break;
582 case DWC3_LINK_STATE_RX_DET:
583 seq_printf(s, "Rx.Detect\n");
584 break;
585 case DWC3_LINK_STATE_SS_INACT:
586 seq_printf(s, "SS.Inactive\n");
587 break;
588 case DWC3_LINK_STATE_POLL:
589 seq_printf(s, "Poll\n");
590 break;
591 case DWC3_LINK_STATE_RECOV:
592 seq_printf(s, "Recovery\n");
593 break;
594 case DWC3_LINK_STATE_HRESET:
595 seq_printf(s, "HRESET\n");
596 break;
597 case DWC3_LINK_STATE_CMPLY:
598 seq_printf(s, "Compliance\n");
599 break;
600 case DWC3_LINK_STATE_LPBK:
601 seq_printf(s, "Loopback\n");
602 break;
603 default:
604 seq_printf(s, "UNKNOWN %d\n", reg);
605 }
606
607 return 0;
608}
609
610static int dwc3_link_state_open(struct inode *inode, struct file *file)
611{
612 return single_open(file, dwc3_link_state_show, inode->i_private);
613}
614
615static ssize_t dwc3_link_state_write(struct file *file,
616 const char __user *ubuf, size_t count, loff_t *ppos)
617{
618 struct seq_file *s = file->private_data;
619 struct dwc3 *dwc = s->private;
620 unsigned long flags;
621 enum dwc3_link_state state = 0;
622 char buf[32];
623
624 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
625 return -EFAULT;
626
627 if (!strncmp(buf, "SS.Disabled", 11))
628 state = DWC3_LINK_STATE_SS_DIS;
629 else if (!strncmp(buf, "Rx.Detect", 9))
630 state = DWC3_LINK_STATE_RX_DET;
631 else if (!strncmp(buf, "SS.Inactive", 11))
632 state = DWC3_LINK_STATE_SS_INACT;
633 else if (!strncmp(buf, "Recovery", 8))
634 state = DWC3_LINK_STATE_RECOV;
635 else if (!strncmp(buf, "Compliance", 10))
636 state = DWC3_LINK_STATE_CMPLY;
637 else if (!strncmp(buf, "Loopback", 8))
638 state = DWC3_LINK_STATE_LPBK;
639 else
640 return -EINVAL;
641
642 spin_lock_irqsave(&dwc->lock, flags);
643 dwc3_gadget_set_link_state(dwc, state);
644 spin_unlock_irqrestore(&dwc->lock, flags);
645
646 return count;
647}
648
649static const struct file_operations dwc3_link_state_fops = {
650 .open = dwc3_link_state_open,
651 .write = dwc3_link_state_write,
652 .read = seq_read,
653 .llseek = seq_lseek,
654 .release = single_release,
655};
656
Vijayavardhan Vennapusaffeb26b2013-02-14 16:33:30 +0530657static int ep_num;
658static ssize_t dwc3_store_ep_num(struct file *file, const char __user *ubuf,
659 size_t count, loff_t *ppos)
660{
661 struct seq_file *s = file->private_data;
662 struct dwc3 *dwc = s->private;
663 char kbuf[10];
664 unsigned int num, dir;
665 unsigned long flags;
666
667 memset(kbuf, 0, 10);
668
669 if (copy_from_user(kbuf, ubuf, count > 10 ? 10 : count))
670 return -EFAULT;
671
672 if (sscanf(kbuf, "%u %u", &num, &dir) != 2)
673 return -EINVAL;
674
675 spin_lock_irqsave(&dwc->lock, flags);
676 ep_num = (num << 1) + dir;
677 spin_unlock_irqrestore(&dwc->lock, flags);
678
679 return count;
680}
681
682static int dwc3_ep_req_list_show(struct seq_file *s, void *unused)
683{
684 struct dwc3 *dwc = s->private;
685 struct dwc3_ep *dep;
686 struct dwc3_request *req = NULL;
687 struct list_head *ptr = NULL;
688 unsigned long flags;
689
690 spin_lock_irqsave(&dwc->lock, flags);
691 dep = dwc->eps[ep_num];
692
693 seq_printf(s, "%s request list: flags: 0x%x\n", dep->name, dep->flags);
694 list_for_each(ptr, &dep->request_list) {
695 req = list_entry(ptr, struct dwc3_request, list);
696
Hemant Kumar1b378d92013-04-19 11:24:05 -0700697 seq_printf(s,
698 "req:0x%p len: %d sts: %d dma:0x%pa num_sgs: %d\n",
Vijayavardhan Vennapusaffeb26b2013-02-14 16:33:30 +0530699 req, req->request.length, req->request.status,
Hemant Kumar1b378d92013-04-19 11:24:05 -0700700 &req->request.dma, req->request.num_sgs);
Vijayavardhan Vennapusaffeb26b2013-02-14 16:33:30 +0530701 }
702 spin_unlock_irqrestore(&dwc->lock, flags);
703
704 return 0;
705}
706
707static int dwc3_ep_req_list_open(struct inode *inode, struct file *file)
708{
709 return single_open(file, dwc3_ep_req_list_show, inode->i_private);
710}
711
712static const struct file_operations dwc3_ep_req_list_fops = {
713 .open = dwc3_ep_req_list_open,
714 .write = dwc3_store_ep_num,
715 .read = seq_read,
716 .llseek = seq_lseek,
717 .release = single_release,
718};
719
720static int dwc3_ep_queued_req_show(struct seq_file *s, void *unused)
721{
722 struct dwc3 *dwc = s->private;
723 struct dwc3_ep *dep;
724 struct dwc3_request *req = NULL;
725 struct list_head *ptr = NULL;
726 unsigned long flags;
727
728 spin_lock_irqsave(&dwc->lock, flags);
729 dep = dwc->eps[ep_num];
730
731 seq_printf(s, "%s queued reqs to HW: flags:0x%x\n", dep->name,
732 dep->flags);
733 list_for_each(ptr, &dep->req_queued) {
734 req = list_entry(ptr, struct dwc3_request, list);
735
Hemant Kumar1b378d92013-04-19 11:24:05 -0700736 seq_printf(s,
737 "req:0x%p len:%d sts:%d dma:%pa nsg:%d trb:0x%p\n",
Vijayavardhan Vennapusaffeb26b2013-02-14 16:33:30 +0530738 req, req->request.length, req->request.status,
Hemant Kumar1b378d92013-04-19 11:24:05 -0700739 &req->request.dma, req->request.num_sgs, req->trb);
Vijayavardhan Vennapusaffeb26b2013-02-14 16:33:30 +0530740 }
741 spin_unlock_irqrestore(&dwc->lock, flags);
742
743 return 0;
744}
745
746static int dwc3_ep_queued_req_open(struct inode *inode, struct file *file)
747{
748 return single_open(file, dwc3_ep_queued_req_show, inode->i_private);
749}
750
751const struct file_operations dwc3_ep_req_queued_fops = {
752 .open = dwc3_ep_queued_req_open,
753 .write = dwc3_store_ep_num,
754 .read = seq_read,
755 .llseek = seq_lseek,
756 .release = single_release,
757};
758
759static int dwc3_ep_trbs_show(struct seq_file *s, void *unused)
760{
761 struct dwc3 *dwc = s->private;
762 struct dwc3_ep *dep;
763 struct dwc3_trb *trb;
764 unsigned long flags;
765 int j;
766
767 if (!ep_num)
768 return 0;
769
770 spin_lock_irqsave(&dwc->lock, flags);
771 dep = dwc->eps[ep_num];
772
773 seq_printf(s, "%s trb pool: flags:0x%x freeslot:%d busyslot:%d\n",
774 dep->name, dep->flags, dep->free_slot, dep->busy_slot);
775 for (j = 0; j < DWC3_TRB_NUM; j++) {
776 trb = &dep->trb_pool[j];
777 seq_printf(s, "trb:0x%p bph:0x%x bpl:0x%x size:0x%x ctrl: %x\n",
778 trb, trb->bph, trb->bpl, trb->size, trb->ctrl);
779 }
780 spin_unlock_irqrestore(&dwc->lock, flags);
781
782 return 0;
783}
784
785static int dwc3_ep_trbs_list_open(struct inode *inode, struct file *file)
786{
787 return single_open(file, dwc3_ep_trbs_show, inode->i_private);
788}
789
790const struct file_operations dwc3_ep_trb_list_fops = {
791 .open = dwc3_ep_trbs_list_open,
792 .write = dwc3_store_ep_num,
793 .read = seq_read,
794 .llseek = seq_lseek,
795 .release = single_release,
796};
797
Vijayavardhan Vennapusa3486b9d2013-11-29 12:46:34 +0530798static unsigned int ep_addr_rxdbg_mask = 1;
Vijayavardhan Vennapusaffeb26b2013-02-14 16:33:30 +0530799module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
Vijayavardhan Vennapusa3486b9d2013-11-29 12:46:34 +0530800static unsigned int ep_addr_txdbg_mask = 1;
Vijayavardhan Vennapusaffeb26b2013-02-14 16:33:30 +0530801module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
802
803/* Maximum debug message length */
804#define DBG_DATA_MSG 64UL
805
806/* Maximum number of messages */
807#define DBG_DATA_MAX 128UL
808
809static struct {
810 char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
811 unsigned idx; /* index */
812 unsigned tty; /* print to console? */
813 rwlock_t lck; /* lock */
814} dbg_dwc3_data = {
815 .idx = 0,
816 .tty = 0,
817 .lck = __RW_LOCK_UNLOCKED(lck)
818};
819
820/**
821 * dbg_dec: decrements debug event index
822 * @idx: buffer index
823 */
824static inline void __maybe_unused dbg_dec(unsigned *idx)
825{
826 *idx = (*idx - 1) % DBG_DATA_MAX;
827}
828
829/**
830 * dbg_inc: increments debug event index
831 * @idx: buffer index
832 */
833static inline void dbg_inc(unsigned *idx)
834{
835 *idx = (*idx + 1) % DBG_DATA_MAX;
836}
837
838#define TIME_BUF_LEN 20
839/*get_timestamp - returns time of day in us */
840static char *get_timestamp(char *tbuf)
841{
842 unsigned long long t;
843 unsigned long nanosec_rem;
844
845 t = cpu_clock(smp_processor_id());
846 nanosec_rem = do_div(t, 1000000000)/1000;
847 scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
848 nanosec_rem);
849 return tbuf;
850}
851
852static int allow_dbg_print(u8 ep_num)
853{
854 int dir, num;
855
856 /* allow bus wide events */
857 if (ep_num == 0xff)
858 return 1;
859
860 dir = ep_num & 0x1;
861 num = ep_num >> 1;
862 num = 1 << num;
863
864 if (dir && (num & ep_addr_txdbg_mask))
865 return 1;
866 if (!dir && (num & ep_addr_rxdbg_mask))
867 return 1;
868
869 return 0;
870}
871
872/**
873 * dbg_print: prints the common part of the event
874 * @addr: endpoint address
875 * @name: event name
876 * @status: status
877 * @extra: extra information
878 */
879void dbg_print(u8 ep_num, const char *name, int status, const char *extra)
880{
881 unsigned long flags;
882 char tbuf[TIME_BUF_LEN];
883
884 if (!allow_dbg_print(ep_num))
885 return;
886
887 write_lock_irqsave(&dbg_dwc3_data.lck, flags);
888
889 scnprintf(dbg_dwc3_data.buf[dbg_dwc3_data.idx], DBG_DATA_MSG,
890 "%s\t? %02X %-7.7s %4i ?\t%s\n",
891 get_timestamp(tbuf), ep_num, name, status, extra);
892
893 dbg_inc(&dbg_dwc3_data.idx);
894
895 write_unlock_irqrestore(&dbg_dwc3_data.lck, flags);
896
897 if (dbg_dwc3_data.tty != 0)
898 pr_notice("%s\t? %02X %-7.7s %4i ?\t%s\n",
899 get_timestamp(tbuf), ep_num, name, status, extra);
900}
901
902/**
903 * dbg_done: prints a DONE event
904 * @addr: endpoint address
905 * @td: transfer descriptor
906 * @status: status
907 */
908void dbg_done(u8 ep_num, const u32 count, int status)
909{
910 char msg[DBG_DATA_MSG];
911
912 if (!allow_dbg_print(ep_num))
913 return;
914
915 scnprintf(msg, sizeof(msg), "%d", count);
916 dbg_print(ep_num, "DONE", status, msg);
917}
918
919/**
920 * dbg_event: prints a generic event
921 * @addr: endpoint address
922 * @name: event name
923 * @status: status
924 */
925void dbg_event(u8 ep_num, const char *name, int status)
926{
927 if (!allow_dbg_print(ep_num))
928 return;
929
930 if (name != NULL)
931 dbg_print(ep_num, name, status, "");
932}
933
934/*
935 * dbg_queue: prints a QUEUE event
936 * @addr: endpoint address
937 * @req: USB request
938 * @status: status
939 */
940void dbg_queue(u8 ep_num, const struct usb_request *req, int status)
941{
942 char msg[DBG_DATA_MSG];
943
944 if (!allow_dbg_print(ep_num))
945 return;
946
947 if (req != NULL) {
948 scnprintf(msg, sizeof(msg),
949 "%d %d", !req->no_interrupt, req->length);
950 dbg_print(ep_num, "QUEUE", status, msg);
951 }
952}
953
954/**
955 * dbg_setup: prints a SETUP event
956 * @addr: endpoint address
957 * @req: setup request
958 */
959void dbg_setup(u8 ep_num, const struct usb_ctrlrequest *req)
960{
961 char msg[DBG_DATA_MSG];
962
963 if (!allow_dbg_print(ep_num))
964 return;
965
966 if (req != NULL) {
967 scnprintf(msg, sizeof(msg),
968 "%02X %02X %04X %04X %d", req->bRequestType,
969 req->bRequest, le16_to_cpu(req->wValue),
970 le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
971 dbg_print(ep_num, "SETUP", 0, msg);
972 }
973}
974
975/**
Vijayavardhan Vennapusa8a011c92013-07-29 09:06:48 +0530976 * dbg_print_reg: prints a reg value
977 * @name: reg name
978 * @reg: reg value to be printed
979 */
980void dbg_print_reg(const char *name, int reg)
981{
982 unsigned long flags;
983
984 write_lock_irqsave(&dbg_dwc3_data.lck, flags);
985
986 scnprintf(dbg_dwc3_data.buf[dbg_dwc3_data.idx], DBG_DATA_MSG,
987 "%s = 0x%08x\n", name, reg);
988
989 dbg_inc(&dbg_dwc3_data.idx);
990
991 write_unlock_irqrestore(&dbg_dwc3_data.lck, flags);
992
993 if (dbg_dwc3_data.tty != 0)
994 pr_notice("%s = 0x%08x\n", name, reg);
995}
996
997/**
Vijayavardhan Vennapusaffeb26b2013-02-14 16:33:30 +0530998 * store_events: configure if events are going to be also printed to console
999 *
1000 */
1001static ssize_t dwc3_store_events(struct file *file,
1002 const char __user *buf, size_t count, loff_t *ppos)
1003{
1004 unsigned tty;
1005
1006 if (buf == NULL) {
1007 pr_err("[%s] EINVAL\n", __func__);
1008 goto done;
1009 }
1010
1011 if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
1012 pr_err("<1|0>: enable|disable console log\n");
1013 goto done;
1014 }
1015
1016 dbg_dwc3_data.tty = tty;
1017 pr_info("tty = %u", dbg_dwc3_data.tty);
1018
1019 done:
1020 return count;
1021}
1022
1023static int dwc3_gadget_data_events_show(struct seq_file *s, void *unused)
1024{
1025 unsigned long flags;
1026 unsigned i;
1027
1028 read_lock_irqsave(&dbg_dwc3_data.lck, flags);
1029
1030 i = dbg_dwc3_data.idx;
1031 if (strnlen(dbg_dwc3_data.buf[i], DBG_DATA_MSG))
1032 seq_printf(s, "%s\n", dbg_dwc3_data.buf[i]);
1033 for (dbg_inc(&i); i != dbg_dwc3_data.idx; dbg_inc(&i)) {
1034 if (!strnlen(dbg_dwc3_data.buf[i], DBG_DATA_MSG))
1035 continue;
1036 seq_printf(s, "%s\n", dbg_dwc3_data.buf[i]);
1037 }
1038
1039 read_unlock_irqrestore(&dbg_dwc3_data.lck, flags);
1040
1041 return 0;
1042}
1043
1044static int dwc3_gadget_data_events_open(struct inode *inode, struct file *f)
1045{
1046 return single_open(f, dwc3_gadget_data_events_show, inode->i_private);
1047}
1048
1049const struct file_operations dwc3_gadget_dbg_data_fops = {
1050 .open = dwc3_gadget_data_events_open,
1051 .read = seq_read,
1052 .write = dwc3_store_events,
1053 .llseek = seq_lseek,
1054 .release = single_release,
1055};
1056
Felipe Balbi72246da2011-08-19 18:10:58 +03001057int __devinit dwc3_debugfs_init(struct dwc3 *dwc)
1058{
1059 struct dentry *root;
1060 struct dentry *file;
1061 int ret;
1062
1063 root = debugfs_create_dir(dev_name(dwc->dev), NULL);
Felipe Balbi3d4c0d42012-01-31 13:33:32 +02001064 if (!root) {
1065 ret = -ENOMEM;
Felipe Balbi72246da2011-08-19 18:10:58 +03001066 goto err0;
1067 }
1068
1069 dwc->root = root;
1070
1071 file = debugfs_create_file("regdump", S_IRUGO, root, dwc,
1072 &dwc3_regdump_fops);
Felipe Balbi3d4c0d42012-01-31 13:33:32 +02001073 if (!file) {
1074 ret = -ENOMEM;
Felipe Balbi72246da2011-08-19 18:10:58 +03001075 goto err1;
1076 }
Felipe Balbi0b9fe322011-10-17 08:50:39 +03001077
1078 file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
1079 dwc, &dwc3_mode_fops);
Felipe Balbi3d4c0d42012-01-31 13:33:32 +02001080 if (!file) {
1081 ret = -ENOMEM;
Felipe Balbi0b9fe322011-10-17 08:50:39 +03001082 goto err1;
1083 }
1084
Felipe Balbi080d9212012-01-02 18:38:30 +02001085 file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
1086 dwc, &dwc3_testmode_fops);
Felipe Balbi3d4c0d42012-01-31 13:33:32 +02001087 if (!file) {
1088 ret = -ENOMEM;
Felipe Balbi080d9212012-01-02 18:38:30 +02001089 goto err1;
1090 }
1091
Felipe Balbi138801a2012-01-02 19:25:16 +02001092 file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
1093 dwc, &dwc3_link_state_fops);
Felipe Balbi3d4c0d42012-01-31 13:33:32 +02001094 if (!file) {
1095 ret = -ENOMEM;
Felipe Balbi138801a2012-01-02 19:25:16 +02001096 goto err1;
1097 }
1098
Vijayavardhan Vennapusaffeb26b2013-02-14 16:33:30 +05301099 file = debugfs_create_file("trbs", S_IRUGO | S_IWUSR, root,
1100 dwc, &dwc3_ep_trb_list_fops);
1101 if (!file) {
1102 ret = -ENOMEM;
1103 goto err1;
1104 }
1105
1106 file = debugfs_create_file("requests", S_IRUGO | S_IWUSR, root,
1107 dwc, &dwc3_ep_req_list_fops);
1108 if (!file) {
1109 ret = -ENOMEM;
1110 goto err1;
1111 }
1112
1113 file = debugfs_create_file("queued_reqs", S_IRUGO | S_IWUSR, root,
1114 dwc, &dwc3_ep_req_queued_fops);
1115 if (!file) {
1116 ret = -ENOMEM;
1117 goto err1;
1118 }
1119
1120 file = debugfs_create_file("events", S_IRUGO | S_IWUSR, root,
1121 dwc, &dwc3_gadget_dbg_data_fops);
1122 if (!file) {
1123 ret = -ENOMEM;
1124 goto err1;
1125 }
Felipe Balbi72246da2011-08-19 18:10:58 +03001126 return 0;
1127
1128err1:
1129 debugfs_remove_recursive(root);
1130
1131err0:
1132 return ret;
1133}
1134
1135void __devexit dwc3_debugfs_exit(struct dwc3 *dwc)
1136{
1137 debugfs_remove_recursive(dwc->root);
1138 dwc->root = NULL;
1139}