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