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