[adm5120] add copyright header to the USB driver's files
[openwrt.git] / target / linux / adm5120 / files / drivers / usb / host / adm5120-dbg.c
1 /*
2  * ADM5120 HCD (Host Controller Driver) for USB
3  *
4  * Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
5  *
6  * This file was derived from: drivers/usb/host/ohci-dbg.c
7  *   (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
8  *   (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
9  *
10  * This file is licenced under the GPL.
11  */
12
13 /*-------------------------------------------------------------------------*/
14
15 static inline char *ed_typestring(int ed_type)
16 {
17         switch (ed_type) {
18         case PIPE_CONTROL:
19                 return "ctrl";
20         case PIPE_BULK:
21                 return "bulk";
22         case PIPE_INTERRUPT:
23                 return "intr";
24         case PIPE_ISOCHRONOUS:
25                 return "isoc";
26         }
27         return "(bad ed_type)";
28 }
29
30 static inline char *ed_statestring(int state)
31 {
32         switch (state) {
33         case ED_IDLE:
34                 return "IDLE";
35         case ED_UNLINK:
36                 return "UNLINK";
37         case ED_OPER:
38                 return "OPER";
39         }
40         return "?STATE";
41 }
42
43 static inline char *pipestring(int pipe)
44 {
45         return ed_typestring(usb_pipetype(pipe));
46 }
47
48 static inline char *td_pidstring(u32 info)
49 {
50         switch (info & TD_DP) {
51         case TD_DP_SETUP:
52                 return "SETUP";
53         case TD_DP_IN:
54                 return "IN";
55         case TD_DP_OUT:
56                 return "OUT";
57         }
58         return "?PID";
59 }
60
61 static inline char *td_togglestring(u32 info)
62 {
63         switch (info & TD_T) {
64         case TD_T_DATA0:
65                 return "DATA0";
66         case TD_T_DATA1:
67                 return "DATA1";
68         case TD_T_CARRY:
69                 return "CARRY";
70         }
71         return "?TOGGLE";
72 }
73
74 /*-------------------------------------------------------------------------*/
75
76 #ifdef DEBUG
77
78 /* debug| print the main components of an URB
79  * small: 0) header + data packets 1) just header
80  */
81 static void __attribute__((unused))
82 urb_print(struct admhcd *ahcd, struct urb *urb, char *str, int small)
83 {
84         unsigned int pipe = urb->pipe;
85
86         if (!urb->dev || !urb->dev->bus) {
87                 admhc_dbg(ahcd, "%s URB: no dev", str);
88                 return;
89         }
90
91 #ifndef ADMHC_VERBOSE_DEBUG
92         if (urb->status != 0)
93 #endif
94         admhc_dbg(ahcd, "URB-%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d "
95                         "stat=%d\n",
96                         str,
97                         urb,
98                         usb_pipedevice (pipe),
99                         usb_pipeendpoint (pipe),
100                         usb_pipeout(pipe)? "out" : "in",
101                         pipestring(pipe),
102                         urb->transfer_flags,
103                         urb->actual_length,
104                         urb->transfer_buffer_length,
105                         urb->status);
106
107 #ifdef  ADMHC_VERBOSE_DEBUG
108         if (!small) {
109                 int i, len;
110
111                 if (usb_pipecontrol(pipe)) {
112                         admhc_dbg(ahcd, "setup(8):");
113                         for (i = 0; i < 8 ; i++)
114                                 printk (" %02x", ((__u8 *) urb->setup_packet) [i]);
115                         printk ("\n");
116                 }
117                 if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) {
118                         admhc_dbg(ahcd, "data(%d/%d):",
119                                 urb->actual_length,
120                                 urb->transfer_buffer_length);
121                         len = usb_pipeout(pipe)?
122                                                 urb->transfer_buffer_length: urb->actual_length;
123                         for (i = 0; i < 16 && i < len; i++)
124                                 printk(" %02x", ((__u8 *)urb->transfer_buffer)[i]);
125                         printk("%s stat:%d\n", i < len? "...": "", urb->status);
126                 }
127         }
128 #endif /* ADMHC_VERBOSE_DEBUG */
129 }
130
131 #define admhc_dbg_sw(ahcd, next, size, format, arg...) \
132         do { \
133         if (next) { \
134                 unsigned s_len; \
135                 s_len = scnprintf(*next, *size, format, ## arg ); \
136                 *size -= s_len; *next += s_len; \
137         } else \
138                 admhc_dbg(ahcd,format, ## arg ); \
139         } while (0);
140
141
142 static void admhc_dump_intr_mask(struct admhcd *ahcd, char *label, u32 mask,
143                 char **next, unsigned *size)
144 {
145         admhc_dbg_sw(ahcd, next, size, "%s 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n",
146                 label,
147                 mask,
148                 (mask & ADMHC_INTR_INTA) ? " INTA" : "",
149                 (mask & ADMHC_INTR_FATI) ? " FATI" : "",
150                 (mask & ADMHC_INTR_SWI) ? " SWI" : "",
151                 (mask & ADMHC_INTR_TDC) ? " TDC" : "",
152                 (mask & ADMHC_INTR_FNO) ? " FNO" : "",
153                 (mask & ADMHC_INTR_SO) ? " SO" : "",
154                 (mask & ADMHC_INTR_INSM) ? " INSM" : "",
155                 (mask & ADMHC_INTR_BABI) ? " BABI" : "",
156                 (mask & ADMHC_INTR_7) ? " !7!" : "",
157                 (mask & ADMHC_INTR_6) ? " !6!" : "",
158                 (mask & ADMHC_INTR_RESI) ? " RESI" : "",
159                 (mask & ADMHC_INTR_SOFI) ? " SOFI" : ""
160                 );
161 }
162
163 static void maybe_print_eds(struct admhcd *ahcd, char *label, u32 value,
164                 char **next, unsigned *size)
165 {
166         if (value)
167                 admhc_dbg_sw(ahcd, next, size, "%s %08x\n", label, value);
168 }
169
170 static char *buss2string (int state)
171 {
172         switch (state) {
173         case ADMHC_BUSS_RESET:
174                 return "reset";
175         case ADMHC_BUSS_RESUME:
176                 return "resume";
177         case ADMHC_BUSS_OPER:
178                 return "operational";
179         case ADMHC_BUSS_SUSPEND:
180                 return "suspend";
181         }
182         return "?state";
183 }
184
185 static void
186 admhc_dump_status(struct admhcd *ahcd, char **next, unsigned *size)
187 {
188         struct admhcd_regs __iomem *regs = ahcd->regs;
189         u32                     temp;
190
191         temp = admhc_readl(ahcd, &regs->gencontrol);
192         admhc_dbg_sw(ahcd, next, size,
193                 "gencontrol 0x%08x%s%s%s%s\n",
194                 temp,
195                 (temp & ADMHC_CTRL_UHFE) ? " UHFE" : "",
196                 (temp & ADMHC_CTRL_SIR) ? " SIR" : "",
197                 (temp & ADMHC_CTRL_DMAA) ? " DMAA" : "",
198                 (temp & ADMHC_CTRL_SR) ? " SR" : ""
199                 );
200
201         temp = admhc_readl(ahcd, &regs->host_control);
202         admhc_dbg_sw(ahcd, next, size,
203                 "host_control 0x%08x BUSS=%s%s\n",
204                 temp,
205                 buss2string(temp & ADMHC_HC_BUSS),
206                 (temp & ADMHC_HC_DMAE) ? " DMAE" : ""
207                 );
208
209         admhc_dump_intr_mask(ahcd, "int_status",
210                         admhc_readl(ahcd, &regs->int_status),
211                         next, size);
212         admhc_dump_intr_mask(ahcd, "int_enable",
213                         admhc_readl(ahcd, &regs->int_enable),
214                         next, size);
215
216         maybe_print_eds(ahcd, "hosthead",
217                         admhc_readl(ahcd, &regs->hosthead), next, size);
218 }
219
220 #define dbg_port_sw(hc,num,value,next,size) \
221         admhc_dbg_sw(hc, next, size, \
222                 "portstatus [%d] " \
223                 "0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \
224                 num, temp, \
225                 (temp & ADMHC_PS_PRSC) ? " PRSC" : "", \
226                 (temp & ADMHC_PS_OCIC) ? " OCIC" : "", \
227                 (temp & ADMHC_PS_PSSC) ? " PSSC" : "", \
228                 (temp & ADMHC_PS_PESC) ? " PESC" : "", \
229                 (temp & ADMHC_PS_CSC) ? " CSC" : "", \
230                 \
231                 (temp & ADMHC_PS_LSDA) ? " LSDA" : "", \
232                 (temp & ADMHC_PS_PPS) ? " PPS" : "", \
233                 (temp & ADMHC_PS_PRS) ? " PRS" : "", \
234                 (temp & ADMHC_PS_POCI) ? " POCI" : "", \
235                 (temp & ADMHC_PS_PSS) ? " PSS" : "", \
236                 \
237                 (temp & ADMHC_PS_PES) ? " PES" : "", \
238                 (temp & ADMHC_PS_CCS) ? " CCS" : "" \
239                 );
240
241
242 static void
243 admhc_dump_roothub(
244         struct admhcd *ahcd,
245         int verbose,
246         char **next,
247         unsigned *size)
248 {
249         u32                     temp, i;
250
251         temp = admhc_read_rhdesc(ahcd);
252         if (temp == ~(u32)0)
253                 return;
254
255         if (verbose) {
256                 admhc_dbg_sw(ahcd, next, size,
257                         "rhdesc %08x%s%s%s%s%s%s PPCM=%02x%s%s%s%s NUMP=%d(%d)\n",
258                         temp,
259                         (temp & ADMHC_RH_CRWE) ? " CRWE" : "",
260                         (temp & ADMHC_RH_OCIC) ? " OCIC" : "",
261                         (temp & ADMHC_RH_LPSC) ? " LPSC" : "",
262                         (temp & ADMHC_RH_LPSC) ? " DRWE" : "",
263                         (temp & ADMHC_RH_LPSC) ? " OCI" : "",
264                         (temp & ADMHC_RH_LPSC) ? " LPS" : "",
265                         ((temp & ADMHC_RH_PPCM) >> 16),
266                         (temp & ADMHC_RH_NOCP) ? " NOCP" : "",
267                         (temp & ADMHC_RH_OCPM) ? " OCPM" : "",
268                         (temp & ADMHC_RH_NPS) ? " NPS" : "",
269                         (temp & ADMHC_RH_PSM) ? " PSM" : "",
270                         (temp & ADMHC_RH_NUMP), ahcd->num_ports
271                         );
272         }
273
274         for (i = 0; i < ahcd->num_ports; i++) {
275                 temp = admhc_read_portstatus(ahcd, i);
276                 dbg_port_sw(ahcd, i, temp, next, size);
277         }
278 }
279
280 static void admhc_dump(struct admhcd *ahcd, int verbose)
281 {
282         admhc_dbg(ahcd, "ADMHC ahcd state\n");
283
284         /* dumps some of the state we know about */
285         admhc_dump_status(ahcd, NULL, NULL);
286         admhc_dbg(ahcd,"current frame #%04x\n",
287                 admhc_frame_no(ahcd));
288
289         admhc_dump_roothub(ahcd, verbose, NULL, NULL);
290 }
291
292 static const char data0[] = "DATA0";
293 static const char data1[] = "DATA1";
294
295 static void admhc_dump_td(const struct admhcd *ahcd, const char *label,
296                 const struct td *td)
297 {
298         u32     tmp;
299
300         admhc_dbg(ahcd, "%s td %p; urb %p index %d; hwNextTD %08x\n",
301                 label, td,
302                 td->urb, td->index,
303                 hc32_to_cpup(ahcd, &td->hwNextTD));
304
305         tmp = hc32_to_cpup(ahcd, &td->hwINFO);
306         admhc_dbg(ahcd, "     status %08x%s CC=%x EC=%d %s %s ISI=%x FN=%x\n",
307                 tmp,
308                 (tmp & TD_OWN) ? " OWN" : "",
309                 TD_CC_GET(tmp),
310                 TD_EC_GET(tmp),
311                 td_togglestring(tmp),
312                 td_pidstring(tmp),
313                 TD_ISI_GET(tmp),
314                 TD_FN_GET(tmp));
315
316         tmp = hc32_to_cpup(ahcd, &td->hwCBL);
317         admhc_dbg(ahcd, "     dbp %08x; cbl %08x; LEN=%d%s\n",
318                 hc32_to_cpup(ahcd, &td->hwDBP),
319                 tmp,
320                 TD_BL_GET(tmp),
321                 (tmp & TD_IE) ? " IE" : "");
322 }
323
324 /* caller MUST own hcd spinlock if verbose is set! */
325 static void __attribute__((unused))
326 admhc_dump_ed(const struct admhcd *ahcd, const char *label,
327                 const struct ed *ed, int verbose)
328 {
329         u32 tmp = hc32_to_cpu(ahcd, ed->hwINFO);
330
331         admhc_dbg(ahcd, "%s ed %p %s type %s; next ed %08x\n",
332                 label,
333                 ed, ed_statestring(ed->state), ed_typestring(ed->type),
334                 hc32_to_cpup(ahcd, &ed->hwNextED));
335
336         admhc_dbg(ahcd, "  info %08x MAX=%d%s%s%s%s EP=%d DEV=%d\n", tmp,
337                 ED_MPS_GET(tmp),
338                 (tmp & ED_ISO) ? " ISO" : "",
339                 (tmp & ED_SKIP) ? " SKIP" : "",
340                 (tmp & ED_SPEED_FULL) ? " FULL" : " LOW",
341                 (tmp & ED_INT) ? " INT" : "",
342                 ED_EN_GET(tmp),
343                 ED_FA_GET(tmp));
344
345         tmp = hc32_to_cpup(ahcd, &ed->hwHeadP);
346         admhc_dbg(ahcd, "  tds: head %08x tail %08x %s%s%s\n",
347                 tmp & TD_MASK,
348                 hc32_to_cpup (ahcd, &ed->hwTailP),
349                 (tmp & ED_C) ? data1 : data0,
350                 (tmp & ED_H) ? " HALT" : "",
351                 verbose ? " td list follows" : " (not listing)");
352
353         if (verbose) {
354                 struct list_head        *tmp;
355
356                 /* use ed->td_list because HC concurrently modifies
357                  * hwNextTD as it accumulates ed_donelist.
358                  */
359                 list_for_each(tmp, &ed->td_list) {
360                         struct td               *td;
361                         td = list_entry(tmp, struct td, td_list);
362                         admhc_dump_td (ahcd, "  ->", td);
363                 }
364         }
365 }
366
367 #else /* ifdef DEBUG */
368
369 static inline void urb_print(struct admhcd *ahcd, struct urb * urb, char * str,
370         int small) {}
371 static inline void admhc_dump_ed(const struct admhcd *ahcd, const char *label,
372         const struct ed *ed, int verbose) {}
373 static inline void admhc_dump_td(const struct admhcd *ahcd, const char *label,
374         const struct td *td) {}
375 static inline void admhc_dump(struct admhcd *ahcd, int verbose) {}
376
377 #undef ADMHC_VERBOSE_DEBUG
378
379 #endif /* DEBUG */
380
381 /*-------------------------------------------------------------------------*/
382
383 #ifdef STUB_DEBUG_FILES
384
385 static inline void create_debug_files(struct admhcd *bus) { }
386 static inline void remove_debug_files(struct admhcd *bus) { }
387
388 #else
389
390 static ssize_t
391 show_list(struct admhcd *ahcd, char *buf, size_t count, struct ed *ed)
392 {
393         unsigned                temp, size = count;
394
395         if (!ed)
396                 return 0;
397
398         /* dump a snapshot of the bulk or control schedule */
399         while (ed) {
400                 u32 info = hc32_to_cpu(ahcd, ed->hwINFO);
401                 u32 headp = hc32_to_cpu(ahcd, ed->hwHeadP);
402                 u32 tailp = hc32_to_cpu(ahcd, ed->hwTailP);
403                 struct list_head *entry;
404                 struct td       *td;
405
406                 temp = scnprintf(buf, size,
407                         "ed/%p %s %s %cs dev%d ep%d %s%smax %d %08x%s%s %s"
408                         " h:%08x t:%08x",
409                         ed,
410                         ed_statestring(ed->state),
411                         ed_typestring (ed->type),
412                         (info & ED_SPEED_FULL) ? 'f' : 'l',
413                         info & ED_FA_MASK,
414                         (info >> ED_EN_SHIFT) & ED_EN_MASK,
415                         (info & ED_INT) ? "INT " : "",
416                         (info & ED_ISO) ? "ISO " : "",
417                         (info >> ED_MPS_SHIFT) & ED_MPS_MASK ,
418                         info,
419                         (info & ED_SKIP) ? " S" : "",
420                         (headp & ED_H) ? " H" : "",
421                         (headp & ED_C) ? data1 : data0,
422                         headp & ED_MASK,tailp);
423                 size -= temp;
424                 buf += temp;
425
426                 list_for_each(entry, &ed->td_list) {
427                         u32             dbp, cbl;
428
429                         td = list_entry(entry, struct td, td_list);
430                         info = hc32_to_cpup (ahcd, &td->hwINFO);
431                         dbp = hc32_to_cpup (ahcd, &td->hwDBP);
432                         cbl = hc32_to_cpup (ahcd, &td->hwCBL);
433
434                         temp = scnprintf(buf, size,
435                                 "\n\ttd/%p %s %d %s%scc=%x urb %p (%08x,%08x)",
436                                 td,
437                                 td_pidstring(info),
438                                 TD_BL_GET(cbl),
439                                 (info & TD_OWN) ? "" : "DONE ",
440                                 (cbl & TD_IE) ? "IE " : "",
441                                 TD_CC_GET (info), td->urb, info, cbl);
442                         size -= temp;
443                         buf += temp;
444                 }
445
446                 temp = scnprintf(buf, size, "\n");
447                 size -= temp;
448                 buf += temp;
449
450                 ed = ed->ed_next;
451         }
452         return count - size;
453 }
454
455 static ssize_t
456 show_async(struct class_device *class_dev, char *buf)
457 {
458         struct usb_bus          *bus;
459         struct usb_hcd          *hcd;
460         struct admhcd           *ahcd;
461         size_t                  temp;
462         unsigned long           flags;
463
464         bus = class_get_devdata(class_dev);
465         hcd = bus_to_hcd(bus);
466         ahcd = hcd_to_admhcd(hcd);
467
468         /* display control and bulk lists together, for simplicity */
469         spin_lock_irqsave(&ahcd->lock, flags);
470         temp = show_list(ahcd, buf, PAGE_SIZE, ahcd->ed_head);
471         spin_unlock_irqrestore(&ahcd->lock, flags);
472
473         return temp;
474 }
475 static CLASS_DEVICE_ATTR(async, S_IRUGO, show_async, NULL);
476
477
478 #define DBG_SCHED_LIMIT 64
479
480 static ssize_t
481 show_periodic(struct class_device *class_dev, char *buf)
482 {
483         struct usb_bus          *bus;
484         struct usb_hcd          *hcd;
485         struct admhcd           *ahcd;
486         struct ed               **seen, *ed;
487         unsigned long           flags;
488         unsigned                temp, size, seen_count;
489         char                    *next;
490         unsigned                i;
491
492         if (!(seen = kmalloc(DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC)))
493                 return 0;
494         seen_count = 0;
495
496         bus = class_get_devdata(class_dev);
497         hcd = bus_to_hcd(bus);
498         ahcd = hcd_to_admhcd(hcd);
499         next = buf;
500         size = PAGE_SIZE;
501
502         temp = scnprintf(next, size, "size = %d\n", NUM_INTS);
503         size -= temp;
504         next += temp;
505
506         /* dump a snapshot of the periodic schedule (and load) */
507         spin_lock_irqsave(&ahcd->lock, flags);
508         for (i = 0; i < NUM_INTS; i++) {
509                 if (!(ed = ahcd->periodic [i]))
510                         continue;
511
512                 temp = scnprintf(next, size, "%2d [%3d]:", i, ahcd->load [i]);
513                 size -= temp;
514                 next += temp;
515
516                 do {
517                         temp = scnprintf(next, size, " ed%d/%p",
518                                 ed->interval, ed);
519                         size -= temp;
520                         next += temp;
521                         for (temp = 0; temp < seen_count; temp++) {
522                                 if (seen [temp] == ed)
523                                         break;
524                         }
525
526                         /* show more info the first time around */
527                         if (temp == seen_count) {
528                                 u32     info = hc32_to_cpu (ahcd, ed->hwINFO);
529                                 struct list_head        *entry;
530                                 unsigned                qlen = 0;
531
532                                 /* qlen measured here in TDs, not urbs */
533                                 list_for_each (entry, &ed->td_list)
534                                         qlen++;
535                                 temp = scnprintf(next, size,
536                                         " (%cs dev%d ep%d%s qlen %u"
537                                         " max %d %08x%s%s)",
538                                         (info & ED_SPEED_FULL) ? 'f' : 'l',
539                                         ED_FA_GET(info),
540                                         ED_EN_GET(info),
541                                         (info & ED_ISO) ? "iso" : "int",
542                                         qlen,
543                                         ED_MPS_GET(info),
544                                         info,
545                                         (info & ED_SKIP) ? " K" : "",
546                                         (ed->hwHeadP &
547                                                 cpu_to_hc32(ahcd, ED_H)) ?
548                                                         " H" : "");
549                                 size -= temp;
550                                 next += temp;
551
552                                 if (seen_count < DBG_SCHED_LIMIT)
553                                         seen [seen_count++] = ed;
554
555                                 ed = ed->ed_next;
556
557                         } else {
558                                 /* we've seen it and what's after */
559                                 temp = 0;
560                                 ed = NULL;
561                         }
562
563                 } while (ed);
564
565                 temp = scnprintf(next, size, "\n");
566                 size -= temp;
567                 next += temp;
568         }
569         spin_unlock_irqrestore(&ahcd->lock, flags);
570         kfree (seen);
571
572         return PAGE_SIZE - size;
573 }
574 static CLASS_DEVICE_ATTR(periodic, S_IRUGO, show_periodic, NULL);
575
576
577 #undef DBG_SCHED_LIMIT
578
579 static ssize_t
580 show_registers(struct class_device *class_dev, char *buf)
581 {
582         struct usb_bus          *bus;
583         struct usb_hcd          *hcd;
584         struct admhcd           *ahcd;
585         struct admhcd_regs __iomem *regs;
586         unsigned long           flags;
587         unsigned                temp, size;
588         char                    *next;
589         u32                     rdata;
590
591         bus = class_get_devdata(class_dev);
592         hcd = bus_to_hcd(bus);
593         ahcd = hcd_to_admhcd(hcd);
594         regs = ahcd->regs;
595         next = buf;
596         size = PAGE_SIZE;
597
598         spin_lock_irqsave(&ahcd->lock, flags);
599
600         /* dump driver info, then registers in spec order */
601
602         admhc_dbg_sw(ahcd, &next, &size,
603                 "bus %s, device %s\n"
604                 "%s\n"
605                 "%s version " DRIVER_VERSION "\n",
606                 hcd->self.controller->bus->name,
607                 hcd->self.controller->bus_id,
608                 hcd->product_desc,
609                 hcd_name);
610
611         if (bus->controller->power.power_state.event) {
612                 size -= scnprintf(next, size,
613                         "SUSPENDED (no register access)\n");
614                 goto done;
615         }
616
617         admhc_dump_status(ahcd, &next, &size);
618
619         /* other registers mostly affect frame timings */
620         rdata = admhc_readl(ahcd, &regs->fminterval);
621         temp = scnprintf(next, size,
622                         "fmintvl 0x%08x %sFSLDP=0x%04x FI=0x%04x\n",
623                         rdata, (rdata & ADMHC_SFI_FIT) ? "FIT " : "",
624                         (rdata >> ADMHC_SFI_FSLDP_SHIFT) & ADMHC_SFI_FSLDP_MASK,
625                         rdata  & ADMHC_SFI_FI_MASK);
626         size -= temp;
627         next += temp;
628
629         rdata = admhc_readl(ahcd, &regs->fmnumber);
630         temp = scnprintf(next, size, "fmnumber 0x%08x %sFR=0x%04x FN=%04x\n",
631                         rdata, (rdata & ADMHC_SFN_FRT) ? "FRT " : "",
632                         (rdata >> ADMHC_SFN_FR_SHIFT) & ADMHC_SFN_FR_MASK,
633                         rdata  & ADMHC_SFN_FN_MASK);
634         size -= temp;
635         next += temp;
636
637         /* TODO: use predefined bitmask */
638         rdata = admhc_readl(ahcd, &regs->lsthresh);
639         temp = scnprintf(next, size, "lsthresh 0x%04x\n",
640                         rdata & 0x3fff);
641         size -= temp;
642         next += temp;
643
644         temp = scnprintf(next, size, "hub poll timer: %s\n",
645                         admhcd_to_hcd(ahcd)->poll_rh ? "ON" : "OFF");
646         size -= temp;
647         next += temp;
648
649         /* roothub */
650         admhc_dump_roothub(ahcd, 1, &next, &size);
651
652 done:
653         spin_unlock_irqrestore(&ahcd->lock, flags);
654         return PAGE_SIZE - size;
655 }
656 static CLASS_DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL);
657
658
659 static inline void create_debug_files (struct admhcd *ahcd)
660 {
661         struct class_device *cldev = admhcd_to_hcd(ahcd)->self.class_dev;
662         int retval;
663
664         retval = class_device_create_file(cldev, &class_device_attr_async);
665         retval = class_device_create_file(cldev, &class_device_attr_periodic);
666         retval = class_device_create_file(cldev, &class_device_attr_registers);
667         admhc_dbg(ahcd, "created debug files\n");
668 }
669
670 static inline void remove_debug_files (struct admhcd *ahcd)
671 {
672         struct class_device *cldev = admhcd_to_hcd(ahcd)->self.class_dev;
673
674         class_device_remove_file(cldev, &class_device_attr_async);
675         class_device_remove_file(cldev, &class_device_attr_periodic);
676         class_device_remove_file(cldev, &class_device_attr_registers);
677 }
678
679 #endif
680
681 /*-------------------------------------------------------------------------*/