]> err.no Git - linux-2.6/blob - drivers/usb/musb/musb_procfs.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
[linux-2.6] / drivers / usb / musb / musb_procfs.c
1 /*
2  * MUSB OTG driver debug support
3  *
4  * Copyright 2005 Mentor Graphics Corporation
5  * Copyright (C) 2005-2006 by Texas Instruments
6  * Copyright (C) 2006-2007 Nokia Corporation
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
25  * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34
35 #include <linux/kernel.h>
36 #include <linux/proc_fs.h>
37 #include <linux/seq_file.h>
38 #include <linux/uaccess.h>      /* FIXME remove procfs writes */
39 #include <asm/arch/hardware.h>
40
41 #include "musb_core.h"
42
43 #include "davinci.h"
44
45 #ifdef CONFIG_USB_MUSB_HDRC_HCD
46
47 static int dump_qh(struct musb_qh *qh, char *buf, unsigned max)
48 {
49         int                             count;
50         int                             tmp;
51         struct usb_host_endpoint        *hep = qh->hep;
52         struct urb                      *urb;
53
54         count = snprintf(buf, max, "    qh %p dev%d ep%d%s max%d\n",
55                         qh, qh->dev->devnum, qh->epnum,
56                         ({ char *s; switch (qh->type) {
57                         case USB_ENDPOINT_XFER_BULK:
58                                 s = "-bulk"; break;
59                         case USB_ENDPOINT_XFER_INT:
60                                 s = "-int"; break;
61                         case USB_ENDPOINT_XFER_CONTROL:
62                                 s = ""; break;
63                         default:
64                                 s = "iso"; break;
65                         }; s; }),
66                         qh->maxpacket);
67         if (count <= 0)
68                 return 0;
69         buf += count;
70         max -= count;
71
72         list_for_each_entry(urb, &hep->urb_list, urb_list) {
73                 tmp = snprintf(buf, max, "\t%s urb %p %d/%d\n",
74                                 usb_pipein(urb->pipe) ? "in" : "out",
75                                 urb, urb->actual_length,
76                                 urb->transfer_buffer_length);
77                 if (tmp <= 0)
78                         break;
79                 tmp = min(tmp, (int)max);
80                 count += tmp;
81                 buf += tmp;
82                 max -= tmp;
83         }
84         return count;
85 }
86
87 static int
88 dump_queue(struct list_head *q, char *buf, unsigned max)
89 {
90         int             count = 0;
91         struct musb_qh  *qh;
92
93         list_for_each_entry(qh, q, ring) {
94                 int     tmp;
95
96                 tmp = dump_qh(qh, buf, max);
97                 if (tmp <= 0)
98                         break;
99                 tmp = min(tmp, (int)max);
100                 count += tmp;
101                 buf += tmp;
102                 max -= tmp;
103         }
104         return count;
105 }
106
107 #endif  /* HCD */
108
109 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
110 static int dump_ep(struct musb_ep *ep, char *buffer, unsigned max)
111 {
112         char            *buf = buffer;
113         int             code = 0;
114         void __iomem    *regs = ep->hw_ep->regs;
115         char            *mode = "1buf";
116
117         if (ep->is_in) {
118                 if (ep->hw_ep->tx_double_buffered)
119                         mode = "2buf";
120         } else {
121                 if (ep->hw_ep->rx_double_buffered)
122                         mode = "2buf";
123         }
124
125         do {
126                 struct usb_request      *req;
127
128                 code = snprintf(buf, max,
129                                 "\n%s (hw%d): %s%s, csr %04x maxp %04x\n",
130                                 ep->name, ep->current_epnum,
131                                 mode, ep->dma ? " dma" : "",
132                                 musb_readw(regs,
133                                         (ep->is_in || !ep->current_epnum)
134                                                 ? MUSB_TXCSR
135                                                 : MUSB_RXCSR),
136                                 musb_readw(regs, ep->is_in
137                                                 ? MUSB_TXMAXP
138                                                 : MUSB_RXMAXP)
139                                 );
140                 if (code <= 0)
141                         break;
142                 code = min(code, (int) max);
143                 buf += code;
144                 max -= code;
145
146                 if (is_cppi_enabled() && ep->current_epnum) {
147                         unsigned        cppi = ep->current_epnum - 1;
148                         void __iomem    *base = ep->musb->ctrl_base;
149                         unsigned        off1 = cppi << 2;
150                         void __iomem    *ram = base;
151                         char            tmp[16];
152
153                         if (ep->is_in) {
154                                 ram += DAVINCI_TXCPPI_STATERAM_OFFSET(cppi);
155                                 tmp[0] = 0;
156                         } else {
157                                 ram += DAVINCI_RXCPPI_STATERAM_OFFSET(cppi);
158                                 snprintf(tmp, sizeof tmp, "%d left, ",
159                                         musb_readl(base,
160                                         DAVINCI_RXCPPI_BUFCNT0_REG + off1));
161                         }
162
163                         code = snprintf(buf, max, "%cX DMA%d: %s"
164                                         "%08x %08x, %08x %08x; "
165                                         "%08x %08x %08x .. %08x\n",
166                                 ep->is_in ? 'T' : 'R',
167                                 ep->current_epnum - 1, tmp,
168                                 musb_readl(ram, 0 * 4),
169                                 musb_readl(ram, 1 * 4),
170                                 musb_readl(ram, 2 * 4),
171                                 musb_readl(ram, 3 * 4),
172                                 musb_readl(ram, 4 * 4),
173                                 musb_readl(ram, 5 * 4),
174                                 musb_readl(ram, 6 * 4),
175                                 musb_readl(ram, 7 * 4));
176                         if (code <= 0)
177                                 break;
178                         code = min(code, (int) max);
179                         buf += code;
180                         max -= code;
181                 }
182
183                 if (list_empty(&ep->req_list)) {
184                         code = snprintf(buf, max, "\t(queue empty)\n");
185                         if (code <= 0)
186                                 break;
187                         code = min(code, (int) max);
188                         buf += code;
189                         max -= code;
190                         break;
191                 }
192                 list_for_each_entry(req, &ep->req_list, list) {
193                         code = snprintf(buf, max, "\treq %p, %s%s%d/%d\n",
194                                         req,
195                                         req->zero ? "zero, " : "",
196                                         req->short_not_ok ? "!short, " : "",
197                                         req->actual, req->length);
198                         if (code <= 0)
199                                 break;
200                         code = min(code, (int) max);
201                         buf += code;
202                         max -= code;
203                 }
204         } while (0);
205         return buf - buffer;
206 }
207 #endif
208
209 static int
210 dump_end_info(struct musb *musb, u8 epnum, char *aBuffer, unsigned max)
211 {
212         int                     code = 0;
213         char                    *buf = aBuffer;
214         struct musb_hw_ep       *hw_ep = &musb->endpoints[epnum];
215
216         do {
217                 musb_ep_select(musb->mregs, epnum);
218 #ifdef CONFIG_USB_MUSB_HDRC_HCD
219                 if (is_host_active(musb)) {
220                         int             dump_rx, dump_tx;
221                         void __iomem    *regs = hw_ep->regs;
222
223                         /* TEMPORARY (!) until we have a real periodic
224                          * schedule tree ...
225                          */
226                         if (!epnum) {
227                                 /* control is shared, uses RX queue
228                                  * but (mostly) shadowed tx registers
229                                  */
230                                 dump_tx = !list_empty(&musb->control);
231                                 dump_rx = 0;
232                         } else if (hw_ep == musb->bulk_ep) {
233                                 dump_tx = !list_empty(&musb->out_bulk);
234                                 dump_rx = !list_empty(&musb->in_bulk);
235                         } else if (musb->periodic[epnum]) {
236                                 struct usb_host_endpoint        *hep;
237
238                                 hep = musb->periodic[epnum]->hep;
239                                 dump_rx = hep->desc.bEndpointAddress
240                                                 & USB_ENDPOINT_DIR_MASK;
241                                 dump_tx = !dump_rx;
242                         } else
243                                 break;
244                         /* END TEMPORARY */
245
246
247                         if (dump_rx) {
248                                 code = snprintf(buf, max,
249                                         "\nRX%d: %s rxcsr %04x interval %02x "
250                                         "max %04x type %02x; "
251                                         "dev %d hub %d port %d"
252                                         "\n",
253                                         epnum,
254                                         hw_ep->rx_double_buffered
255                                                 ? "2buf" : "1buf",
256                                         musb_readw(regs, MUSB_RXCSR),
257                                         musb_readb(regs, MUSB_RXINTERVAL),
258                                         musb_readw(regs, MUSB_RXMAXP),
259                                         musb_readb(regs, MUSB_RXTYPE),
260                                         /* FIXME:  assumes multipoint */
261                                         musb_readb(musb->mregs,
262                                                 MUSB_BUSCTL_OFFSET(epnum,
263                                                 MUSB_RXFUNCADDR)),
264                                         musb_readb(musb->mregs,
265                                                 MUSB_BUSCTL_OFFSET(epnum,
266                                                 MUSB_RXHUBADDR)),
267                                         musb_readb(musb->mregs,
268                                                 MUSB_BUSCTL_OFFSET(epnum,
269                                                 MUSB_RXHUBPORT))
270                                         );
271                                 if (code <= 0)
272                                         break;
273                                 code = min(code, (int) max);
274                                 buf += code;
275                                 max -= code;
276
277                                 if (is_cppi_enabled()
278                                                 && epnum
279                                                 && hw_ep->rx_channel) {
280                                         unsigned        cppi = epnum - 1;
281                                         unsigned        off1 = cppi << 2;
282                                         void __iomem    *base;
283                                         void __iomem    *ram;
284                                         char            tmp[16];
285
286                                         base = musb->ctrl_base;
287                                         ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
288                                                         cppi) + base;
289                                         snprintf(tmp, sizeof tmp, "%d left, ",
290                                                 musb_readl(base,
291                                                 DAVINCI_RXCPPI_BUFCNT0_REG
292                                                                 + off1));
293
294                                         code = snprintf(buf, max,
295                                                 "    rx dma%d: %s"
296                                                 "%08x %08x, %08x %08x; "
297                                                 "%08x %08x %08x .. %08x\n",
298                                                 cppi, tmp,
299                                                 musb_readl(ram, 0 * 4),
300                                                 musb_readl(ram, 1 * 4),
301                                                 musb_readl(ram, 2 * 4),
302                                                 musb_readl(ram, 3 * 4),
303                                                 musb_readl(ram, 4 * 4),
304                                                 musb_readl(ram, 5 * 4),
305                                                 musb_readl(ram, 6 * 4),
306                                                 musb_readl(ram, 7 * 4));
307                                         if (code <= 0)
308                                                 break;
309                                         code = min(code, (int) max);
310                                         buf += code;
311                                         max -= code;
312                                 }
313
314                                 if (hw_ep == musb->bulk_ep
315                                                 && !list_empty(
316                                                         &musb->in_bulk)) {
317                                         code = dump_queue(&musb->in_bulk,
318                                                         buf, max);
319                                         if (code <= 0)
320                                                 break;
321                                         code = min(code, (int) max);
322                                         buf += code;
323                                         max -= code;
324                                 } else if (musb->periodic[epnum]) {
325                                         code = dump_qh(musb->periodic[epnum],
326                                                         buf, max);
327                                         if (code <= 0)
328                                                 break;
329                                         code = min(code, (int) max);
330                                         buf += code;
331                                         max -= code;
332                                 }
333                         }
334
335                         if (dump_tx) {
336                                 code = snprintf(buf, max,
337                                         "\nTX%d: %s txcsr %04x interval %02x "
338                                         "max %04x type %02x; "
339                                         "dev %d hub %d port %d"
340                                         "\n",
341                                         epnum,
342                                         hw_ep->tx_double_buffered
343                                                 ? "2buf" : "1buf",
344                                         musb_readw(regs, MUSB_TXCSR),
345                                         musb_readb(regs, MUSB_TXINTERVAL),
346                                         musb_readw(regs, MUSB_TXMAXP),
347                                         musb_readb(regs, MUSB_TXTYPE),
348                                         /* FIXME:  assumes multipoint */
349                                         musb_readb(musb->mregs,
350                                                 MUSB_BUSCTL_OFFSET(epnum,
351                                                 MUSB_TXFUNCADDR)),
352                                         musb_readb(musb->mregs,
353                                                 MUSB_BUSCTL_OFFSET(epnum,
354                                                 MUSB_TXHUBADDR)),
355                                         musb_readb(musb->mregs,
356                                                 MUSB_BUSCTL_OFFSET(epnum,
357                                                 MUSB_TXHUBPORT))
358                                         );
359                                 if (code <= 0)
360                                         break;
361                                 code = min(code, (int) max);
362                                 buf += code;
363                                 max -= code;
364
365                                 if (is_cppi_enabled()
366                                                 && epnum
367                                                 && hw_ep->tx_channel) {
368                                         unsigned        cppi = epnum - 1;
369                                         void __iomem    *base;
370                                         void __iomem    *ram;
371
372                                         base = musb->ctrl_base;
373                                         ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
374                                                         cppi) + base;
375                                         code = snprintf(buf, max,
376                                                 "    tx dma%d: "
377                                                 "%08x %08x, %08x %08x; "
378                                                 "%08x %08x %08x .. %08x\n",
379                                                 cppi,
380                                                 musb_readl(ram, 0 * 4),
381                                                 musb_readl(ram, 1 * 4),
382                                                 musb_readl(ram, 2 * 4),
383                                                 musb_readl(ram, 3 * 4),
384                                                 musb_readl(ram, 4 * 4),
385                                                 musb_readl(ram, 5 * 4),
386                                                 musb_readl(ram, 6 * 4),
387                                                 musb_readl(ram, 7 * 4));
388                                         if (code <= 0)
389                                                 break;
390                                         code = min(code, (int) max);
391                                         buf += code;
392                                         max -= code;
393                                 }
394
395                                 if (hw_ep == musb->control_ep
396                                                 && !list_empty(
397                                                         &musb->control)) {
398                                         code = dump_queue(&musb->control,
399                                                         buf, max);
400                                         if (code <= 0)
401                                                 break;
402                                         code = min(code, (int) max);
403                                         buf += code;
404                                         max -= code;
405                                 } else if (hw_ep == musb->bulk_ep
406                                                 && !list_empty(
407                                                         &musb->out_bulk)) {
408                                         code = dump_queue(&musb->out_bulk,
409                                                         buf, max);
410                                         if (code <= 0)
411                                                 break;
412                                         code = min(code, (int) max);
413                                         buf += code;
414                                         max -= code;
415                                 } else if (musb->periodic[epnum]) {
416                                         code = dump_qh(musb->periodic[epnum],
417                                                         buf, max);
418                                         if (code <= 0)
419                                                 break;
420                                         code = min(code, (int) max);
421                                         buf += code;
422                                         max -= code;
423                                 }
424                         }
425                 }
426 #endif
427 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
428                 if (is_peripheral_active(musb)) {
429                         code = 0;
430
431                         if (hw_ep->ep_in.desc || !epnum) {
432                                 code = dump_ep(&hw_ep->ep_in, buf, max);
433                                 if (code <= 0)
434                                         break;
435                                 code = min(code, (int) max);
436                                 buf += code;
437                                 max -= code;
438                         }
439                         if (hw_ep->ep_out.desc) {
440                                 code = dump_ep(&hw_ep->ep_out, buf, max);
441                                 if (code <= 0)
442                                         break;
443                                 code = min(code, (int) max);
444                                 buf += code;
445                                 max -= code;
446                         }
447                 }
448 #endif
449         } while (0);
450
451         return buf - aBuffer;
452 }
453
454 /* Dump the current status and compile options.
455  * @param musb the device driver instance
456  * @param buffer where to dump the status; it must be big enough to hold the
457  * result otherwise "BAD THINGS HAPPENS(TM)".
458  */
459 static int dump_header_stats(struct musb *musb, char *buffer)
460 {
461         int code, count = 0;
462         const void __iomem *mbase = musb->mregs;
463
464         *buffer = 0;
465         count = sprintf(buffer, "Status: %sHDRC, Mode=%s "
466                                 "(Power=%02x, DevCtl=%02x)\n",
467                         (musb->is_multipoint ? "M" : ""), MUSB_MODE(musb),
468                         musb_readb(mbase, MUSB_POWER),
469                         musb_readb(mbase, MUSB_DEVCTL));
470         if (count <= 0)
471                 return 0;
472         buffer += count;
473
474         code = sprintf(buffer, "OTG state: %s; %sactive\n",
475                         otg_state_string(musb),
476                         musb->is_active ? "" : "in");
477         if (code <= 0)
478                 goto done;
479         buffer += code;
480         count += code;
481
482         code = sprintf(buffer,
483                         "Options: "
484 #ifdef CONFIG_MUSB_PIO_ONLY
485                         "pio"
486 #elif defined(CONFIG_USB_TI_CPPI_DMA)
487                         "cppi-dma"
488 #elif defined(CONFIG_USB_INVENTRA_DMA)
489                         "musb-dma"
490 #elif defined(CONFIG_USB_TUSB_OMAP_DMA)
491                         "tusb-omap-dma"
492 #else
493                         "?dma?"
494 #endif
495                         ", "
496 #ifdef CONFIG_USB_MUSB_OTG
497                         "otg (peripheral+host)"
498 #elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
499                         "peripheral"
500 #elif defined(CONFIG_USB_MUSB_HDRC_HCD)
501                         "host"
502 #endif
503                         ", debug=%d [eps=%d]\n",
504                 debug,
505                 musb->nr_endpoints);
506         if (code <= 0)
507                 goto done;
508         count += code;
509         buffer += code;
510
511 #ifdef  CONFIG_USB_GADGET_MUSB_HDRC
512         code = sprintf(buffer, "Peripheral address: %02x\n",
513                         musb_readb(musb->ctrl_base, MUSB_FADDR));
514         if (code <= 0)
515                 goto done;
516         buffer += code;
517         count += code;
518 #endif
519
520 #ifdef  CONFIG_USB_MUSB_HDRC_HCD
521         code = sprintf(buffer, "Root port status: %08x\n",
522                         musb->port1_status);
523         if (code <= 0)
524                 goto done;
525         buffer += code;
526         count += code;
527 #endif
528
529 #ifdef  CONFIG_ARCH_DAVINCI
530         code = sprintf(buffer,
531                         "DaVinci: ctrl=%02x stat=%1x phy=%03x\n"
532                         "\trndis=%05x auto=%04x intsrc=%08x intmsk=%08x"
533                         "\n",
534                         musb_readl(musb->ctrl_base, DAVINCI_USB_CTRL_REG),
535                         musb_readl(musb->ctrl_base, DAVINCI_USB_STAT_REG),
536                         __raw_readl((void __force __iomem *)
537                                         IO_ADDRESS(USBPHY_CTL_PADDR)),
538                         musb_readl(musb->ctrl_base, DAVINCI_RNDIS_REG),
539                         musb_readl(musb->ctrl_base, DAVINCI_AUTOREQ_REG),
540                         musb_readl(musb->ctrl_base,
541                                         DAVINCI_USB_INT_SOURCE_REG),
542                         musb_readl(musb->ctrl_base,
543                                         DAVINCI_USB_INT_MASK_REG));
544         if (code <= 0)
545                 goto done;
546         count += code;
547         buffer += code;
548 #endif  /* DAVINCI */
549
550 #ifdef CONFIG_USB_TUSB6010
551         code = sprintf(buffer,
552                         "TUSB6010: devconf %08x, phy enable %08x drive %08x"
553                         "\n\totg %03x timer %08x"
554                         "\n\tprcm conf %08x mgmt %08x; int src %08x mask %08x"
555                         "\n",
556                         musb_readl(musb->ctrl_base, TUSB_DEV_CONF),
557                         musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL_ENABLE),
558                         musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL),
559                         musb_readl(musb->ctrl_base, TUSB_DEV_OTG_STAT),
560                         musb_readl(musb->ctrl_base, TUSB_DEV_OTG_TIMER),
561                         musb_readl(musb->ctrl_base, TUSB_PRCM_CONF),
562                         musb_readl(musb->ctrl_base, TUSB_PRCM_MNGMT),
563                         musb_readl(musb->ctrl_base, TUSB_INT_SRC),
564                         musb_readl(musb->ctrl_base, TUSB_INT_MASK));
565         if (code <= 0)
566                 goto done;
567         count += code;
568         buffer += code;
569 #endif  /* DAVINCI */
570
571         if (is_cppi_enabled() && musb->dma_controller) {
572                 code = sprintf(buffer,
573                                 "CPPI: txcr=%d txsrc=%01x txena=%01x; "
574                                 "rxcr=%d rxsrc=%01x rxena=%01x "
575                                 "\n",
576                                 musb_readl(musb->ctrl_base,
577                                                 DAVINCI_TXCPPI_CTRL_REG),
578                                 musb_readl(musb->ctrl_base,
579                                                 DAVINCI_TXCPPI_RAW_REG),
580                                 musb_readl(musb->ctrl_base,
581                                                 DAVINCI_TXCPPI_INTENAB_REG),
582                                 musb_readl(musb->ctrl_base,
583                                                 DAVINCI_RXCPPI_CTRL_REG),
584                                 musb_readl(musb->ctrl_base,
585                                                 DAVINCI_RXCPPI_RAW_REG),
586                                 musb_readl(musb->ctrl_base,
587                                                 DAVINCI_RXCPPI_INTENAB_REG));
588                 if (code <= 0)
589                         goto done;
590                 count += code;
591                 buffer += code;
592         }
593
594 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
595         if (is_peripheral_enabled(musb)) {
596                 code = sprintf(buffer, "Gadget driver: %s\n",
597                                 musb->gadget_driver
598                                         ? musb->gadget_driver->driver.name
599                                         : "(none)");
600                 if (code <= 0)
601                         goto done;
602                 count += code;
603                 buffer += code;
604         }
605 #endif
606
607 done:
608         return count;
609 }
610
611 /* Write to ProcFS
612  *
613  * C soft-connect
614  * c soft-disconnect
615  * I enable HS
616  * i disable HS
617  * s stop session
618  * F force session (OTG-unfriendly)
619  * E rElinquish bus (OTG)
620  * H request host mode
621  * h cancel host request
622  * T start sending TEST_PACKET
623  * D<num> set/query the debug level
624  */
625 static int musb_proc_write(struct file *file, const char __user *buffer,
626                         unsigned long count, void *data)
627 {
628         char cmd;
629         u8 reg;
630         struct musb *musb = (struct musb *)data;
631         void __iomem *mbase = musb->mregs;
632
633         /* MOD_INC_USE_COUNT; */
634
635         if (unlikely(copy_from_user(&cmd, buffer, 1)))
636                 return -EFAULT;
637
638         switch (cmd) {
639         case 'C':
640                 if (mbase) {
641                         reg = musb_readb(mbase, MUSB_POWER)
642                                         | MUSB_POWER_SOFTCONN;
643                         musb_writeb(mbase, MUSB_POWER, reg);
644                 }
645                 break;
646
647         case 'c':
648                 if (mbase) {
649                         reg = musb_readb(mbase, MUSB_POWER)
650                                         & ~MUSB_POWER_SOFTCONN;
651                         musb_writeb(mbase, MUSB_POWER, reg);
652                 }
653                 break;
654
655         case 'I':
656                 if (mbase) {
657                         reg = musb_readb(mbase, MUSB_POWER)
658                                         | MUSB_POWER_HSENAB;
659                         musb_writeb(mbase, MUSB_POWER, reg);
660                 }
661                 break;
662
663         case 'i':
664                 if (mbase) {
665                         reg = musb_readb(mbase, MUSB_POWER)
666                                         & ~MUSB_POWER_HSENAB;
667                         musb_writeb(mbase, MUSB_POWER, reg);
668                 }
669                 break;
670
671         case 'F':
672                 reg = musb_readb(mbase, MUSB_DEVCTL);
673                 reg |= MUSB_DEVCTL_SESSION;
674                 musb_writeb(mbase, MUSB_DEVCTL, reg);
675                 break;
676
677         case 'H':
678                 if (mbase) {
679                         reg = musb_readb(mbase, MUSB_DEVCTL);
680                         reg |= MUSB_DEVCTL_HR;
681                         musb_writeb(mbase, MUSB_DEVCTL, reg);
682                         /* MUSB_HST_MODE( ((struct musb*)data) ); */
683                         /* WARNING("Host Mode\n"); */
684                 }
685                 break;
686
687         case 'h':
688                 if (mbase) {
689                         reg = musb_readb(mbase, MUSB_DEVCTL);
690                         reg &= ~MUSB_DEVCTL_HR;
691                         musb_writeb(mbase, MUSB_DEVCTL, reg);
692                 }
693                 break;
694
695         case 'T':
696                 if (mbase) {
697                         musb_load_testpacket(musb);
698                         musb_writeb(mbase, MUSB_TESTMODE,
699                                         MUSB_TEST_PACKET);
700                 }
701                 break;
702
703 #if (MUSB_DEBUG > 0)
704                 /* set/read debug level */
705         case 'D':{
706                         if (count > 1) {
707                                 char digits[8], *p = digits;
708                                 int i = 0, level = 0, sign = 1;
709                                 int len = min(count - 1, (unsigned long)8);
710
711                                 if (copy_from_user(&digits, &buffer[1], len))
712                                         return -EFAULT;
713
714                                 /* optional sign */
715                                 if (*p == '-') {
716                                         len -= 1;
717                                         sign = -sign;
718                                         p++;
719                                 }
720
721                                 /* read it */
722                                 while (i++ < len && *p > '0' && *p < '9') {
723                                         level = level * 10 + (*p - '0');
724                                         p++;
725                                 }
726
727                                 level *= sign;
728                                 DBG(1, "debug level %d\n", level);
729                                 debug = level;
730                         }
731                 }
732                 break;
733
734
735         case '?':
736                 INFO("?: you are seeing it\n");
737                 INFO("C/c: soft connect enable/disable\n");
738                 INFO("I/i: hispeed enable/disable\n");
739                 INFO("F: force session start\n");
740                 INFO("H: host mode\n");
741                 INFO("T: start sending TEST_PACKET\n");
742                 INFO("D: set/read dbug level\n");
743                 break;
744 #endif
745
746         default:
747                 ERR("Command %c not implemented\n", cmd);
748                 break;
749         }
750
751         musb_platform_try_idle(musb, 0);
752
753         return count;
754 }
755
756 static int musb_proc_read(char *page, char **start,
757                         off_t off, int count, int *eof, void *data)
758 {
759         char *buffer = page;
760         int code = 0;
761         unsigned long   flags;
762         struct musb     *musb = data;
763         unsigned        epnum;
764
765         count -= off;
766         count -= 1;             /* for NUL at end */
767         if (count <= 0)
768                 return -EINVAL;
769
770         spin_lock_irqsave(&musb->lock, flags);
771
772         code = dump_header_stats(musb, buffer);
773         if (code > 0) {
774                 buffer += code;
775                 count -= code;
776         }
777
778         /* generate the report for the end points */
779         /* REVISIT ... not unless something's connected! */
780         for (epnum = 0; count >= 0 && epnum < musb->nr_endpoints;
781                         epnum++) {
782                 code = dump_end_info(musb, epnum, buffer, count);
783                 if (code > 0) {
784                         buffer += code;
785                         count -= code;
786                 }
787         }
788
789         musb_platform_try_idle(musb, 0);
790
791         spin_unlock_irqrestore(&musb->lock, flags);
792         *eof = 1;
793
794         return buffer - page;
795 }
796
797 void __devexit musb_debug_delete(char *name, struct musb *musb)
798 {
799         if (musb->proc_entry)
800                 remove_proc_entry(name, NULL);
801 }
802
803 struct proc_dir_entry *__init
804 musb_debug_create(char *name, struct musb *data)
805 {
806         struct proc_dir_entry   *pde;
807
808         /* FIXME convert everything to seq_file; then later, debugfs */
809
810         if (!name)
811                 return NULL;
812
813         pde = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, NULL);
814         data->proc_entry = pde;
815         if (pde) {
816                 pde->data = data;
817                 /* pde->owner = THIS_MODULE; */
818
819                 pde->read_proc = musb_proc_read;
820                 pde->write_proc = musb_proc_write;
821
822                 pde->size = 0;
823
824                 pr_debug("Registered /proc/%s\n", name);
825         } else {
826                 pr_debug("Cannot create a valid proc file entry");
827         }
828
829         return pde;
830 }