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