Commit 746cdd0b authored by Felipe Balbi's avatar Felipe Balbi Committed by Greg Kroah-Hartman
Browse files

usb: musb: get rid of procfs entry



Drivers should not add procfs. The functionality in the old
procfs file will be moved to debugfs.

Cc: Anand Gadiyar <gadiyar@ti.com>
Cc: Bryan Wu <bryan.wu@analog.com>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@nokia.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent bf31338b
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -76,11 +76,6 @@ endif

ifneq ($(MUSB_DEBUG),0)
    EXTRA_CFLAGS += -DDEBUG

    ifeq ($(CONFIG_PROC_FS),y)
	musb_hdrc-objs		+= musb_procfs.o
    endif

endif

EXTRA_CFLAGS += -DMUSB_DEBUG=$(MUSB_DEBUG)
+11 −10
Original line number Diff line number Diff line
@@ -2037,6 +2037,8 @@ bad_config:
		musb->xceiv.state = OTG_STATE_A_IDLE;

		status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
		if (status)
			goto fail;

		DBG(1, "%s mode, status %d, devctl %02x %c\n",
			"HOST", status,
@@ -2051,6 +2053,8 @@ bad_config:
		musb->xceiv.state = OTG_STATE_B_IDLE;

		status = musb_gadget_setup(musb);
		if (status)
			goto fail;

		DBG(1, "%s mode, status %d, dev%02x\n",
			is_otg_enabled(musb) ? "OTG" : "PERIPHERAL",
@@ -2059,16 +2063,14 @@ bad_config:

	}

	if (status == 0)
		musb_debug_create("driver/musb_hdrc", musb);
	else {
	return 0;

fail:
	if (musb->clock)
		clk_put(musb->clock);
	device_init_wakeup(dev, 0);
	musb_free(musb);
	return status;
	}

#ifdef CONFIG_SYSFS
	status = device_create_file(dev, &dev_attr_mode);
@@ -2131,7 +2133,6 @@ static int __devexit musb_remove(struct platform_device *pdev)
	 *  - OTG mode: both roles are deactivated (or never-activated)
	 */
	musb_shutdown(pdev);
	musb_debug_delete("driver/musb_hdrc", musb);
#ifdef CONFIG_USB_MUSB_HDRC_HCD
	if (musb->board_mode == MUSB_HOST)
		usb_remove_hcd(musb_to_hcd(musb));
+0 −19
Original line number Diff line number Diff line
@@ -485,23 +485,4 @@ extern int musb_platform_get_vbus_status(struct musb *musb);
extern int __init musb_platform_init(struct musb *musb);
extern int musb_platform_exit(struct musb *musb);

/*-------------------------- ProcFS definitions ---------------------*/

struct proc_dir_entry;

#if (MUSB_DEBUG > 0) && defined(MUSB_CONFIG_PROC_FS)
extern struct proc_dir_entry *musb_debug_create(char *name, struct musb *data);
extern void musb_debug_delete(char *name, struct musb *data);

#else
static inline struct proc_dir_entry *
musb_debug_create(char *name, struct musb *data)
{
	return NULL;
}
static inline void musb_debug_delete(char *name, struct musb *data)
{
}
#endif

#endif	/* __MUSB_CORE_H__ */

drivers/usb/musb/musb_procfs.c

deleted100644 → 0
+0 −830
Original line number Diff line number Diff line
/*
 * MUSB OTG driver debug support
 *
 * Copyright 2005 Mentor Graphics Corporation
 * Copyright (C) 2005-2006 by Texas Instruments
 * Copyright (C) 2006-2007 Nokia Corporation
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>	/* FIXME remove procfs writes */
#include <asm/arch/hardware.h>

#include "musb_core.h"

#include "davinci.h"

#ifdef CONFIG_USB_MUSB_HDRC_HCD

static int dump_qh(struct musb_qh *qh, char *buf, unsigned max)
{
	int				count;
	int				tmp;
	struct usb_host_endpoint	*hep = qh->hep;
	struct urb			*urb;

	count = snprintf(buf, max, "    qh %p dev%d ep%d%s max%d\n",
			qh, qh->dev->devnum, qh->epnum,
			({ char *s; switch (qh->type) {
			case USB_ENDPOINT_XFER_BULK:
				s = "-bulk"; break;
			case USB_ENDPOINT_XFER_INT:
				s = "-int"; break;
			case USB_ENDPOINT_XFER_CONTROL:
				s = ""; break;
			default:
				s = "iso"; break;
			}; s; }),
			qh->maxpacket);
	if (count <= 0)
		return 0;
	buf += count;
	max -= count;

	list_for_each_entry(urb, &hep->urb_list, urb_list) {
		tmp = snprintf(buf, max, "\t%s urb %p %d/%d\n",
				usb_pipein(urb->pipe) ? "in" : "out",
				urb, urb->actual_length,
				urb->transfer_buffer_length);
		if (tmp <= 0)
			break;
		tmp = min(tmp, (int)max);
		count += tmp;
		buf += tmp;
		max -= tmp;
	}
	return count;
}

static int
dump_queue(struct list_head *q, char *buf, unsigned max)
{
	int		count = 0;
	struct musb_qh	*qh;

	list_for_each_entry(qh, q, ring) {
		int	tmp;

		tmp = dump_qh(qh, buf, max);
		if (tmp <= 0)
			break;
		tmp = min(tmp, (int)max);
		count += tmp;
		buf += tmp;
		max -= tmp;
	}
	return count;
}

#endif	/* HCD */

#ifdef CONFIG_USB_GADGET_MUSB_HDRC
static int dump_ep(struct musb_ep *ep, char *buffer, unsigned max)
{
	char		*buf = buffer;
	int		code = 0;
	void __iomem	*regs = ep->hw_ep->regs;
	char		*mode = "1buf";

	if (ep->is_in) {
		if (ep->hw_ep->tx_double_buffered)
			mode = "2buf";
	} else {
		if (ep->hw_ep->rx_double_buffered)
			mode = "2buf";
	}

	do {
		struct usb_request	*req;

		code = snprintf(buf, max,
				"\n%s (hw%d): %s%s, csr %04x maxp %04x\n",
				ep->name, ep->current_epnum,
				mode, ep->dma ? " dma" : "",
				musb_readw(regs,
					(ep->is_in || !ep->current_epnum)
						? MUSB_TXCSR
						: MUSB_RXCSR),
				musb_readw(regs, ep->is_in
						? MUSB_TXMAXP
						: MUSB_RXMAXP)
				);
		if (code <= 0)
			break;
		code = min(code, (int) max);
		buf += code;
		max -= code;

		if (is_cppi_enabled() && ep->current_epnum) {
			unsigned	cppi = ep->current_epnum - 1;
			void __iomem	*base = ep->musb->ctrl_base;
			unsigned	off1 = cppi << 2;
			void __iomem	*ram = base;
			char		tmp[16];

			if (ep->is_in) {
				ram += DAVINCI_TXCPPI_STATERAM_OFFSET(cppi);
				tmp[0] = 0;
			} else {
				ram += DAVINCI_RXCPPI_STATERAM_OFFSET(cppi);
				snprintf(tmp, sizeof tmp, "%d left, ",
					musb_readl(base,
					DAVINCI_RXCPPI_BUFCNT0_REG + off1));
			}

			code = snprintf(buf, max, "%cX DMA%d: %s"
					"%08x %08x, %08x %08x; "
					"%08x %08x %08x .. %08x\n",
				ep->is_in ? 'T' : 'R',
				ep->current_epnum - 1, tmp,
				musb_readl(ram, 0 * 4),
				musb_readl(ram, 1 * 4),
				musb_readl(ram, 2 * 4),
				musb_readl(ram, 3 * 4),
				musb_readl(ram, 4 * 4),
				musb_readl(ram, 5 * 4),
				musb_readl(ram, 6 * 4),
				musb_readl(ram, 7 * 4));
			if (code <= 0)
				break;
			code = min(code, (int) max);
			buf += code;
			max -= code;
		}

		if (list_empty(&ep->req_list)) {
			code = snprintf(buf, max, "\t(queue empty)\n");
			if (code <= 0)
				break;
			code = min(code, (int) max);
			buf += code;
			max -= code;
			break;
		}
		list_for_each_entry(req, &ep->req_list, list) {
			code = snprintf(buf, max, "\treq %p, %s%s%d/%d\n",
					req,
					req->zero ? "zero, " : "",
					req->short_not_ok ? "!short, " : "",
					req->actual, req->length);
			if (code <= 0)
				break;
			code = min(code, (int) max);
			buf += code;
			max -= code;
		}
	} while (0);
	return buf - buffer;
}
#endif

static int
dump_end_info(struct musb *musb, u8 epnum, char *aBuffer, unsigned max)
{
	int			code = 0;
	char			*buf = aBuffer;
	struct musb_hw_ep	*hw_ep = &musb->endpoints[epnum];

	do {
		musb_ep_select(musb->mregs, epnum);
#ifdef CONFIG_USB_MUSB_HDRC_HCD
		if (is_host_active(musb)) {
			int		dump_rx, dump_tx;
			void __iomem	*regs = hw_ep->regs;

			/* TEMPORARY (!) until we have a real periodic
			 * schedule tree ...
			 */
			if (!epnum) {
				/* control is shared, uses RX queue
				 * but (mostly) shadowed tx registers
				 */
				dump_tx = !list_empty(&musb->control);
				dump_rx = 0;
			} else if (hw_ep == musb->bulk_ep) {
				dump_tx = !list_empty(&musb->out_bulk);
				dump_rx = !list_empty(&musb->in_bulk);
			} else if (musb->periodic[epnum]) {
				struct usb_host_endpoint	*hep;

				hep = musb->periodic[epnum]->hep;
				dump_rx = hep->desc.bEndpointAddress
						& USB_ENDPOINT_DIR_MASK;
				dump_tx = !dump_rx;
			} else
				break;
			/* END TEMPORARY */


			if (dump_rx) {
				code = snprintf(buf, max,
					"\nRX%d: %s rxcsr %04x interval %02x "
					"max %04x type %02x; "
					"dev %d hub %d port %d"
					"\n",
					epnum,
					hw_ep->rx_double_buffered
						? "2buf" : "1buf",
					musb_readw(regs, MUSB_RXCSR),
					musb_readb(regs, MUSB_RXINTERVAL),
					musb_readw(regs, MUSB_RXMAXP),
					musb_readb(regs, MUSB_RXTYPE),
					/* FIXME:  assumes multipoint */
					musb_readb(musb->mregs,
						MUSB_BUSCTL_OFFSET(epnum,
						MUSB_RXFUNCADDR)),
					musb_readb(musb->mregs,
						MUSB_BUSCTL_OFFSET(epnum,
						MUSB_RXHUBADDR)),
					musb_readb(musb->mregs,
						MUSB_BUSCTL_OFFSET(epnum,
						MUSB_RXHUBPORT))
					);
				if (code <= 0)
					break;
				code = min(code, (int) max);
				buf += code;
				max -= code;

				if (is_cppi_enabled()
						&& epnum
						&& hw_ep->rx_channel) {
					unsigned	cppi = epnum - 1;
					unsigned	off1 = cppi << 2;
					void __iomem	*base;
					void __iomem	*ram;
					char		tmp[16];

					base = musb->ctrl_base;
					ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
							cppi) + base;
					snprintf(tmp, sizeof tmp, "%d left, ",
						musb_readl(base,
						DAVINCI_RXCPPI_BUFCNT0_REG
								+ off1));

					code = snprintf(buf, max,
						"    rx dma%d: %s"
						"%08x %08x, %08x %08x; "
						"%08x %08x %08x .. %08x\n",
						cppi, tmp,
						musb_readl(ram, 0 * 4),
						musb_readl(ram, 1 * 4),
						musb_readl(ram, 2 * 4),
						musb_readl(ram, 3 * 4),
						musb_readl(ram, 4 * 4),
						musb_readl(ram, 5 * 4),
						musb_readl(ram, 6 * 4),
						musb_readl(ram, 7 * 4));
					if (code <= 0)
						break;
					code = min(code, (int) max);
					buf += code;
					max -= code;
				}

				if (hw_ep == musb->bulk_ep
						&& !list_empty(
							&musb->in_bulk)) {
					code = dump_queue(&musb->in_bulk,
							buf, max);
					if (code <= 0)
						break;
					code = min(code, (int) max);
					buf += code;
					max -= code;
				} else if (musb->periodic[epnum]) {
					code = dump_qh(musb->periodic[epnum],
							buf, max);
					if (code <= 0)
						break;
					code = min(code, (int) max);
					buf += code;
					max -= code;
				}
			}

			if (dump_tx) {
				code = snprintf(buf, max,
					"\nTX%d: %s txcsr %04x interval %02x "
					"max %04x type %02x; "
					"dev %d hub %d port %d"
					"\n",
					epnum,
					hw_ep->tx_double_buffered
						? "2buf" : "1buf",
					musb_readw(regs, MUSB_TXCSR),
					musb_readb(regs, MUSB_TXINTERVAL),
					musb_readw(regs, MUSB_TXMAXP),
					musb_readb(regs, MUSB_TXTYPE),
					/* FIXME:  assumes multipoint */
					musb_readb(musb->mregs,
						MUSB_BUSCTL_OFFSET(epnum,
						MUSB_TXFUNCADDR)),
					musb_readb(musb->mregs,
						MUSB_BUSCTL_OFFSET(epnum,
						MUSB_TXHUBADDR)),
					musb_readb(musb->mregs,
						MUSB_BUSCTL_OFFSET(epnum,
						MUSB_TXHUBPORT))
					);
				if (code <= 0)
					break;
				code = min(code, (int) max);
				buf += code;
				max -= code;

				if (is_cppi_enabled()
						&& epnum
						&& hw_ep->tx_channel) {
					unsigned	cppi = epnum - 1;
					void __iomem	*base;
					void __iomem	*ram;

					base = musb->ctrl_base;
					ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
							cppi) + base;
					code = snprintf(buf, max,
						"    tx dma%d: "
						"%08x %08x, %08x %08x; "
						"%08x %08x %08x .. %08x\n",
						cppi,
						musb_readl(ram, 0 * 4),
						musb_readl(ram, 1 * 4),
						musb_readl(ram, 2 * 4),
						musb_readl(ram, 3 * 4),
						musb_readl(ram, 4 * 4),
						musb_readl(ram, 5 * 4),
						musb_readl(ram, 6 * 4),
						musb_readl(ram, 7 * 4));
					if (code <= 0)
						break;
					code = min(code, (int) max);
					buf += code;
					max -= code;
				}

				if (hw_ep == musb->control_ep
						&& !list_empty(
							&musb->control)) {
					code = dump_queue(&musb->control,
							buf, max);
					if (code <= 0)
						break;
					code = min(code, (int) max);
					buf += code;
					max -= code;
				} else if (hw_ep == musb->bulk_ep
						&& !list_empty(
							&musb->out_bulk)) {
					code = dump_queue(&musb->out_bulk,
							buf, max);
					if (code <= 0)
						break;
					code = min(code, (int) max);
					buf += code;
					max -= code;
				} else if (musb->periodic[epnum]) {
					code = dump_qh(musb->periodic[epnum],
							buf, max);
					if (code <= 0)
						break;
					code = min(code, (int) max);
					buf += code;
					max -= code;
				}
			}
		}
#endif
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
		if (is_peripheral_active(musb)) {
			code = 0;

			if (hw_ep->ep_in.desc || !epnum) {
				code = dump_ep(&hw_ep->ep_in, buf, max);
				if (code <= 0)
					break;
				code = min(code, (int) max);
				buf += code;
				max -= code;
			}
			if (hw_ep->ep_out.desc) {
				code = dump_ep(&hw_ep->ep_out, buf, max);
				if (code <= 0)
					break;
				code = min(code, (int) max);
				buf += code;
				max -= code;
			}
		}
#endif
	} while (0);

	return buf - aBuffer;
}

/* Dump the current status and compile options.
 * @param musb the device driver instance
 * @param buffer where to dump the status; it must be big enough to hold the
 * result otherwise "BAD THINGS HAPPENS(TM)".
 */
static int dump_header_stats(struct musb *musb, char *buffer)
{
	int code, count = 0;
	const void __iomem *mbase = musb->mregs;

	*buffer = 0;
	count = sprintf(buffer, "Status: %sHDRC, Mode=%s "
				"(Power=%02x, DevCtl=%02x)\n",
			(musb->is_multipoint ? "M" : ""), MUSB_MODE(musb),
			musb_readb(mbase, MUSB_POWER),
			musb_readb(mbase, MUSB_DEVCTL));
	if (count <= 0)
		return 0;
	buffer += count;

	code = sprintf(buffer, "OTG state: %s; %sactive\n",
			otg_state_string(musb),
			musb->is_active ? "" : "in");
	if (code <= 0)
		goto done;
	buffer += code;
	count += code;

	code = sprintf(buffer,
			"Options: "
#ifdef CONFIG_MUSB_PIO_ONLY
			"pio"
#elif defined(CONFIG_USB_TI_CPPI_DMA)
			"cppi-dma"
#elif defined(CONFIG_USB_INVENTRA_DMA)
			"musb-dma"
#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
			"tusb-omap-dma"
#else
			"?dma?"
#endif
			", "
#ifdef CONFIG_USB_MUSB_OTG
			"otg (peripheral+host)"
#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
			"peripheral"
#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
			"host"
#endif
			", debug=%d [eps=%d]\n",
		debug,
		musb->nr_endpoints);
	if (code <= 0)
		goto done;
	count += code;
	buffer += code;

#ifdef	CONFIG_USB_GADGET_MUSB_HDRC
	code = sprintf(buffer, "Peripheral address: %02x\n",
			musb_readb(musb->ctrl_base, MUSB_FADDR));
	if (code <= 0)
		goto done;
	buffer += code;
	count += code;
#endif

#ifdef	CONFIG_USB_MUSB_HDRC_HCD
	code = sprintf(buffer, "Root port status: %08x\n",
			musb->port1_status);
	if (code <= 0)
		goto done;
	buffer += code;
	count += code;
#endif

#ifdef	CONFIG_ARCH_DAVINCI
	code = sprintf(buffer,
			"DaVinci: ctrl=%02x stat=%1x phy=%03x\n"
			"\trndis=%05x auto=%04x intsrc=%08x intmsk=%08x"
			"\n",
			musb_readl(musb->ctrl_base, DAVINCI_USB_CTRL_REG),
			musb_readl(musb->ctrl_base, DAVINCI_USB_STAT_REG),
			__raw_readl((void __force __iomem *)
					IO_ADDRESS(USBPHY_CTL_PADDR)),
			musb_readl(musb->ctrl_base, DAVINCI_RNDIS_REG),
			musb_readl(musb->ctrl_base, DAVINCI_AUTOREQ_REG),
			musb_readl(musb->ctrl_base,
					DAVINCI_USB_INT_SOURCE_REG),
			musb_readl(musb->ctrl_base,
					DAVINCI_USB_INT_MASK_REG));
	if (code <= 0)
		goto done;
	count += code;
	buffer += code;
#endif	/* DAVINCI */

#ifdef CONFIG_USB_TUSB6010
	code = sprintf(buffer,
			"TUSB6010: devconf %08x, phy enable %08x drive %08x"
			"\n\totg %03x timer %08x"
			"\n\tprcm conf %08x mgmt %08x; int src %08x mask %08x"
			"\n",
			musb_readl(musb->ctrl_base, TUSB_DEV_CONF),
			musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL_ENABLE),
			musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL),
			musb_readl(musb->ctrl_base, TUSB_DEV_OTG_STAT),
			musb_readl(musb->ctrl_base, TUSB_DEV_OTG_TIMER),
			musb_readl(musb->ctrl_base, TUSB_PRCM_CONF),
			musb_readl(musb->ctrl_base, TUSB_PRCM_MNGMT),
			musb_readl(musb->ctrl_base, TUSB_INT_SRC),
			musb_readl(musb->ctrl_base, TUSB_INT_MASK));
	if (code <= 0)
		goto done;
	count += code;
	buffer += code;
#endif	/* DAVINCI */

	if (is_cppi_enabled() && musb->dma_controller) {
		code = sprintf(buffer,
				"CPPI: txcr=%d txsrc=%01x txena=%01x; "
				"rxcr=%d rxsrc=%01x rxena=%01x "
				"\n",
				musb_readl(musb->ctrl_base,
						DAVINCI_TXCPPI_CTRL_REG),
				musb_readl(musb->ctrl_base,
						DAVINCI_TXCPPI_RAW_REG),
				musb_readl(musb->ctrl_base,
						DAVINCI_TXCPPI_INTENAB_REG),
				musb_readl(musb->ctrl_base,
						DAVINCI_RXCPPI_CTRL_REG),
				musb_readl(musb->ctrl_base,
						DAVINCI_RXCPPI_RAW_REG),
				musb_readl(musb->ctrl_base,
						DAVINCI_RXCPPI_INTENAB_REG));
		if (code <= 0)
			goto done;
		count += code;
		buffer += code;
	}

#ifdef CONFIG_USB_GADGET_MUSB_HDRC
	if (is_peripheral_enabled(musb)) {
		code = sprintf(buffer, "Gadget driver: %s\n",
				musb->gadget_driver
					? musb->gadget_driver->driver.name
					: "(none)");
		if (code <= 0)
			goto done;
		count += code;
		buffer += code;
	}
#endif

done:
	return count;
}

/* Write to ProcFS
 *
 * C soft-connect
 * c soft-disconnect
 * I enable HS
 * i disable HS
 * s stop session
 * F force session (OTG-unfriendly)
 * E rElinquish bus (OTG)
 * H request host mode
 * h cancel host request
 * T start sending TEST_PACKET
 * D<num> set/query the debug level
 */
static int musb_proc_write(struct file *file, const char __user *buffer,
			unsigned long count, void *data)
{
	char cmd;
	u8 reg;
	struct musb *musb = (struct musb *)data;
	void __iomem *mbase = musb->mregs;

	/* MOD_INC_USE_COUNT; */

	if (unlikely(copy_from_user(&cmd, buffer, 1)))
		return -EFAULT;

	switch (cmd) {
	case 'C':
		if (mbase) {
			reg = musb_readb(mbase, MUSB_POWER)
					| MUSB_POWER_SOFTCONN;
			musb_writeb(mbase, MUSB_POWER, reg);
		}
		break;

	case 'c':
		if (mbase) {
			reg = musb_readb(mbase, MUSB_POWER)
					& ~MUSB_POWER_SOFTCONN;
			musb_writeb(mbase, MUSB_POWER, reg);
		}
		break;

	case 'I':
		if (mbase) {
			reg = musb_readb(mbase, MUSB_POWER)
					| MUSB_POWER_HSENAB;
			musb_writeb(mbase, MUSB_POWER, reg);
		}
		break;

	case 'i':
		if (mbase) {
			reg = musb_readb(mbase, MUSB_POWER)
					& ~MUSB_POWER_HSENAB;
			musb_writeb(mbase, MUSB_POWER, reg);
		}
		break;

	case 'F':
		reg = musb_readb(mbase, MUSB_DEVCTL);
		reg |= MUSB_DEVCTL_SESSION;
		musb_writeb(mbase, MUSB_DEVCTL, reg);
		break;

	case 'H':
		if (mbase) {
			reg = musb_readb(mbase, MUSB_DEVCTL);
			reg |= MUSB_DEVCTL_HR;
			musb_writeb(mbase, MUSB_DEVCTL, reg);
			/* MUSB_HST_MODE( ((struct musb*)data) ); */
			/* WARNING("Host Mode\n"); */
		}
		break;

	case 'h':
		if (mbase) {
			reg = musb_readb(mbase, MUSB_DEVCTL);
			reg &= ~MUSB_DEVCTL_HR;
			musb_writeb(mbase, MUSB_DEVCTL, reg);
		}
		break;

	case 'T':
		if (mbase) {
			musb_load_testpacket(musb);
			musb_writeb(mbase, MUSB_TESTMODE,
					MUSB_TEST_PACKET);
		}
		break;

#if (MUSB_DEBUG > 0)
		/* set/read debug level */
	case 'D':{
			if (count > 1) {
				char digits[8], *p = digits;
				int i = 0, level = 0, sign = 1;
				int len = min(count - 1, (unsigned long)8);

				if (copy_from_user(&digits, &buffer[1], len))
					return -EFAULT;

				/* optional sign */
				if (*p == '-') {
					len -= 1;
					sign = -sign;
					p++;
				}

				/* read it */
				while (i++ < len && *p > '0' && *p < '9') {
					level = level * 10 + (*p - '0');
					p++;
				}

				level *= sign;
				DBG(1, "debug level %d\n", level);
				debug = level;
			}
		}
		break;


	case '?':
		INFO("?: you are seeing it\n");
		INFO("C/c: soft connect enable/disable\n");
		INFO("I/i: hispeed enable/disable\n");
		INFO("F: force session start\n");
		INFO("H: host mode\n");
		INFO("T: start sending TEST_PACKET\n");
		INFO("D: set/read dbug level\n");
		break;
#endif

	default:
		ERR("Command %c not implemented\n", cmd);
		break;
	}

	musb_platform_try_idle(musb, 0);

	return count;
}

static int musb_proc_read(char *page, char **start,
			off_t off, int count, int *eof, void *data)
{
	char *buffer = page;
	int code = 0;
	unsigned long	flags;
	struct musb	*musb = data;
	unsigned	epnum;

	count -= off;
	count -= 1;		/* for NUL at end */
	if (count <= 0)
		return -EINVAL;

	spin_lock_irqsave(&musb->lock, flags);

	code = dump_header_stats(musb, buffer);
	if (code > 0) {
		buffer += code;
		count -= code;
	}

	/* generate the report for the end points */
	/* REVISIT ... not unless something's connected! */
	for (epnum = 0; count >= 0 && epnum < musb->nr_endpoints;
			epnum++) {
		code = dump_end_info(musb, epnum, buffer, count);
		if (code > 0) {
			buffer += code;
			count -= code;
		}
	}

	musb_platform_try_idle(musb, 0);

	spin_unlock_irqrestore(&musb->lock, flags);
	*eof = 1;

	return buffer - page;
}

void __devexit musb_debug_delete(char *name, struct musb *musb)
{
	if (musb->proc_entry)
		remove_proc_entry(name, NULL);
}

struct proc_dir_entry *__init
musb_debug_create(char *name, struct musb *data)
{
	struct proc_dir_entry	*pde;

	/* FIXME convert everything to seq_file; then later, debugfs */

	if (!name)
		return NULL;

	pde = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, NULL);
	data->proc_entry = pde;
	if (pde) {
		pde->data = data;
		/* pde->owner = THIS_MODULE; */

		pde->read_proc = musb_proc_read;
		pde->write_proc = musb_proc_write;

		pde->size = 0;

		pr_debug("Registered /proc/%s\n", name);
	} else {
		pr_debug("Cannot create a valid proc file entry");
	}

	return pde;
}