1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * debugfs.c - Designware USB2 DRD controller debugfs |
4 | * |
5 | * Copyright (C) 2015 Intel Corporation |
6 | * Mian Yousaf Kaukab <yousaf.kaukab@intel.com> |
7 | */ |
8 | |
9 | #include <linux/spinlock.h> |
10 | #include <linux/debugfs.h> |
11 | #include <linux/seq_file.h> |
12 | #include <linux/uaccess.h> |
13 | |
14 | #include "core.h" |
15 | #include "debug.h" |
16 | |
17 | #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ |
18 | IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) |
19 | |
20 | /** |
21 | * testmode_write() - change usb test mode state. |
22 | * @file: The file to write to. |
23 | * @ubuf: The buffer where user wrote. |
24 | * @count: The ubuf size. |
25 | * @ppos: Unused parameter. |
26 | */ |
27 | static ssize_t testmode_write(struct file *file, const char __user *ubuf, size_t |
28 | count, loff_t *ppos) |
29 | { |
30 | struct seq_file *s = file->private_data; |
31 | struct dwc2_hsotg *hsotg = s->private; |
32 | unsigned long flags; |
33 | u32 testmode = 0; |
34 | char buf[32]; |
35 | |
36 | if (copy_from_user(to: &buf, from: ubuf, min_t(size_t, sizeof(buf) - 1, count))) |
37 | return -EFAULT; |
38 | |
39 | if (!strncmp(buf, "test_j" , 6)) |
40 | testmode = USB_TEST_J; |
41 | else if (!strncmp(buf, "test_k" , 6)) |
42 | testmode = USB_TEST_K; |
43 | else if (!strncmp(buf, "test_se0_nak" , 12)) |
44 | testmode = USB_TEST_SE0_NAK; |
45 | else if (!strncmp(buf, "test_packet" , 11)) |
46 | testmode = USB_TEST_PACKET; |
47 | else if (!strncmp(buf, "test_force_enable" , 17)) |
48 | testmode = USB_TEST_FORCE_ENABLE; |
49 | else |
50 | testmode = 0; |
51 | |
52 | spin_lock_irqsave(&hsotg->lock, flags); |
53 | dwc2_hsotg_set_test_mode(hsotg, testmode); |
54 | spin_unlock_irqrestore(lock: &hsotg->lock, flags); |
55 | return count; |
56 | } |
57 | |
58 | /** |
59 | * testmode_show() - debugfs: show usb test mode state |
60 | * @s: The seq file to write to. |
61 | * @unused: Unused parameter. |
62 | * |
63 | * This debugfs entry shows which usb test mode is currently enabled. |
64 | */ |
65 | static int testmode_show(struct seq_file *s, void *unused) |
66 | { |
67 | struct dwc2_hsotg *hsotg = s->private; |
68 | unsigned long flags; |
69 | int dctl; |
70 | |
71 | spin_lock_irqsave(&hsotg->lock, flags); |
72 | dctl = dwc2_readl(hsotg, DCTL); |
73 | dctl &= DCTL_TSTCTL_MASK; |
74 | dctl >>= DCTL_TSTCTL_SHIFT; |
75 | spin_unlock_irqrestore(lock: &hsotg->lock, flags); |
76 | |
77 | switch (dctl) { |
78 | case 0: |
79 | seq_puts(m: s, s: "no test\n" ); |
80 | break; |
81 | case USB_TEST_J: |
82 | seq_puts(m: s, s: "test_j\n" ); |
83 | break; |
84 | case USB_TEST_K: |
85 | seq_puts(m: s, s: "test_k\n" ); |
86 | break; |
87 | case USB_TEST_SE0_NAK: |
88 | seq_puts(m: s, s: "test_se0_nak\n" ); |
89 | break; |
90 | case USB_TEST_PACKET: |
91 | seq_puts(m: s, s: "test_packet\n" ); |
92 | break; |
93 | case USB_TEST_FORCE_ENABLE: |
94 | seq_puts(m: s, s: "test_force_enable\n" ); |
95 | break; |
96 | default: |
97 | seq_printf(m: s, fmt: "UNKNOWN %d\n" , dctl); |
98 | } |
99 | |
100 | return 0; |
101 | } |
102 | |
103 | static int testmode_open(struct inode *inode, struct file *file) |
104 | { |
105 | return single_open(file, testmode_show, inode->i_private); |
106 | } |
107 | |
108 | static const struct file_operations testmode_fops = { |
109 | .owner = THIS_MODULE, |
110 | .open = testmode_open, |
111 | .write = testmode_write, |
112 | .read = seq_read, |
113 | .llseek = seq_lseek, |
114 | .release = single_release, |
115 | }; |
116 | |
117 | /** |
118 | * state_show - debugfs: show overall driver and device state. |
119 | * @seq: The seq file to write to. |
120 | * @v: Unused parameter. |
121 | * |
122 | * This debugfs entry shows the overall state of the hardware and |
123 | * some general information about each of the endpoints available |
124 | * to the system. |
125 | */ |
126 | static int state_show(struct seq_file *seq, void *v) |
127 | { |
128 | struct dwc2_hsotg *hsotg = seq->private; |
129 | int idx; |
130 | |
131 | seq_printf(m: seq, fmt: "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n" , |
132 | dwc2_readl(hsotg, DCFG), |
133 | dwc2_readl(hsotg, DCTL), |
134 | dwc2_readl(hsotg, DSTS)); |
135 | |
136 | seq_printf(m: seq, fmt: "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n" , |
137 | dwc2_readl(hsotg, DIEPMSK), dwc2_readl(hsotg, DOEPMSK)); |
138 | |
139 | seq_printf(m: seq, fmt: "GINTMSK=0x%08x, GINTSTS=0x%08x\n" , |
140 | dwc2_readl(hsotg, GINTMSK), |
141 | dwc2_readl(hsotg, GINTSTS)); |
142 | |
143 | seq_printf(m: seq, fmt: "DAINTMSK=0x%08x, DAINT=0x%08x\n" , |
144 | dwc2_readl(hsotg, DAINTMSK), |
145 | dwc2_readl(hsotg, DAINT)); |
146 | |
147 | seq_printf(m: seq, fmt: "GNPTXSTS=0x%08x, GRXSTSR=%08x\n" , |
148 | dwc2_readl(hsotg, GNPTXSTS), |
149 | dwc2_readl(hsotg, GRXSTSR)); |
150 | |
151 | seq_puts(m: seq, s: "\nEndpoint status:\n" ); |
152 | |
153 | for (idx = 0; idx < hsotg->num_of_eps; idx++) { |
154 | u32 in, out; |
155 | |
156 | in = dwc2_readl(hsotg, DIEPCTL(idx)); |
157 | out = dwc2_readl(hsotg, DOEPCTL(idx)); |
158 | |
159 | seq_printf(m: seq, fmt: "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x" , |
160 | idx, in, out); |
161 | |
162 | in = dwc2_readl(hsotg, DIEPTSIZ(idx)); |
163 | out = dwc2_readl(hsotg, DOEPTSIZ(idx)); |
164 | |
165 | seq_printf(m: seq, fmt: ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x" , |
166 | in, out); |
167 | |
168 | seq_puts(m: seq, s: "\n" ); |
169 | } |
170 | |
171 | return 0; |
172 | } |
173 | DEFINE_SHOW_ATTRIBUTE(state); |
174 | |
175 | /** |
176 | * fifo_show - debugfs: show the fifo information |
177 | * @seq: The seq_file to write data to. |
178 | * @v: Unused parameter. |
179 | * |
180 | * Show the FIFO information for the overall fifo and all the |
181 | * periodic transmission FIFOs. |
182 | */ |
183 | static int fifo_show(struct seq_file *seq, void *v) |
184 | { |
185 | struct dwc2_hsotg *hsotg = seq->private; |
186 | int fifo_count = dwc2_hsotg_tx_fifo_count(hsotg); |
187 | u32 val; |
188 | int idx; |
189 | |
190 | seq_puts(m: seq, s: "Non-periodic FIFOs:\n" ); |
191 | seq_printf(m: seq, fmt: "RXFIFO: Size %d\n" , dwc2_readl(hsotg, GRXFSIZ)); |
192 | |
193 | val = dwc2_readl(hsotg, GNPTXFSIZ); |
194 | seq_printf(m: seq, fmt: "NPTXFIFO: Size %d, Start 0x%08x\n" , |
195 | val >> FIFOSIZE_DEPTH_SHIFT, |
196 | val & FIFOSIZE_STARTADDR_MASK); |
197 | |
198 | seq_puts(m: seq, s: "\nPeriodic TXFIFOs:\n" ); |
199 | |
200 | for (idx = 1; idx <= fifo_count; idx++) { |
201 | val = dwc2_readl(hsotg, DPTXFSIZN(idx)); |
202 | |
203 | seq_printf(m: seq, fmt: "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n" , idx, |
204 | val >> FIFOSIZE_DEPTH_SHIFT, |
205 | val & FIFOSIZE_STARTADDR_MASK); |
206 | } |
207 | |
208 | return 0; |
209 | } |
210 | DEFINE_SHOW_ATTRIBUTE(fifo); |
211 | |
212 | static const char *decode_direction(int is_in) |
213 | { |
214 | return is_in ? "in" : "out" ; |
215 | } |
216 | |
217 | /** |
218 | * ep_show - debugfs: show the state of an endpoint. |
219 | * @seq: The seq_file to write data to. |
220 | * @v: Unused parameter. |
221 | * |
222 | * This debugfs entry shows the state of the given endpoint (one is |
223 | * registered for each available). |
224 | */ |
225 | static int ep_show(struct seq_file *seq, void *v) |
226 | { |
227 | struct dwc2_hsotg_ep *ep = seq->private; |
228 | struct dwc2_hsotg *hsotg = ep->parent; |
229 | struct dwc2_hsotg_req *req; |
230 | int index = ep->index; |
231 | int show_limit = 15; |
232 | unsigned long flags; |
233 | |
234 | seq_printf(m: seq, fmt: "Endpoint index %d, named %s, dir %s:\n" , |
235 | ep->index, ep->ep.name, decode_direction(is_in: ep->dir_in)); |
236 | |
237 | /* first show the register state */ |
238 | |
239 | seq_printf(m: seq, fmt: "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n" , |
240 | dwc2_readl(hsotg, DIEPCTL(index)), |
241 | dwc2_readl(hsotg, DOEPCTL(index))); |
242 | |
243 | seq_printf(m: seq, fmt: "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n" , |
244 | dwc2_readl(hsotg, DIEPDMA(index)), |
245 | dwc2_readl(hsotg, DOEPDMA(index))); |
246 | |
247 | seq_printf(m: seq, fmt: "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n" , |
248 | dwc2_readl(hsotg, DIEPINT(index)), |
249 | dwc2_readl(hsotg, DOEPINT(index))); |
250 | |
251 | seq_printf(m: seq, fmt: "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n" , |
252 | dwc2_readl(hsotg, DIEPTSIZ(index)), |
253 | dwc2_readl(hsotg, DOEPTSIZ(index))); |
254 | |
255 | seq_puts(m: seq, s: "\n" ); |
256 | seq_printf(m: seq, fmt: "mps %d\n" , ep->ep.maxpacket); |
257 | seq_printf(m: seq, fmt: "total_data=%ld\n" , ep->total_data); |
258 | |
259 | seq_printf(m: seq, fmt: "request list (%p,%p):\n" , |
260 | ep->queue.next, ep->queue.prev); |
261 | |
262 | spin_lock_irqsave(&hsotg->lock, flags); |
263 | |
264 | list_for_each_entry(req, &ep->queue, queue) { |
265 | if (--show_limit < 0) { |
266 | seq_puts(m: seq, s: "not showing more requests...\n" ); |
267 | break; |
268 | } |
269 | |
270 | seq_printf(m: seq, fmt: "%c req %p: %d bytes @%p, " , |
271 | req == ep->req ? '*' : ' ', |
272 | req, req->req.length, req->req.buf); |
273 | seq_printf(m: seq, fmt: "%d done, res %d\n" , |
274 | req->req.actual, req->req.status); |
275 | } |
276 | |
277 | spin_unlock_irqrestore(lock: &hsotg->lock, flags); |
278 | |
279 | return 0; |
280 | } |
281 | DEFINE_SHOW_ATTRIBUTE(ep); |
282 | |
283 | /** |
284 | * dwc2_hsotg_create_debug - create debugfs directory and files |
285 | * @hsotg: The driver state |
286 | * |
287 | * Create the debugfs files to allow the user to get information |
288 | * about the state of the system. The directory name is created |
289 | * with the same name as the device itself, in case we end up |
290 | * with multiple blocks in future systems. |
291 | */ |
292 | static void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg) |
293 | { |
294 | struct dentry *root; |
295 | unsigned int epidx; |
296 | |
297 | root = hsotg->debug_root; |
298 | |
299 | /* create general state file */ |
300 | debugfs_create_file(name: "state" , mode: 0444, parent: root, data: hsotg, fops: &state_fops); |
301 | debugfs_create_file(name: "testmode" , mode: 0644, parent: root, data: hsotg, fops: &testmode_fops); |
302 | debugfs_create_file(name: "fifo" , mode: 0444, parent: root, data: hsotg, fops: &fifo_fops); |
303 | |
304 | /* Create one file for each out endpoint */ |
305 | for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) { |
306 | struct dwc2_hsotg_ep *ep; |
307 | |
308 | ep = hsotg->eps_out[epidx]; |
309 | if (ep) |
310 | debugfs_create_file(name: ep->name, mode: 0444, parent: root, data: ep, fops: &ep_fops); |
311 | } |
312 | /* Create one file for each in endpoint. EP0 is handled with out eps */ |
313 | for (epidx = 1; epidx < hsotg->num_of_eps; epidx++) { |
314 | struct dwc2_hsotg_ep *ep; |
315 | |
316 | ep = hsotg->eps_in[epidx]; |
317 | if (ep) |
318 | debugfs_create_file(name: ep->name, mode: 0444, parent: root, data: ep, fops: &ep_fops); |
319 | } |
320 | } |
321 | #else |
322 | static inline void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg) {} |
323 | #endif |
324 | |
325 | /* dwc2_hsotg_delete_debug is removed as cleanup in done in dwc2_debugfs_exit */ |
326 | |
327 | #define dump_register(nm) \ |
328 | { \ |
329 | .name = #nm, \ |
330 | .offset = nm, \ |
331 | } |
332 | |
333 | static const struct debugfs_reg32 dwc2_regs[] = { |
334 | /* |
335 | * Accessing registers like this can trigger mode mismatch interrupt. |
336 | * However, according to dwc2 databook, the register access, in this |
337 | * case, is completed on the processor bus but is ignored by the core |
338 | * and does not affect its operation. |
339 | */ |
340 | dump_register(GOTGCTL), |
341 | dump_register(GOTGINT), |
342 | dump_register(GAHBCFG), |
343 | dump_register(GUSBCFG), |
344 | dump_register(GRSTCTL), |
345 | dump_register(GINTSTS), |
346 | dump_register(GINTMSK), |
347 | dump_register(GRXSTSR), |
348 | /* Omit GRXSTSP */ |
349 | dump_register(GRXFSIZ), |
350 | dump_register(GNPTXFSIZ), |
351 | dump_register(GNPTXSTS), |
352 | dump_register(GI2CCTL), |
353 | dump_register(GPVNDCTL), |
354 | dump_register(GGPIO), |
355 | dump_register(GUID), |
356 | dump_register(GSNPSID), |
357 | dump_register(GHWCFG1), |
358 | dump_register(GHWCFG2), |
359 | dump_register(GHWCFG3), |
360 | dump_register(GHWCFG4), |
361 | dump_register(GLPMCFG), |
362 | dump_register(GPWRDN), |
363 | dump_register(GDFIFOCFG), |
364 | dump_register(ADPCTL), |
365 | dump_register(HPTXFSIZ), |
366 | dump_register(DPTXFSIZN(1)), |
367 | dump_register(DPTXFSIZN(2)), |
368 | dump_register(DPTXFSIZN(3)), |
369 | dump_register(DPTXFSIZN(4)), |
370 | dump_register(DPTXFSIZN(5)), |
371 | dump_register(DPTXFSIZN(6)), |
372 | dump_register(DPTXFSIZN(7)), |
373 | dump_register(DPTXFSIZN(8)), |
374 | dump_register(DPTXFSIZN(9)), |
375 | dump_register(DPTXFSIZN(10)), |
376 | dump_register(DPTXFSIZN(11)), |
377 | dump_register(DPTXFSIZN(12)), |
378 | dump_register(DPTXFSIZN(13)), |
379 | dump_register(DPTXFSIZN(14)), |
380 | dump_register(DPTXFSIZN(15)), |
381 | dump_register(DCFG), |
382 | dump_register(DCTL), |
383 | dump_register(DSTS), |
384 | dump_register(DIEPMSK), |
385 | dump_register(DOEPMSK), |
386 | dump_register(DAINT), |
387 | dump_register(DAINTMSK), |
388 | dump_register(DTKNQR1), |
389 | dump_register(DTKNQR2), |
390 | dump_register(DTKNQR3), |
391 | dump_register(DTKNQR4), |
392 | dump_register(DVBUSDIS), |
393 | dump_register(DVBUSPULSE), |
394 | dump_register(DIEPCTL(0)), |
395 | dump_register(DIEPCTL(1)), |
396 | dump_register(DIEPCTL(2)), |
397 | dump_register(DIEPCTL(3)), |
398 | dump_register(DIEPCTL(4)), |
399 | dump_register(DIEPCTL(5)), |
400 | dump_register(DIEPCTL(6)), |
401 | dump_register(DIEPCTL(7)), |
402 | dump_register(DIEPCTL(8)), |
403 | dump_register(DIEPCTL(9)), |
404 | dump_register(DIEPCTL(10)), |
405 | dump_register(DIEPCTL(11)), |
406 | dump_register(DIEPCTL(12)), |
407 | dump_register(DIEPCTL(13)), |
408 | dump_register(DIEPCTL(14)), |
409 | dump_register(DIEPCTL(15)), |
410 | dump_register(DOEPCTL(0)), |
411 | dump_register(DOEPCTL(1)), |
412 | dump_register(DOEPCTL(2)), |
413 | dump_register(DOEPCTL(3)), |
414 | dump_register(DOEPCTL(4)), |
415 | dump_register(DOEPCTL(5)), |
416 | dump_register(DOEPCTL(6)), |
417 | dump_register(DOEPCTL(7)), |
418 | dump_register(DOEPCTL(8)), |
419 | dump_register(DOEPCTL(9)), |
420 | dump_register(DOEPCTL(10)), |
421 | dump_register(DOEPCTL(11)), |
422 | dump_register(DOEPCTL(12)), |
423 | dump_register(DOEPCTL(13)), |
424 | dump_register(DOEPCTL(14)), |
425 | dump_register(DOEPCTL(15)), |
426 | dump_register(DIEPINT(0)), |
427 | dump_register(DIEPINT(1)), |
428 | dump_register(DIEPINT(2)), |
429 | dump_register(DIEPINT(3)), |
430 | dump_register(DIEPINT(4)), |
431 | dump_register(DIEPINT(5)), |
432 | dump_register(DIEPINT(6)), |
433 | dump_register(DIEPINT(7)), |
434 | dump_register(DIEPINT(8)), |
435 | dump_register(DIEPINT(9)), |
436 | dump_register(DIEPINT(10)), |
437 | dump_register(DIEPINT(11)), |
438 | dump_register(DIEPINT(12)), |
439 | dump_register(DIEPINT(13)), |
440 | dump_register(DIEPINT(14)), |
441 | dump_register(DIEPINT(15)), |
442 | dump_register(DOEPINT(0)), |
443 | dump_register(DOEPINT(1)), |
444 | dump_register(DOEPINT(2)), |
445 | dump_register(DOEPINT(3)), |
446 | dump_register(DOEPINT(4)), |
447 | dump_register(DOEPINT(5)), |
448 | dump_register(DOEPINT(6)), |
449 | dump_register(DOEPINT(7)), |
450 | dump_register(DOEPINT(8)), |
451 | dump_register(DOEPINT(9)), |
452 | dump_register(DOEPINT(10)), |
453 | dump_register(DOEPINT(11)), |
454 | dump_register(DOEPINT(12)), |
455 | dump_register(DOEPINT(13)), |
456 | dump_register(DOEPINT(14)), |
457 | dump_register(DOEPINT(15)), |
458 | dump_register(DIEPTSIZ(0)), |
459 | dump_register(DIEPTSIZ(1)), |
460 | dump_register(DIEPTSIZ(2)), |
461 | dump_register(DIEPTSIZ(3)), |
462 | dump_register(DIEPTSIZ(4)), |
463 | dump_register(DIEPTSIZ(5)), |
464 | dump_register(DIEPTSIZ(6)), |
465 | dump_register(DIEPTSIZ(7)), |
466 | dump_register(DIEPTSIZ(8)), |
467 | dump_register(DIEPTSIZ(9)), |
468 | dump_register(DIEPTSIZ(10)), |
469 | dump_register(DIEPTSIZ(11)), |
470 | dump_register(DIEPTSIZ(12)), |
471 | dump_register(DIEPTSIZ(13)), |
472 | dump_register(DIEPTSIZ(14)), |
473 | dump_register(DIEPTSIZ(15)), |
474 | dump_register(DOEPTSIZ(0)), |
475 | dump_register(DOEPTSIZ(1)), |
476 | dump_register(DOEPTSIZ(2)), |
477 | dump_register(DOEPTSIZ(3)), |
478 | dump_register(DOEPTSIZ(4)), |
479 | dump_register(DOEPTSIZ(5)), |
480 | dump_register(DOEPTSIZ(6)), |
481 | dump_register(DOEPTSIZ(7)), |
482 | dump_register(DOEPTSIZ(8)), |
483 | dump_register(DOEPTSIZ(9)), |
484 | dump_register(DOEPTSIZ(10)), |
485 | dump_register(DOEPTSIZ(11)), |
486 | dump_register(DOEPTSIZ(12)), |
487 | dump_register(DOEPTSIZ(13)), |
488 | dump_register(DOEPTSIZ(14)), |
489 | dump_register(DOEPTSIZ(15)), |
490 | dump_register(DIEPDMA(0)), |
491 | dump_register(DIEPDMA(1)), |
492 | dump_register(DIEPDMA(2)), |
493 | dump_register(DIEPDMA(3)), |
494 | dump_register(DIEPDMA(4)), |
495 | dump_register(DIEPDMA(5)), |
496 | dump_register(DIEPDMA(6)), |
497 | dump_register(DIEPDMA(7)), |
498 | dump_register(DIEPDMA(8)), |
499 | dump_register(DIEPDMA(9)), |
500 | dump_register(DIEPDMA(10)), |
501 | dump_register(DIEPDMA(11)), |
502 | dump_register(DIEPDMA(12)), |
503 | dump_register(DIEPDMA(13)), |
504 | dump_register(DIEPDMA(14)), |
505 | dump_register(DIEPDMA(15)), |
506 | dump_register(DOEPDMA(0)), |
507 | dump_register(DOEPDMA(1)), |
508 | dump_register(DOEPDMA(2)), |
509 | dump_register(DOEPDMA(3)), |
510 | dump_register(DOEPDMA(4)), |
511 | dump_register(DOEPDMA(5)), |
512 | dump_register(DOEPDMA(6)), |
513 | dump_register(DOEPDMA(7)), |
514 | dump_register(DOEPDMA(8)), |
515 | dump_register(DOEPDMA(9)), |
516 | dump_register(DOEPDMA(10)), |
517 | dump_register(DOEPDMA(11)), |
518 | dump_register(DOEPDMA(12)), |
519 | dump_register(DOEPDMA(13)), |
520 | dump_register(DOEPDMA(14)), |
521 | dump_register(DOEPDMA(15)), |
522 | dump_register(DTXFSTS(0)), |
523 | dump_register(DTXFSTS(1)), |
524 | dump_register(DTXFSTS(2)), |
525 | dump_register(DTXFSTS(3)), |
526 | dump_register(DTXFSTS(4)), |
527 | dump_register(DTXFSTS(5)), |
528 | dump_register(DTXFSTS(6)), |
529 | dump_register(DTXFSTS(7)), |
530 | dump_register(DTXFSTS(8)), |
531 | dump_register(DTXFSTS(9)), |
532 | dump_register(DTXFSTS(10)), |
533 | dump_register(DTXFSTS(11)), |
534 | dump_register(DTXFSTS(12)), |
535 | dump_register(DTXFSTS(13)), |
536 | dump_register(DTXFSTS(14)), |
537 | dump_register(DTXFSTS(15)), |
538 | dump_register(PCGCTL), |
539 | dump_register(HCFG), |
540 | dump_register(HFIR), |
541 | dump_register(HFNUM), |
542 | dump_register(HPTXSTS), |
543 | dump_register(HAINT), |
544 | dump_register(HAINTMSK), |
545 | dump_register(HFLBADDR), |
546 | dump_register(HPRT0), |
547 | dump_register(HCCHAR(0)), |
548 | dump_register(HCCHAR(1)), |
549 | dump_register(HCCHAR(2)), |
550 | dump_register(HCCHAR(3)), |
551 | dump_register(HCCHAR(4)), |
552 | dump_register(HCCHAR(5)), |
553 | dump_register(HCCHAR(6)), |
554 | dump_register(HCCHAR(7)), |
555 | dump_register(HCCHAR(8)), |
556 | dump_register(HCCHAR(9)), |
557 | dump_register(HCCHAR(10)), |
558 | dump_register(HCCHAR(11)), |
559 | dump_register(HCCHAR(12)), |
560 | dump_register(HCCHAR(13)), |
561 | dump_register(HCCHAR(14)), |
562 | dump_register(HCCHAR(15)), |
563 | dump_register(HCSPLT(0)), |
564 | dump_register(HCSPLT(1)), |
565 | dump_register(HCSPLT(2)), |
566 | dump_register(HCSPLT(3)), |
567 | dump_register(HCSPLT(4)), |
568 | dump_register(HCSPLT(5)), |
569 | dump_register(HCSPLT(6)), |
570 | dump_register(HCSPLT(7)), |
571 | dump_register(HCSPLT(8)), |
572 | dump_register(HCSPLT(9)), |
573 | dump_register(HCSPLT(10)), |
574 | dump_register(HCSPLT(11)), |
575 | dump_register(HCSPLT(12)), |
576 | dump_register(HCSPLT(13)), |
577 | dump_register(HCSPLT(14)), |
578 | dump_register(HCSPLT(15)), |
579 | dump_register(HCINT(0)), |
580 | dump_register(HCINT(1)), |
581 | dump_register(HCINT(2)), |
582 | dump_register(HCINT(3)), |
583 | dump_register(HCINT(4)), |
584 | dump_register(HCINT(5)), |
585 | dump_register(HCINT(6)), |
586 | dump_register(HCINT(7)), |
587 | dump_register(HCINT(8)), |
588 | dump_register(HCINT(9)), |
589 | dump_register(HCINT(10)), |
590 | dump_register(HCINT(11)), |
591 | dump_register(HCINT(12)), |
592 | dump_register(HCINT(13)), |
593 | dump_register(HCINT(14)), |
594 | dump_register(HCINT(15)), |
595 | dump_register(HCINTMSK(0)), |
596 | dump_register(HCINTMSK(1)), |
597 | dump_register(HCINTMSK(2)), |
598 | dump_register(HCINTMSK(3)), |
599 | dump_register(HCINTMSK(4)), |
600 | dump_register(HCINTMSK(5)), |
601 | dump_register(HCINTMSK(6)), |
602 | dump_register(HCINTMSK(7)), |
603 | dump_register(HCINTMSK(8)), |
604 | dump_register(HCINTMSK(9)), |
605 | dump_register(HCINTMSK(10)), |
606 | dump_register(HCINTMSK(11)), |
607 | dump_register(HCINTMSK(12)), |
608 | dump_register(HCINTMSK(13)), |
609 | dump_register(HCINTMSK(14)), |
610 | dump_register(HCINTMSK(15)), |
611 | dump_register(HCTSIZ(0)), |
612 | dump_register(HCTSIZ(1)), |
613 | dump_register(HCTSIZ(2)), |
614 | dump_register(HCTSIZ(3)), |
615 | dump_register(HCTSIZ(4)), |
616 | dump_register(HCTSIZ(5)), |
617 | dump_register(HCTSIZ(6)), |
618 | dump_register(HCTSIZ(7)), |
619 | dump_register(HCTSIZ(8)), |
620 | dump_register(HCTSIZ(9)), |
621 | dump_register(HCTSIZ(10)), |
622 | dump_register(HCTSIZ(11)), |
623 | dump_register(HCTSIZ(12)), |
624 | dump_register(HCTSIZ(13)), |
625 | dump_register(HCTSIZ(14)), |
626 | dump_register(HCTSIZ(15)), |
627 | dump_register(HCDMA(0)), |
628 | dump_register(HCDMA(1)), |
629 | dump_register(HCDMA(2)), |
630 | dump_register(HCDMA(3)), |
631 | dump_register(HCDMA(4)), |
632 | dump_register(HCDMA(5)), |
633 | dump_register(HCDMA(6)), |
634 | dump_register(HCDMA(7)), |
635 | dump_register(HCDMA(8)), |
636 | dump_register(HCDMA(9)), |
637 | dump_register(HCDMA(10)), |
638 | dump_register(HCDMA(11)), |
639 | dump_register(HCDMA(12)), |
640 | dump_register(HCDMA(13)), |
641 | dump_register(HCDMA(14)), |
642 | dump_register(HCDMA(15)), |
643 | dump_register(HCDMAB(0)), |
644 | dump_register(HCDMAB(1)), |
645 | dump_register(HCDMAB(2)), |
646 | dump_register(HCDMAB(3)), |
647 | dump_register(HCDMAB(4)), |
648 | dump_register(HCDMAB(5)), |
649 | dump_register(HCDMAB(6)), |
650 | dump_register(HCDMAB(7)), |
651 | dump_register(HCDMAB(8)), |
652 | dump_register(HCDMAB(9)), |
653 | dump_register(HCDMAB(10)), |
654 | dump_register(HCDMAB(11)), |
655 | dump_register(HCDMAB(12)), |
656 | dump_register(HCDMAB(13)), |
657 | dump_register(HCDMAB(14)), |
658 | dump_register(HCDMAB(15)), |
659 | }; |
660 | |
661 | #define print_param(_seq, _ptr, _param) \ |
662 | seq_printf((_seq), "%-30s: %d\n", #_param, (_ptr)->_param) |
663 | |
664 | #define print_param_hex(_seq, _ptr, _param) \ |
665 | seq_printf((_seq), "%-30s: 0x%x\n", #_param, (_ptr)->_param) |
666 | |
667 | static int params_show(struct seq_file *seq, void *v) |
668 | { |
669 | struct dwc2_hsotg *hsotg = seq->private; |
670 | struct dwc2_core_params *p = &hsotg->params; |
671 | int i; |
672 | |
673 | print_param(seq, p, otg_caps.hnp_support); |
674 | print_param(seq, p, otg_caps.srp_support); |
675 | print_param(seq, p, otg_caps.otg_rev); |
676 | print_param(seq, p, dma_desc_enable); |
677 | print_param(seq, p, dma_desc_fs_enable); |
678 | print_param(seq, p, speed); |
679 | print_param(seq, p, enable_dynamic_fifo); |
680 | print_param(seq, p, en_multiple_tx_fifo); |
681 | print_param(seq, p, host_rx_fifo_size); |
682 | print_param(seq, p, host_nperio_tx_fifo_size); |
683 | print_param(seq, p, host_perio_tx_fifo_size); |
684 | print_param(seq, p, max_transfer_size); |
685 | print_param(seq, p, max_packet_count); |
686 | print_param(seq, p, host_channels); |
687 | print_param(seq, p, phy_type); |
688 | print_param(seq, p, phy_utmi_width); |
689 | print_param(seq, p, phy_ulpi_ddr); |
690 | print_param(seq, p, phy_ulpi_ext_vbus); |
691 | print_param(seq, p, i2c_enable); |
692 | print_param(seq, p, ipg_isoc_en); |
693 | print_param(seq, p, ulpi_fs_ls); |
694 | print_param(seq, p, host_support_fs_ls_low_power); |
695 | print_param(seq, p, host_ls_low_power_phy_clk); |
696 | print_param(seq, p, activate_stm_fs_transceiver); |
697 | print_param(seq, p, activate_stm_id_vb_detection); |
698 | print_param(seq, p, ts_dline); |
699 | print_param(seq, p, reload_ctl); |
700 | print_param_hex(seq, p, ahbcfg); |
701 | print_param(seq, p, uframe_sched); |
702 | print_param(seq, p, external_id_pin_ctl); |
703 | print_param(seq, p, power_down); |
704 | print_param(seq, p, lpm); |
705 | print_param(seq, p, lpm_clock_gating); |
706 | print_param(seq, p, besl); |
707 | print_param(seq, p, hird_threshold_en); |
708 | print_param(seq, p, hird_threshold); |
709 | print_param(seq, p, service_interval); |
710 | print_param(seq, p, host_dma); |
711 | print_param(seq, p, g_dma); |
712 | print_param(seq, p, g_dma_desc); |
713 | print_param(seq, p, g_rx_fifo_size); |
714 | print_param(seq, p, g_np_tx_fifo_size); |
715 | |
716 | for (i = 0; i < MAX_EPS_CHANNELS; i++) { |
717 | char str[32]; |
718 | |
719 | snprintf(buf: str, size: 32, fmt: "g_tx_fifo_size[%d]" , i); |
720 | seq_printf(m: seq, fmt: "%-30s: %d\n" , str, p->g_tx_fifo_size[i]); |
721 | } |
722 | |
723 | return 0; |
724 | } |
725 | DEFINE_SHOW_ATTRIBUTE(params); |
726 | |
727 | static int hw_params_show(struct seq_file *seq, void *v) |
728 | { |
729 | struct dwc2_hsotg *hsotg = seq->private; |
730 | struct dwc2_hw_params *hw = &hsotg->hw_params; |
731 | |
732 | print_param(seq, hw, op_mode); |
733 | print_param(seq, hw, arch); |
734 | print_param(seq, hw, dma_desc_enable); |
735 | print_param(seq, hw, enable_dynamic_fifo); |
736 | print_param(seq, hw, en_multiple_tx_fifo); |
737 | print_param(seq, hw, rx_fifo_size); |
738 | print_param(seq, hw, host_nperio_tx_fifo_size); |
739 | print_param(seq, hw, dev_nperio_tx_fifo_size); |
740 | print_param(seq, hw, host_perio_tx_fifo_size); |
741 | print_param(seq, hw, nperio_tx_q_depth); |
742 | print_param(seq, hw, host_perio_tx_q_depth); |
743 | print_param(seq, hw, dev_token_q_depth); |
744 | print_param(seq, hw, max_transfer_size); |
745 | print_param(seq, hw, max_packet_count); |
746 | print_param(seq, hw, host_channels); |
747 | print_param(seq, hw, hs_phy_type); |
748 | print_param(seq, hw, fs_phy_type); |
749 | print_param(seq, hw, i2c_enable); |
750 | print_param(seq, hw, num_dev_ep); |
751 | print_param(seq, hw, num_dev_perio_in_ep); |
752 | print_param(seq, hw, total_fifo_size); |
753 | print_param(seq, hw, power_optimized); |
754 | print_param(seq, hw, utmi_phy_data_width); |
755 | print_param_hex(seq, hw, snpsid); |
756 | print_param_hex(seq, hw, dev_ep_dirs); |
757 | |
758 | return 0; |
759 | } |
760 | DEFINE_SHOW_ATTRIBUTE(hw_params); |
761 | |
762 | static int dr_mode_show(struct seq_file *seq, void *v) |
763 | { |
764 | struct dwc2_hsotg *hsotg = seq->private; |
765 | const char *dr_mode = "" ; |
766 | |
767 | device_property_read_string(dev: hsotg->dev, propname: "dr_mode" , val: &dr_mode); |
768 | seq_printf(m: seq, fmt: "%s\n" , dr_mode); |
769 | return 0; |
770 | } |
771 | DEFINE_SHOW_ATTRIBUTE(dr_mode); |
772 | |
773 | int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) |
774 | { |
775 | int ret; |
776 | struct dentry *root; |
777 | |
778 | root = debugfs_create_dir(name: dev_name(dev: hsotg->dev), parent: usb_debug_root); |
779 | hsotg->debug_root = root; |
780 | |
781 | debugfs_create_file(name: "params" , mode: 0444, parent: root, data: hsotg, fops: ¶ms_fops); |
782 | debugfs_create_file(name: "hw_params" , mode: 0444, parent: root, data: hsotg, fops: &hw_params_fops); |
783 | debugfs_create_file(name: "dr_mode" , mode: 0444, parent: root, data: hsotg, fops: &dr_mode_fops); |
784 | |
785 | /* Add gadget debugfs nodes */ |
786 | dwc2_hsotg_create_debug(hsotg); |
787 | |
788 | hsotg->regset = devm_kzalloc(dev: hsotg->dev, size: sizeof(*hsotg->regset), |
789 | GFP_KERNEL); |
790 | if (!hsotg->regset) { |
791 | ret = -ENOMEM; |
792 | goto err; |
793 | } |
794 | |
795 | hsotg->regset->regs = dwc2_regs; |
796 | hsotg->regset->nregs = ARRAY_SIZE(dwc2_regs); |
797 | hsotg->regset->base = hsotg->regs; |
798 | |
799 | debugfs_create_regset32(name: "regdump" , mode: 0444, parent: root, regset: hsotg->regset); |
800 | |
801 | return 0; |
802 | err: |
803 | debugfs_remove_recursive(dentry: hsotg->debug_root); |
804 | return ret; |
805 | } |
806 | |
807 | void dwc2_debugfs_exit(struct dwc2_hsotg *hsotg) |
808 | { |
809 | debugfs_remove_recursive(dentry: hsotg->debug_root); |
810 | hsotg->debug_root = NULL; |
811 | } |
812 | |