usb: Make USB persist default configurable
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / usb / chipidea / debug.c
CommitLineData
e443b333
AS
1#include <linux/delay.h>
2#include <linux/device.h>
3#include <linux/dmapool.h>
4#include <linux/dma-mapping.h>
5#include <linux/init.h>
6#include <linux/platform_device.h>
7#include <linux/module.h>
8#include <linux/interrupt.h>
9#include <linux/io.h>
10#include <linux/irq.h>
11#include <linux/kernel.h>
12#include <linux/slab.h>
13#include <linux/pm_runtime.h>
14#include <linux/usb/ch9.h>
15#include <linux/usb/gadget.h>
16#include <linux/usb/otg.h>
17#include <linux/usb/chipidea.h>
18
19#include "ci.h"
20#include "udc.h"
21#include "bits.h"
22#include "debug.h"
23
24/* Interrupt statistics */
25#define ISR_MASK 0x1F
26static struct isr_statistics {
27 u32 test;
28 u32 ui;
29 u32 uei;
30 u32 pci;
31 u32 uri;
32 u32 sli;
33 u32 none;
34 struct {
35 u32 cnt;
36 u32 buf[ISR_MASK+1];
37 u32 idx;
38 } hndl;
39} isr_statistics;
40
41void dbg_interrupt(u32 intmask)
42{
43 if (!intmask) {
44 isr_statistics.none++;
45 return;
46 }
47
48 isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intmask;
49 isr_statistics.hndl.idx &= ISR_MASK;
50 isr_statistics.hndl.cnt++;
51
52 if (USBi_URI & intmask)
53 isr_statistics.uri++;
54 if (USBi_PCI & intmask)
55 isr_statistics.pci++;
56 if (USBi_UEI & intmask)
57 isr_statistics.uei++;
58 if (USBi_UI & intmask)
59 isr_statistics.ui++;
60 if (USBi_SLI & intmask)
61 isr_statistics.sli++;
62}
63
64/**
65 * hw_register_read: reads all device registers (execute without interruption)
66 * @buf: destination buffer
67 * @size: buffer size
68 *
69 * This function returns number of registers read
70 */
26c696c6 71static size_t hw_register_read(struct ci13xxx *ci, u32 *buf, size_t size)
e443b333
AS
72{
73 unsigned i;
74
26c696c6
RZ
75 if (size > ci->hw_bank.size)
76 size = ci->hw_bank.size;
e443b333
AS
77
78 for (i = 0; i < size; i++)
26c696c6 79 buf[i] = hw_read(ci, i * sizeof(u32), ~0);
e443b333
AS
80
81 return size;
82}
83
84/**
85 * hw_register_write: writes to register
86 * @addr: register address
87 * @data: register value
88 *
89 * This function returns an error code
90 */
26c696c6 91static int hw_register_write(struct ci13xxx *ci, u16 addr, u32 data)
e443b333
AS
92{
93 /* align */
94 addr /= sizeof(u32);
95
26c696c6 96 if (addr >= ci->hw_bank.size)
e443b333
AS
97 return -EINVAL;
98
99 /* align */
100 addr *= sizeof(u32);
101
26c696c6 102 hw_write(ci, addr, ~0, data);
e443b333
AS
103 return 0;
104}
105
106/**
107 * hw_intr_clear: disables interrupt & clears interrupt status (execute without
108 * interruption)
109 * @n: interrupt bit
110 *
111 * This function returns an error code
112 */
26c696c6 113static int hw_intr_clear(struct ci13xxx *ci, int n)
e443b333
AS
114{
115 if (n >= REG_BITS)
116 return -EINVAL;
117
26c696c6
RZ
118 hw_write(ci, OP_USBINTR, BIT(n), 0);
119 hw_write(ci, OP_USBSTS, BIT(n), BIT(n));
e443b333
AS
120 return 0;
121}
122
123/**
124 * hw_intr_force: enables interrupt & forces interrupt status (execute without
125 * interruption)
126 * @n: interrupt bit
127 *
128 * This function returns an error code
129 */
26c696c6 130static int hw_intr_force(struct ci13xxx *ci, int n)
e443b333
AS
131{
132 if (n >= REG_BITS)
133 return -EINVAL;
134
26c696c6
RZ
135 hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
136 hw_write(ci, OP_USBINTR, BIT(n), BIT(n));
137 hw_write(ci, OP_USBSTS, BIT(n), BIT(n));
138 hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, 0);
e443b333
AS
139 return 0;
140}
141
142/**
143 * show_device: prints information about device capabilities and status
144 *
145 * Check "device.h" for details
146 */
147static ssize_t show_device(struct device *dev, struct device_attribute *attr,
148 char *buf)
149{
26c696c6
RZ
150 struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
151 struct usb_gadget *gadget = &ci->gadget;
e443b333
AS
152 int n = 0;
153
154 if (attr == NULL || buf == NULL) {
26c696c6 155 dev_err(ci->dev, "[%s] EINVAL\n", __func__);
e443b333
AS
156 return 0;
157 }
158
159 n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
160 gadget->speed);
161 n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
162 gadget->max_speed);
e443b333
AS
163 n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
164 gadget->is_otg);
165 n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
166 gadget->is_a_peripheral);
167 n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n",
168 gadget->b_hnp_enable);
169 n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n",
170 gadget->a_hnp_support);
171 n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
172 gadget->a_alt_hnp_support);
173 n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n",
174 (gadget->name ? gadget->name : ""));
175
176 return n;
177}
178static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
179
180/**
181 * show_driver: prints information about attached gadget (if any)
182 *
183 * Check "device.h" for details
184 */
185static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
186 char *buf)
187{
26c696c6
RZ
188 struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
189 struct usb_gadget_driver *driver = ci->driver;
e443b333
AS
190 int n = 0;
191
192 if (attr == NULL || buf == NULL) {
193 dev_err(dev, "[%s] EINVAL\n", __func__);
194 return 0;
195 }
196
197 if (driver == NULL)
198 return scnprintf(buf, PAGE_SIZE,
199 "There is no gadget attached!\n");
200
201 n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
202 (driver->function ? driver->function : ""));
203 n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
204 driver->max_speed);
205
206 return n;
207}
208static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
209
210/* Maximum event message length */
211#define DBG_DATA_MSG 64UL
212
213/* Maximum event messages */
214#define DBG_DATA_MAX 128UL
215
216/* Event buffer descriptor */
217static struct {
218 char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
219 unsigned idx; /* index */
220 unsigned tty; /* print to console? */
221 rwlock_t lck; /* lock */
222} dbg_data = {
223 .idx = 0,
224 .tty = 0,
eece09ec 225 .lck = __RW_LOCK_UNLOCKED(dbg_data.lck)
e443b333
AS
226};
227
228/**
229 * dbg_dec: decrements debug event index
230 * @idx: buffer index
231 */
232static void dbg_dec(unsigned *idx)
233{
234 *idx = (*idx - 1) & (DBG_DATA_MAX-1);
235}
236
237/**
238 * dbg_inc: increments debug event index
239 * @idx: buffer index
240 */
241static void dbg_inc(unsigned *idx)
242{
243 *idx = (*idx + 1) & (DBG_DATA_MAX-1);
244}
245
246/**
247 * dbg_print: prints the common part of the event
248 * @addr: endpoint address
249 * @name: event name
250 * @status: status
251 * @extra: extra information
252 */
253static void dbg_print(u8 addr, const char *name, int status, const char *extra)
254{
255 struct timeval tval;
256 unsigned int stamp;
257 unsigned long flags;
258
259 write_lock_irqsave(&dbg_data.lck, flags);
260
261 do_gettimeofday(&tval);
262 stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
263 stamp = stamp * 1000000 + tval.tv_usec;
264
265 scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
266 "%04X\t? %02X %-7.7s %4i ?\t%s\n",
267 stamp, addr, name, status, extra);
268
269 dbg_inc(&dbg_data.idx);
270
271 write_unlock_irqrestore(&dbg_data.lck, flags);
272
273 if (dbg_data.tty != 0)
274 pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
275 stamp, addr, name, status, extra);
276}
277
278/**
279 * dbg_done: prints a DONE event
280 * @addr: endpoint address
281 * @td: transfer descriptor
282 * @status: status
283 */
284void dbg_done(u8 addr, const u32 token, int status)
285{
286 char msg[DBG_DATA_MSG];
287
288 scnprintf(msg, sizeof(msg), "%d %02X",
289 (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
290 (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
291 dbg_print(addr, "DONE", status, msg);
292}
293
294/**
295 * dbg_event: prints a generic event
296 * @addr: endpoint address
297 * @name: event name
298 * @status: status
299 */
300void dbg_event(u8 addr, const char *name, int status)
301{
302 if (name != NULL)
303 dbg_print(addr, name, status, "");
304}
305
306/*
307 * dbg_queue: prints a QUEUE event
308 * @addr: endpoint address
309 * @req: USB request
310 * @status: status
311 */
312void dbg_queue(u8 addr, const struct usb_request *req, int status)
313{
314 char msg[DBG_DATA_MSG];
315
316 if (req != NULL) {
317 scnprintf(msg, sizeof(msg),
318 "%d %d", !req->no_interrupt, req->length);
319 dbg_print(addr, "QUEUE", status, msg);
320 }
321}
322
323/**
324 * dbg_setup: prints a SETUP event
325 * @addr: endpoint address
326 * @req: setup request
327 */
328void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
329{
330 char msg[DBG_DATA_MSG];
331
332 if (req != NULL) {
333 scnprintf(msg, sizeof(msg),
334 "%02X %02X %04X %04X %d", req->bRequestType,
335 req->bRequest, le16_to_cpu(req->wValue),
336 le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
337 dbg_print(addr, "SETUP", 0, msg);
338 }
339}
340
341/**
342 * show_events: displays the event buffer
343 *
344 * Check "device.h" for details
345 */
346static ssize_t show_events(struct device *dev, struct device_attribute *attr,
347 char *buf)
348{
349 unsigned long flags;
350 unsigned i, j, n = 0;
351
352 if (attr == NULL || buf == NULL) {
353 dev_err(dev->parent, "[%s] EINVAL\n", __func__);
354 return 0;
355 }
356
357 read_lock_irqsave(&dbg_data.lck, flags);
358
359 i = dbg_data.idx;
360 for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
361 n += strlen(dbg_data.buf[i]);
362 if (n >= PAGE_SIZE) {
363 n -= strlen(dbg_data.buf[i]);
364 break;
365 }
366 }
367 for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
368 j += scnprintf(buf + j, PAGE_SIZE - j,
369 "%s", dbg_data.buf[i]);
370
371 read_unlock_irqrestore(&dbg_data.lck, flags);
372
373 return n;
374}
375
376/**
377 * store_events: configure if events are going to be also printed to console
378 *
379 * Check "device.h" for details
380 */
381static ssize_t store_events(struct device *dev, struct device_attribute *attr,
382 const char *buf, size_t count)
383{
384 unsigned tty;
385
386 if (attr == NULL || buf == NULL) {
387 dev_err(dev, "[%s] EINVAL\n", __func__);
388 goto done;
389 }
390
391 if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
392 dev_err(dev, "<1|0>: enable|disable console log\n");
393 goto done;
394 }
395
396 dbg_data.tty = tty;
397 dev_info(dev, "tty = %u", dbg_data.tty);
398
399 done:
400 return count;
401}
402static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
403
404/**
405 * show_inters: interrupt status, enable status and historic
406 *
407 * Check "device.h" for details
408 */
409static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
410 char *buf)
411{
26c696c6 412 struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
e443b333
AS
413 unsigned long flags;
414 u32 intr;
415 unsigned i, j, n = 0;
416
417 if (attr == NULL || buf == NULL) {
26c696c6 418 dev_err(ci->dev, "[%s] EINVAL\n", __func__);
e443b333
AS
419 return 0;
420 }
421
26c696c6 422 spin_lock_irqsave(&ci->lock, flags);
e443b333
AS
423
424 /*n += scnprintf(buf + n, PAGE_SIZE - n,
26c696c6 425 "status = %08x\n", hw_read_intr_status(ci));
e443b333 426 n += scnprintf(buf + n, PAGE_SIZE - n,
26c696c6 427 "enable = %08x\n", hw_read_intr_enable(ci));*/
e443b333
AS
428
429 n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
430 isr_statistics.test);
431 n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n",
432 isr_statistics.ui);
433 n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
434 isr_statistics.uei);
435 n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
436 isr_statistics.pci);
437 n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
438 isr_statistics.uri);
439 n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
440 isr_statistics.sli);
441 n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
442 isr_statistics.none);
443 n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
444 isr_statistics.hndl.cnt);
445
446 for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
447 i &= ISR_MASK;
448 intr = isr_statistics.hndl.buf[i];
449
450 if (USBi_UI & intr)
451 n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
452 intr &= ~USBi_UI;
453 if (USBi_UEI & intr)
454 n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
455 intr &= ~USBi_UEI;
456 if (USBi_PCI & intr)
457 n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
458 intr &= ~USBi_PCI;
459 if (USBi_URI & intr)
460 n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
461 intr &= ~USBi_URI;
462 if (USBi_SLI & intr)
463 n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
464 intr &= ~USBi_SLI;
465 if (intr)
466 n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
467 if (isr_statistics.hndl.buf[i])
468 n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
469 }
470
26c696c6 471 spin_unlock_irqrestore(&ci->lock, flags);
e443b333
AS
472
473 return n;
474}
475
476/**
477 * store_inters: enable & force or disable an individual interrutps
478 * (to be used for test purposes only)
479 *
480 * Check "device.h" for details
481 */
482static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
483 const char *buf, size_t count)
484{
26c696c6 485 struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
e443b333
AS
486 unsigned long flags;
487 unsigned en, bit;
488
489 if (attr == NULL || buf == NULL) {
26c696c6 490 dev_err(ci->dev, "EINVAL\n");
e443b333
AS
491 goto done;
492 }
493
494 if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
26c696c6 495 dev_err(ci->dev, "<1|0> <bit>: enable|disable interrupt\n");
e443b333
AS
496 goto done;
497 }
498
26c696c6 499 spin_lock_irqsave(&ci->lock, flags);
e443b333 500 if (en) {
26c696c6 501 if (hw_intr_force(ci, bit))
e443b333
AS
502 dev_err(dev, "invalid bit number\n");
503 else
504 isr_statistics.test++;
505 } else {
26c696c6 506 if (hw_intr_clear(ci, bit))
e443b333
AS
507 dev_err(dev, "invalid bit number\n");
508 }
26c696c6 509 spin_unlock_irqrestore(&ci->lock, flags);
e443b333
AS
510
511 done:
512 return count;
513}
514static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
515
516/**
517 * show_port_test: reads port test mode
518 *
519 * Check "device.h" for details
520 */
521static ssize_t show_port_test(struct device *dev,
522 struct device_attribute *attr, char *buf)
523{
26c696c6 524 struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
e443b333
AS
525 unsigned long flags;
526 unsigned mode;
527
528 if (attr == NULL || buf == NULL) {
26c696c6 529 dev_err(ci->dev, "EINVAL\n");
e443b333
AS
530 return 0;
531 }
532
26c696c6
RZ
533 spin_lock_irqsave(&ci->lock, flags);
534 mode = hw_port_test_get(ci);
535 spin_unlock_irqrestore(&ci->lock, flags);
e443b333
AS
536
537 return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
538}
539
540/**
541 * store_port_test: writes port test mode
542 *
543 * Check "device.h" for details
544 */
545static ssize_t store_port_test(struct device *dev,
546 struct device_attribute *attr,
547 const char *buf, size_t count)
548{
26c696c6 549 struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
e443b333
AS
550 unsigned long flags;
551 unsigned mode;
552
553 if (attr == NULL || buf == NULL) {
26c696c6 554 dev_err(ci->dev, "[%s] EINVAL\n", __func__);
e443b333
AS
555 goto done;
556 }
557
558 if (sscanf(buf, "%u", &mode) != 1) {
26c696c6 559 dev_err(ci->dev, "<mode>: set port test mode");
e443b333
AS
560 goto done;
561 }
562
26c696c6
RZ
563 spin_lock_irqsave(&ci->lock, flags);
564 if (hw_port_test_set(ci, mode))
565 dev_err(ci->dev, "invalid mode\n");
566 spin_unlock_irqrestore(&ci->lock, flags);
e443b333
AS
567
568 done:
569 return count;
570}
571static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
572 show_port_test, store_port_test);
573
574/**
575 * show_qheads: DMA contents of all queue heads
576 *
577 * Check "device.h" for details
578 */
579static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
580 char *buf)
581{
26c696c6 582 struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
e443b333
AS
583 unsigned long flags;
584 unsigned i, j, n = 0;
585
586 if (attr == NULL || buf == NULL) {
26c696c6 587 dev_err(ci->dev, "[%s] EINVAL\n", __func__);
e443b333
AS
588 return 0;
589 }
590
26c696c6
RZ
591 spin_lock_irqsave(&ci->lock, flags);
592 for (i = 0; i < ci->hw_ep_max/2; i++) {
593 struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i];
e443b333 594 struct ci13xxx_ep *mEpTx =
26c696c6 595 &ci->ci13xxx_ep[i + ci->hw_ep_max/2];
e443b333
AS
596 n += scnprintf(buf + n, PAGE_SIZE - n,
597 "EP=%02i: RX=%08X TX=%08X\n",
598 i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
599 for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
600 n += scnprintf(buf + n, PAGE_SIZE - n,
601 " %04X: %08X %08X\n", j,
602 *((u32 *)mEpRx->qh.ptr + j),
603 *((u32 *)mEpTx->qh.ptr + j));
604 }
605 }
26c696c6 606 spin_unlock_irqrestore(&ci->lock, flags);
e443b333
AS
607
608 return n;
609}
610static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
611
612/**
613 * show_registers: dumps all registers
614 *
615 * Check "device.h" for details
616 */
617#define DUMP_ENTRIES 512
618static ssize_t show_registers(struct device *dev,
619 struct device_attribute *attr, char *buf)
620{
26c696c6 621 struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
e443b333
AS
622 unsigned long flags;
623 u32 *dump;
624 unsigned i, k, n = 0;
625
626 if (attr == NULL || buf == NULL) {
26c696c6 627 dev_err(ci->dev, "[%s] EINVAL\n", __func__);
e443b333
AS
628 return 0;
629 }
630
631 dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
632 if (!dump) {
26c696c6 633 dev_err(ci->dev, "%s: out of memory\n", __func__);
e443b333
AS
634 return 0;
635 }
636
26c696c6
RZ
637 spin_lock_irqsave(&ci->lock, flags);
638 k = hw_register_read(ci, dump, DUMP_ENTRIES);
639 spin_unlock_irqrestore(&ci->lock, flags);
e443b333
AS
640
641 for (i = 0; i < k; i++) {
642 n += scnprintf(buf + n, PAGE_SIZE - n,
643 "reg[0x%04X] = 0x%08X\n",
644 i * (unsigned)sizeof(u32), dump[i]);
645 }
646 kfree(dump);
647
648 return n;
649}
650
651/**
652 * store_registers: writes value to register address
653 *
654 * Check "device.h" for details
655 */
656static ssize_t store_registers(struct device *dev,
657 struct device_attribute *attr,
658 const char *buf, size_t count)
659{
26c696c6 660 struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
e443b333
AS
661 unsigned long addr, data, flags;
662
663 if (attr == NULL || buf == NULL) {
26c696c6 664 dev_err(ci->dev, "[%s] EINVAL\n", __func__);
e443b333
AS
665 goto done;
666 }
667
668 if (sscanf(buf, "%li %li", &addr, &data) != 2) {
26c696c6 669 dev_err(ci->dev,
e443b333
AS
670 "<addr> <data>: write data to register address\n");
671 goto done;
672 }
673
26c696c6
RZ
674 spin_lock_irqsave(&ci->lock, flags);
675 if (hw_register_write(ci, addr, data))
676 dev_err(ci->dev, "invalid address range\n");
677 spin_unlock_irqrestore(&ci->lock, flags);
e443b333
AS
678
679 done:
680 return count;
681}
682static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
683 show_registers, store_registers);
684
685/**
686 * show_requests: DMA contents of all requests currently queued (all endpts)
687 *
688 * Check "device.h" for details
689 */
690static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
691 char *buf)
692{
26c696c6 693 struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
e443b333
AS
694 unsigned long flags;
695 struct list_head *ptr = NULL;
696 struct ci13xxx_req *req = NULL;
697 unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
698
699 if (attr == NULL || buf == NULL) {
26c696c6 700 dev_err(ci->dev, "[%s] EINVAL\n", __func__);
e443b333
AS
701 return 0;
702 }
703
26c696c6
RZ
704 spin_lock_irqsave(&ci->lock, flags);
705 for (i = 0; i < ci->hw_ep_max; i++)
706 list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue)
e443b333
AS
707 {
708 req = list_entry(ptr, struct ci13xxx_req, queue);
709
710 n += scnprintf(buf + n, PAGE_SIZE - n,
711 "EP=%02i: TD=%08X %s\n",
26c696c6
RZ
712 i % ci->hw_ep_max/2, (u32)req->dma,
713 ((i < ci->hw_ep_max/2) ? "RX" : "TX"));
e443b333
AS
714
715 for (j = 0; j < qSize; j++)
716 n += scnprintf(buf + n, PAGE_SIZE - n,
717 " %04X: %08X\n", j,
718 *((u32 *)req->ptr + j));
719 }
26c696c6 720 spin_unlock_irqrestore(&ci->lock, flags);
e443b333
AS
721
722 return n;
723}
724static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
725
726/**
727 * dbg_create_files: initializes the attribute interface
728 * @dev: device
729 *
730 * This function returns an error code
731 */
732int dbg_create_files(struct device *dev)
733{
734 int retval = 0;
735
736 if (dev == NULL)
737 return -EINVAL;
738 retval = device_create_file(dev, &dev_attr_device);
739 if (retval)
740 goto done;
741 retval = device_create_file(dev, &dev_attr_driver);
742 if (retval)
743 goto rm_device;
744 retval = device_create_file(dev, &dev_attr_events);
745 if (retval)
746 goto rm_driver;
747 retval = device_create_file(dev, &dev_attr_inters);
748 if (retval)
749 goto rm_events;
750 retval = device_create_file(dev, &dev_attr_port_test);
751 if (retval)
752 goto rm_inters;
753 retval = device_create_file(dev, &dev_attr_qheads);
754 if (retval)
755 goto rm_port_test;
756 retval = device_create_file(dev, &dev_attr_registers);
757 if (retval)
758 goto rm_qheads;
759 retval = device_create_file(dev, &dev_attr_requests);
760 if (retval)
761 goto rm_registers;
762 return 0;
763
764 rm_registers:
765 device_remove_file(dev, &dev_attr_registers);
766 rm_qheads:
767 device_remove_file(dev, &dev_attr_qheads);
768 rm_port_test:
769 device_remove_file(dev, &dev_attr_port_test);
770 rm_inters:
771 device_remove_file(dev, &dev_attr_inters);
772 rm_events:
773 device_remove_file(dev, &dev_attr_events);
774 rm_driver:
775 device_remove_file(dev, &dev_attr_driver);
776 rm_device:
777 device_remove_file(dev, &dev_attr_device);
778 done:
779 return retval;
780}
781
782/**
783 * dbg_remove_files: destroys the attribute interface
784 * @dev: device
785 *
786 * This function returns an error code
787 */
788int dbg_remove_files(struct device *dev)
789{
790 if (dev == NULL)
791 return -EINVAL;
792 device_remove_file(dev, &dev_attr_requests);
793 device_remove_file(dev, &dev_attr_registers);
794 device_remove_file(dev, &dev_attr_qheads);
795 device_remove_file(dev, &dev_attr_port_test);
796 device_remove_file(dev, &dev_attr_inters);
797 device_remove_file(dev, &dev_attr_events);
798 device_remove_file(dev, &dev_attr_driver);
799 device_remove_file(dev, &dev_attr_device);
800 return 0;
801}