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