blob: e57e554ebfc7b8b5f39ca96081046d73f3defe6b [file] [log] [blame]
Mian Yousaf Kaukabf91eea42015-04-29 22:08:59 +02001/**
2 * debugfs.c - Designware USB2 DRD controller debugfs
3 *
4 * Copyright (C) 2015 Intel Corporation
5 * Mian Yousaf Kaukab <yousaf.kaukab@intel.com>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 of
9 * the License as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/spinlock.h>
18#include <linux/debugfs.h>
19#include <linux/seq_file.h>
20#include <linux/uaccess.h>
21
22#include "core.h"
23#include "debug.h"
24
25#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
26 IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
27/**
28 * testmode_write - debugfs: change usb test mode
29 * @seq: The seq file to write to.
30 * @v: Unused parameter.
31 *
32 * This debugfs entry modify the current usb test mode.
33 */
34static ssize_t testmode_write(struct file *file, const char __user *ubuf, size_t
35 count, loff_t *ppos)
36{
37 struct seq_file *s = file->private_data;
38 struct dwc2_hsotg *hsotg = s->private;
39 unsigned long flags;
40 u32 testmode = 0;
41 char buf[32];
42
43 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
44 return -EFAULT;
45
46 if (!strncmp(buf, "test_j", 6))
47 testmode = TEST_J;
48 else if (!strncmp(buf, "test_k", 6))
49 testmode = TEST_K;
50 else if (!strncmp(buf, "test_se0_nak", 12))
51 testmode = TEST_SE0_NAK;
52 else if (!strncmp(buf, "test_packet", 11))
53 testmode = TEST_PACKET;
54 else if (!strncmp(buf, "test_force_enable", 17))
55 testmode = TEST_FORCE_EN;
56 else
57 testmode = 0;
58
59 spin_lock_irqsave(&hsotg->lock, flags);
60 s3c_hsotg_set_test_mode(hsotg, testmode);
61 spin_unlock_irqrestore(&hsotg->lock, flags);
62 return count;
63}
64
65/**
66 * testmode_show - debugfs: show usb test mode state
67 * @seq: The seq file to write to.
68 * @v: Unused parameter.
69 *
70 * This debugfs entry shows which usb test mode is currently enabled.
71 */
72static int testmode_show(struct seq_file *s, void *unused)
73{
74 struct dwc2_hsotg *hsotg = s->private;
75 unsigned long flags;
76 int dctl;
77
78 spin_lock_irqsave(&hsotg->lock, flags);
79 dctl = readl(hsotg->regs + DCTL);
80 dctl &= DCTL_TSTCTL_MASK;
81 dctl >>= DCTL_TSTCTL_SHIFT;
82 spin_unlock_irqrestore(&hsotg->lock, flags);
83
84 switch (dctl) {
85 case 0:
86 seq_puts(s, "no test\n");
87 break;
88 case TEST_J:
89 seq_puts(s, "test_j\n");
90 break;
91 case TEST_K:
92 seq_puts(s, "test_k\n");
93 break;
94 case TEST_SE0_NAK:
95 seq_puts(s, "test_se0_nak\n");
96 break;
97 case TEST_PACKET:
98 seq_puts(s, "test_packet\n");
99 break;
100 case TEST_FORCE_EN:
101 seq_puts(s, "test_force_enable\n");
102 break;
103 default:
104 seq_printf(s, "UNKNOWN %d\n", dctl);
105 }
106
107 return 0;
108}
109
110static int testmode_open(struct inode *inode, struct file *file)
111{
112 return single_open(file, testmode_show, inode->i_private);
113}
114
115static const struct file_operations testmode_fops = {
116 .owner = THIS_MODULE,
117 .open = testmode_open,
118 .write = testmode_write,
119 .read = seq_read,
120 .llseek = seq_lseek,
121 .release = single_release,
122};
123
124/**
125 * state_show - debugfs: show overall driver and device state.
126 * @seq: The seq file to write to.
127 * @v: Unused parameter.
128 *
129 * This debugfs entry shows the overall state of the hardware and
130 * some general information about each of the endpoints available
131 * to the system.
132 */
133static int state_show(struct seq_file *seq, void *v)
134{
135 struct dwc2_hsotg *hsotg = seq->private;
136 void __iomem *regs = hsotg->regs;
137 int idx;
138
139 seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n",
140 readl(regs + DCFG),
141 readl(regs + DCTL),
142 readl(regs + DSTS));
143
144 seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n",
145 readl(regs + DIEPMSK), readl(regs + DOEPMSK));
146
147 seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n",
148 readl(regs + GINTMSK),
149 readl(regs + GINTSTS));
150
151 seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n",
152 readl(regs + DAINTMSK),
153 readl(regs + DAINT));
154
155 seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n",
156 readl(regs + GNPTXSTS),
157 readl(regs + GRXSTSR));
158
159 seq_puts(seq, "\nEndpoint status:\n");
160
161 for (idx = 0; idx < hsotg->num_of_eps; idx++) {
162 u32 in, out;
163
164 in = readl(regs + DIEPCTL(idx));
165 out = readl(regs + DOEPCTL(idx));
166
167 seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x",
168 idx, in, out);
169
170 in = readl(regs + DIEPTSIZ(idx));
171 out = readl(regs + DOEPTSIZ(idx));
172
173 seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x",
174 in, out);
175
176 seq_puts(seq, "\n");
177 }
178
179 return 0;
180}
181
182static int state_open(struct inode *inode, struct file *file)
183{
184 return single_open(file, state_show, inode->i_private);
185}
186
187static const struct file_operations state_fops = {
188 .owner = THIS_MODULE,
189 .open = state_open,
190 .read = seq_read,
191 .llseek = seq_lseek,
192 .release = single_release,
193};
194
195/**
196 * fifo_show - debugfs: show the fifo information
197 * @seq: The seq_file to write data to.
198 * @v: Unused parameter.
199 *
200 * Show the FIFO information for the overall fifo and all the
201 * periodic transmission FIFOs.
202 */
203static int fifo_show(struct seq_file *seq, void *v)
204{
205 struct dwc2_hsotg *hsotg = seq->private;
206 void __iomem *regs = hsotg->regs;
207 u32 val;
208 int idx;
209
210 seq_puts(seq, "Non-periodic FIFOs:\n");
211 seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ));
212
213 val = readl(regs + GNPTXFSIZ);
214 seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n",
215 val >> FIFOSIZE_DEPTH_SHIFT,
216 val & FIFOSIZE_DEPTH_MASK);
217
218 seq_puts(seq, "\nPeriodic TXFIFOs:\n");
219
220 for (idx = 1; idx < hsotg->num_of_eps; idx++) {
221 val = readl(regs + DPTXFSIZN(idx));
222
223 seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx,
224 val >> FIFOSIZE_DEPTH_SHIFT,
225 val & FIFOSIZE_STARTADDR_MASK);
226 }
227
228 return 0;
229}
230
231static int fifo_open(struct inode *inode, struct file *file)
232{
233 return single_open(file, fifo_show, inode->i_private);
234}
235
236static const struct file_operations fifo_fops = {
237 .owner = THIS_MODULE,
238 .open = fifo_open,
239 .read = seq_read,
240 .llseek = seq_lseek,
241 .release = single_release,
242};
243
244static const char *decode_direction(int is_in)
245{
246 return is_in ? "in" : "out";
247}
248
249/**
250 * ep_show - debugfs: show the state of an endpoint.
251 * @seq: The seq_file to write data to.
252 * @v: Unused parameter.
253 *
254 * This debugfs entry shows the state of the given endpoint (one is
255 * registered for each available).
256 */
257static int ep_show(struct seq_file *seq, void *v)
258{
259 struct s3c_hsotg_ep *ep = seq->private;
260 struct dwc2_hsotg *hsotg = ep->parent;
261 struct s3c_hsotg_req *req;
262 void __iomem *regs = hsotg->regs;
263 int index = ep->index;
264 int show_limit = 15;
265 unsigned long flags;
266
267 seq_printf(seq, "Endpoint index %d, named %s, dir %s:\n",
268 ep->index, ep->ep.name, decode_direction(ep->dir_in));
269
270 /* first show the register state */
271
272 seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n",
273 readl(regs + DIEPCTL(index)),
274 readl(regs + DOEPCTL(index)));
275
276 seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n",
277 readl(regs + DIEPDMA(index)),
278 readl(regs + DOEPDMA(index)));
279
280 seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n",
281 readl(regs + DIEPINT(index)),
282 readl(regs + DOEPINT(index)));
283
284 seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n",
285 readl(regs + DIEPTSIZ(index)),
286 readl(regs + DOEPTSIZ(index)));
287
288 seq_puts(seq, "\n");
289 seq_printf(seq, "mps %d\n", ep->ep.maxpacket);
290 seq_printf(seq, "total_data=%ld\n", ep->total_data);
291
292 seq_printf(seq, "request list (%p,%p):\n",
293 ep->queue.next, ep->queue.prev);
294
295 spin_lock_irqsave(&hsotg->lock, flags);
296
297 list_for_each_entry(req, &ep->queue, queue) {
298 if (--show_limit < 0) {
299 seq_puts(seq, "not showing more requests...\n");
300 break;
301 }
302
303 seq_printf(seq, "%c req %p: %d bytes @%p, ",
304 req == ep->req ? '*' : ' ',
305 req, req->req.length, req->req.buf);
306 seq_printf(seq, "%d done, res %d\n",
307 req->req.actual, req->req.status);
308 }
309
310 spin_unlock_irqrestore(&hsotg->lock, flags);
311
312 return 0;
313}
314
315static int ep_open(struct inode *inode, struct file *file)
316{
317 return single_open(file, ep_show, inode->i_private);
318}
319
320static const struct file_operations ep_fops = {
321 .owner = THIS_MODULE,
322 .open = ep_open,
323 .read = seq_read,
324 .llseek = seq_lseek,
325 .release = single_release,
326};
327
328/**
329 * s3c_hsotg_create_debug - create debugfs directory and files
330 * @hsotg: The driver state
331 *
332 * Create the debugfs files to allow the user to get information
333 * about the state of the system. The directory name is created
334 * with the same name as the device itself, in case we end up
335 * with multiple blocks in future systems.
336 */
337static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg)
338{
339 struct dentry *root;
340 struct dentry *file;
341 unsigned epidx;
342
343 root = hsotg->debug_root;
344
345 /* create general state file */
346
347 file = debugfs_create_file("state", S_IRUGO, root, hsotg, &state_fops);
348 if (IS_ERR(file))
349 dev_err(hsotg->dev, "%s: failed to create state\n", __func__);
350
351 file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, hsotg,
352 &testmode_fops);
353 if (IS_ERR(file))
354 dev_err(hsotg->dev, "%s: failed to create testmode\n",
355 __func__);
356
357 file = debugfs_create_file("fifo", S_IRUGO, root, hsotg, &fifo_fops);
358 if (IS_ERR(file))
359 dev_err(hsotg->dev, "%s: failed to create fifo\n", __func__);
360
361 /* Create one file for each out endpoint */
362 for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) {
363 struct s3c_hsotg_ep *ep;
364
365 ep = hsotg->eps_out[epidx];
366 if (ep) {
367 file = debugfs_create_file(ep->name, S_IRUGO,
368 root, ep, &ep_fops);
369 if (IS_ERR(file))
370 dev_err(hsotg->dev, "failed to create %s debug file\n",
371 ep->name);
372 }
373 }
374 /* Create one file for each in endpoint. EP0 is handled with out eps */
375 for (epidx = 1; epidx < hsotg->num_of_eps; epidx++) {
376 struct s3c_hsotg_ep *ep;
377
378 ep = hsotg->eps_in[epidx];
379 if (ep) {
380 file = debugfs_create_file(ep->name, S_IRUGO,
381 root, ep, &ep_fops);
382 if (IS_ERR(file))
383 dev_err(hsotg->dev, "failed to create %s debug file\n",
384 ep->name);
385 }
386 }
387}
388#else
389static inline void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg) {}
390#endif
391
392/* s3c_hsotg_delete_debug is removed as cleanup in done in dwc2_debugfs_exit */
393
394int dwc2_debugfs_init(struct dwc2_hsotg *hsotg)
395{
396 int ret;
397
398 hsotg->debug_root = debugfs_create_dir(dev_name(hsotg->dev), NULL);
399 if (!hsotg->debug_root) {
400 ret = -ENOMEM;
401 goto err0;
402 }
403
404 /* Add gadget debugfs nodes */
405 s3c_hsotg_create_debug(hsotg);
406err0:
407 return ret;
408}
409EXPORT_SYMBOL_GPL(dwc2_debugfs_init);
410
411void dwc2_debugfs_exit(struct dwc2_hsotg *hsotg)
412{
413 debugfs_remove_recursive(hsotg->debug_root);
414 hsotg->debug_root = NULL;
415}
416EXPORT_SYMBOL_GPL(dwc2_debugfs_exit);