diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 6e784d2..117d0c7 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -118,10 +118,10 @@ config USB_AMD5536UDC
 config USB_GADGET_ATMEL_USBA
 	boolean "Atmel USBA"
 	select USB_GADGET_DUALSPEED
-	depends on AVR32 || ARCH_AT91CAP9
+	depends on AVR32 || ARCH_AT91CAP9 || ARCH_AT91SAM9RL
 	help
 	  USBA is the integrated high-speed USB Device controller on
-	  the AT32AP700x and AT91CAP9 processors from Atmel.
+	  the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
 
 config USB_ATMEL_USBA
 	tristate
@@ -172,7 +172,7 @@ config USB_NET2280
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
-config USB_GADGET_PXA2XX
+config USB_GADGET_PXA25X
 	boolean "PXA 25x or IXP 4xx"
 	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
 	help
@@ -184,19 +184,19 @@ config USB_GADGET_PXA2XX
 	   zero (for control transfers).
 
 	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "pxa2xx_udc" and force all
+	   dynamically linked module called "pxa25x_udc" and force all
 	   gadget drivers to also be dynamically linked.
 
-config USB_PXA2XX
+config USB_PXA25X
 	tristate
-	depends on USB_GADGET_PXA2XX
+	depends on USB_GADGET_PXA25X
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
 # if there's only one gadget driver, using only two bulk endpoints,
 # don't waste memory for the other endpoints
-config USB_PXA2XX_SMALL
-	depends on USB_GADGET_PXA2XX
+config USB_PXA25X_SMALL
+	depends on USB_GADGET_PXA25X
 	bool
 	default n if USB_ETH_RNDIS
 	default y if USB_ZERO
@@ -284,6 +284,16 @@ config USB_LH7A40X
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
+# built in ../musb along with host support
+config USB_GADGET_MUSB_HDRC
+	boolean "Inventra HDRC USB Peripheral (TI, ...)"
+	depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG)
+	select USB_GADGET_DUALSPEED
+	select USB_GADGET_SELECTED
+	help
+	  This OTG-capable silicon IP is used in dual designs including
+	  the TI DaVinci, OMAP 243x, OMAP 343x, and TUSB 6010.
+
 config USB_GADGET_OMAP
 	boolean "OMAP USB Device Controller"
 	depends on ARCH_OMAP
@@ -355,6 +365,20 @@ config USB_AT91
 	depends on USB_GADGET_AT91
 	default USB_GADGET
 
+config USB_GADGET_SA1100
+	boolean "SA1100 USB Device Port"
+	depends on ARCH_SA1100
+	help
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "sa1100_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_SA1100
+	tristate
+	depends on USB_GADGET_SA1100
+	default USB_GADGET
+	select USB_GADGET_SELECTED
+
 config USB_GADGET_DUMMY_HCD
 	boolean "Dummy HCD (DEVELOPMENT)"
 	depends on USB=y || (USB=m && USB_GADGET=m)
@@ -504,6 +528,20 @@ config USB_ETH_RNDIS
 	   XP, you'll need to download drivers from Microsoft's website; a URL
 	   is given in comments found in that info file.
 
+config USB_ETH_NO_MDLM
+	bool "Disable MDLM support for CDC_SUBSET"
+	depends on USB_ETH
+	default n
+	help
+	   A variation on CDC_SUBSET support is used in newer kernel 
+	   implementations for use with a proprietary Microsoft Windows driver
+	   used for example with the Zaurus linux distribution.
+	   However, the MDLM extensions break the older host side drivers making
+	   g_ether incompatible with older kernels.
+
+	   If you say "y" here, the Ethernet gadget driver will use the older
+	   pre-MDLM extensions.
+	   
 config USB_GADGETFS
 	tristate "Gadget Filesystem (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -586,6 +624,20 @@ config USB_G_PRINTER
 	  For more information, see Documentation/usb/gadget_printer.txt
 	  which includes sample code for accessing the device file.
 
+config USB_CDC_COMPOSITE
+	tristate "CDC Composite Device (Ethernet and ACM)"
+	depends on NET
+	help
+	  This driver provides two functions in one configuration:
+	  a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
+
+	  This driver requires four bulk and two interrupt endpoints,
+	  plus the ability to handle altsettings.  Not all peripheral
+	  controllers are that capable.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module.
+
 # put drivers that need isochronous transfer support (for audio
 # or video class gadget drivers), or specific hardware, here.
 
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 1235725..79a69ae 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -8,7 +8,7 @@ endif
 obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
 obj-$(CONFIG_USB_AMD5536UDC)	+= amd5536udc.o
-obj-$(CONFIG_USB_PXA2XX)	+= pxa2xx_udc.o
+obj-$(CONFIG_USB_PXA25X)	+= pxa25x_udc.o
 obj-$(CONFIG_USB_PXA27X)	+= pxa27x_udc.o
 obj-$(CONFIG_USB_GOKU)		+= goku_udc.o
 obj-$(CONFIG_USB_OMAP)		+= omap_udc.o
@@ -18,22 +18,27 @@ obj-$(CONFIG_USB_AT91)		+= at91_udc.o
 obj-$(CONFIG_USB_ATMEL_USBA)	+= atmel_usba_udc.o
 obj-$(CONFIG_USB_FSL_USB2)	+= fsl_usb2_udc.o
 obj-$(CONFIG_USB_M66592)	+= m66592-udc.o
+obj-$(CONFIG_USB_SA1100)	+= sa1100_udc.o
 
 #
 # USB gadget drivers
 #
-g_zero-objs			:= zero.o usbstring.o config.o epautoconf.o
-g_ether-objs			:= ether.o usbstring.o config.o epautoconf.o
-g_serial-objs			:= serial.o usbstring.o config.o epautoconf.o
+C_UTILS =	composite.o usbstring.o config.o epautoconf.o
+
+g_zero-objs			:= zero.o f_sourcesink.o f_loopback.o $(C_UTILS)
+g_ether-objs			:= ether.o u_ether.o f_subset.o f_ecm.o $(C_UTILS)
+g_serial-objs			:= serial.o u_serial.o f_acm.o f_serial.o $(C_UTILS)
 g_midi-objs			:= gmidi.o usbstring.o config.o epautoconf.o
 gadgetfs-objs			:= inode.o
 g_file_storage-objs		:= file_storage.o usbstring.o config.o \
 					epautoconf.o
 g_printer-objs			:= printer.o usbstring.o config.o \
 					epautoconf.o
+g_cdc-objs			:= cdc2.o u_ether.o f_ecm.o \
+					u_serial.o f_acm.o $(C_UTILS)
 
 ifeq ($(CONFIG_USB_ETH_RNDIS),y)
-	g_ether-objs		+= rndis.o
+	g_ether-objs		+= f_rndis.o rndis.o
 endif
  
 obj-$(CONFIG_USB_ZERO)		+= g_zero.o
@@ -43,4 +48,5 @@ obj-$(CONFIG_USB_FILE_STORAGE)	+= g_file_storage.o
 obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o
 obj-$(CONFIG_USB_G_PRINTER)	+= g_printer.o
 obj-$(CONFIG_USB_MIDI_GADGET)	+= g_midi.o
+obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
 
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index f261d2a..abf8192 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -44,7 +44,6 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
@@ -3342,7 +3341,7 @@ static int udc_probe(struct udc *dev)
 	spin_lock_init(&dev->lock);
 	dev->gadget.ops = &udc_ops;
 
-	strcpy(dev->gadget.dev.bus_id, "gadget");
+	dev_set_name(&dev->gadget.dev, "gadget");
 	dev->gadget.dev.release = gadget_release;
 	dev->gadget.name = name;
 	dev->gadget.name = name;
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 274c60a..a8a1de4 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -40,16 +40,15 @@
 #include <linux/usb/gadget.h>
 
 #include <asm/byteorder.h>
-#include <asm/hardware.h>
+#include <mach/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-#include <asm/mach-types.h>
 #include <asm/gpio.h>
 
-#include <asm/arch/board.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/at91sam9261_matrix.h>
+#include <mach/board.h>
+#include <mach/cpu.h>
+#include <mach/at91sam9261_matrix.h>
 
 #include "at91_udc.h"
 
@@ -888,7 +887,7 @@ static void pullup(struct at91_udc *udc, int is_on)
 		at91_udp_write(udc, AT91_UDP_TXVC, 0);
 		if (cpu_is_at91rm9200())
 			gpio_set_value(udc->board.pullup_pin, active);
-		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
+		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
 			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
 			txvc |= AT91_UDP_TXVC_PUON;
@@ -906,7 +905,7 @@ static void pullup(struct at91_udc *udc, int is_on)
 		at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
 		if (cpu_is_at91rm9200())
 			gpio_set_value(udc->board.pullup_pin, !active);
-		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
+		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
 			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
 			txvc &= ~AT91_UDP_TXVC_PUON;
@@ -1687,6 +1686,19 @@ static int __init at91udc_probe(struct platform_device *pdev)
 				udc->board.pullup_active_low);
 	}
 
+	/* newer chips have more FIFO memory than rm9200 */
+	if (cpu_is_at91sam9260()) {
+		udc->ep[0].maxpacket = 64;
+		udc->ep[3].maxpacket = 64;
+		udc->ep[4].maxpacket = 512;
+		udc->ep[5].maxpacket = 512;
+	} else if (cpu_is_at91sam9261()) {
+		udc->ep[3].maxpacket = 64;
+	} else if (cpu_is_at91sam9263()) {
+		udc->ep[0].maxpacket = 64;
+		udc->ep[3].maxpacket = 64;
+	}
+
 	udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1);
 	if (!udc->udp_baseaddr) {
 		retval = -ENOMEM;
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index a973f2a..c65d622 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/at91_udc.h
@@ -171,7 +171,7 @@ struct at91_request {
 #endif
 
 #define ERR(stuff...)		pr_err("udc: " stuff)
-#define WARN(stuff...)		pr_warning("udc: " stuff)
+#define WARNING(stuff...)	pr_warning("udc: " stuff)
 #define INFO(stuff...)		pr_info("udc: " stuff)
 #define DBG(stuff...)		pr_debug("udc: " stuff)
 
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 07e5a0b..ae30ab1 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -22,7 +22,7 @@
 #include <linux/delay.h>
 
 #include <asm/gpio.h>
-#include <asm/arch/board.h>
+#include <mach/board.h>
 
 #include "atmel_usba_udc.h"
 
@@ -334,7 +334,7 @@ static void toggle_bias(int is_on)
 
 #elif defined(CONFIG_ARCH_AT91)
 
-#include <asm/arch/at91_pmc.h>
+#include <mach/at91_pmc.h>
 
 static void toggle_bias(int is_on)
 {
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
new file mode 100644
index 0000000..a39a4b9
--- /dev/null
+++ b/drivers/usb/gadget/cdc2.c
@@ -0,0 +1,246 @@
+/*
+ * cdc2.c -- CDC Composite driver, with ECM and ACM support
+ *
+ * Copyright (C) 2008 David Brownell
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+
+#include "u_ether.h"
+#include "u_serial.h"
+
+
+#define DRIVER_DESC		"CDC Composite Gadget"
+#define DRIVER_VERSION		"King Kamehameha Day 2008"
+
+/*-------------------------------------------------------------------------*/
+
+/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
+ * Instead:  allocate your own, using normal USB-IF procedures.
+ */
+
+/* Thanks to NetChip Technologies for donating this product ID.
+ * It's for devices with only this composite CDC configuration.
+ */
+#define CDC_VENDOR_NUM		0x0525	/* NetChip */
+#define CDC_PRODUCT_NUM		0xa4aa	/* CDC Composite: ECM + ACM */
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_device_descriptor device_desc = {
+	.bLength =		sizeof device_desc,
+	.bDescriptorType =	USB_DT_DEVICE,
+
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+
+	.bDeviceClass =		USB_CLASS_COMM,
+	.bDeviceSubClass =	0,
+	.bDeviceProtocol =	0,
+	/* .bMaxPacketSize0 = f(hardware) */
+
+	/* Vendor and product id can be overridden by module parameters.  */
+	.idVendor =		__constant_cpu_to_le16(CDC_VENDOR_NUM),
+	.idProduct =		__constant_cpu_to_le16(CDC_PRODUCT_NUM),
+	/* .bcdDevice = f(hardware) */
+	/* .iManufacturer = DYNAMIC */
+	/* .iProduct = DYNAMIC */
+	/* NO SERIAL NUMBER */
+	.bNumConfigurations =	1,
+};
+
+static struct usb_otg_descriptor otg_descriptor = {
+	.bLength =		sizeof otg_descriptor,
+	.bDescriptorType =	USB_DT_OTG,
+
+	/* REVISIT SRP-only hardware is possible, although
+	 * it would not be called "OTG" ...
+	 */
+	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
+};
+
+static const struct usb_descriptor_header *otg_desc[] = {
+	(struct usb_descriptor_header *) &otg_descriptor,
+	NULL,
+};
+
+
+/* string IDs are assigned dynamically */
+
+#define STRING_MANUFACTURER_IDX		0
+#define STRING_PRODUCT_IDX		1
+
+static char manufacturer[50];
+
+static struct usb_string strings_dev[] = {
+	[STRING_MANUFACTURER_IDX].s = manufacturer,
+	[STRING_PRODUCT_IDX].s = DRIVER_DESC,
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings stringtab_dev = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_dev,
+};
+
+static struct usb_gadget_strings *dev_strings[] = {
+	&stringtab_dev,
+	NULL,
+};
+
+static u8 hostaddr[ETH_ALEN];
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * We _always_ have both CDC ECM and CDC ACM functions.
+ */
+static int __init cdc_do_config(struct usb_configuration *c)
+{
+	int	status;
+
+	if (gadget_is_otg(c->cdev->gadget)) {
+		c->descriptors = otg_desc;
+		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
+	status = ecm_bind_config(c, hostaddr);
+	if (status < 0)
+		return status;
+
+	status = acm_bind_config(c, 0);
+	if (status < 0)
+		return status;
+
+	return 0;
+}
+
+static struct usb_configuration cdc_config_driver = {
+	.label			= "CDC Composite (ECM + ACM)",
+	.bind			= cdc_do_config,
+	.bConfigurationValue	= 1,
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower		= 1,	/* 2 mA, minimal */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init cdc_bind(struct usb_composite_dev *cdev)
+{
+	int			gcnum;
+	struct usb_gadget	*gadget = cdev->gadget;
+	int			status;
+
+	if (!can_support_ecm(cdev->gadget)) {
+		ERROR(cdev, "controller '%s' not usable\n", gadget->name);
+		return -EINVAL;
+	}
+
+	/* set up network link layer */
+	status = gether_setup(cdev->gadget, hostaddr);
+	if (status < 0)
+		return status;
+
+	/* set up serial link layer */
+	status = gserial_setup(cdev->gadget, 1);
+	if (status < 0)
+		goto fail0;
+
+	gcnum = usb_gadget_controller_number(gadget);
+	if (gcnum >= 0)
+		device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
+	else {
+		/* We assume that can_support_ecm() tells the truth;
+		 * but if the controller isn't recognized at all then
+		 * that assumption is a bit more likely to be wrong.
+		 */
+		WARNING(cdev, "controller '%s' not recognized; trying %s\n",
+				gadget->name,
+				cdc_config_driver.label);
+		device_desc.bcdDevice =
+			__constant_cpu_to_le16(0x0300 | 0x0099);
+	}
+
+
+	/* Allocate string descriptor numbers ... note that string
+	 * contents can be overridden by the composite_dev glue.
+	 */
+
+	/* device descriptor strings: manufacturer, product */
+	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
+		init_utsname()->sysname, init_utsname()->release,
+		gadget->name);
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail1;
+	strings_dev[STRING_MANUFACTURER_IDX].id = status;
+	device_desc.iManufacturer = status;
+
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail1;
+	strings_dev[STRING_PRODUCT_IDX].id = status;
+	device_desc.iProduct = status;
+
+	/* register our configuration */
+	status = usb_add_config(cdev, &cdc_config_driver);
+	if (status < 0)
+		goto fail1;
+
+	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC);
+
+	return 0;
+
+fail1:
+	gserial_cleanup();
+fail0:
+	gether_cleanup();
+	return status;
+}
+
+static int __exit cdc_unbind(struct usb_composite_dev *cdev)
+{
+	gserial_cleanup();
+	gether_cleanup();
+	return 0;
+}
+
+static struct usb_composite_driver cdc_driver = {
+	.name		= "g_cdc",
+	.dev		= &device_desc,
+	.strings	= dev_strings,
+	.bind		= cdc_bind,
+	.unbind		= __exit_p(cdc_unbind),
+};
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
+
+static int __init init(void)
+{
+	return usb_composite_register(&cdc_driver);
+}
+module_init(init);
+
+static void __exit cleanup(void)
+{
+	usb_composite_unregister(&cdc_driver);
+}
+module_exit(cleanup);
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
new file mode 100644
index 0000000..85c876c
--- /dev/null
+++ b/drivers/usb/gadget/composite.c
@@ -0,0 +1,1041 @@
+/*
+ * composite.c - infrastructure for Composite USB Gadgets
+ *
+ * Copyright (C) 2006-2008 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kallsyms.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+
+#include <linux/usb/composite.h>
+
+
+/*
+ * The code in this file is utility code, used to build a gadget driver
+ * from one or more "function" drivers, one or more "configuration"
+ * objects, and a "usb_composite_driver" by gluing them together along
+ * with the relevant device-wide data.
+ */
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ	512
+
+static struct usb_composite_driver *composite;
+
+/* Some systems will need runtime overrides for the  product identifers
+ * published in the device descriptor, either numbers or strings or both.
+ * String parameters are in UTF-8 (superset of ASCII's 7 bit characters).
+ */
+
+static ushort idVendor;
+module_param(idVendor, ushort, 0);
+MODULE_PARM_DESC(idVendor, "USB Vendor ID");
+
+static ushort idProduct;
+module_param(idProduct, ushort, 0);
+MODULE_PARM_DESC(idProduct, "USB Product ID");
+
+static ushort bcdDevice;
+module_param(bcdDevice, ushort, 0);
+MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
+
+static char *iManufacturer;
+module_param(iManufacturer, charp, 0);
+MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
+
+static char *iProduct;
+module_param(iProduct, charp, 0);
+MODULE_PARM_DESC(iProduct, "USB Product string");
+
+static char *iSerialNumber;
+module_param(iSerialNumber, charp, 0);
+MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * usb_add_function() - add a function to a configuration
+ * @config: the configuration
+ * @function: the function being added
+ * Context: single threaded during gadget setup
+ *
+ * After initialization, each configuration must have one or more
+ * functions added to it.  Adding a function involves calling its @bind()
+ * method to allocate resources such as interface and string identifiers
+ * and endpoints.
+ *
+ * This function returns the value of the function's bind(), which is
+ * zero for success else a negative errno value.
+ */
+int __init usb_add_function(struct usb_configuration *config,
+		struct usb_function *function)
+{
+	int	value = -EINVAL;
+
+	DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n",
+			function->name, function,
+			config->label, config);
+
+	if (!function->set_alt || !function->disable)
+		goto done;
+
+	function->config = config;
+	list_add_tail(&function->list, &config->functions);
+
+	/* REVISIT *require* function->bind? */
+	if (function->bind) {
+		value = function->bind(config, function);
+		if (value < 0) {
+			list_del(&function->list);
+			function->config = NULL;
+		}
+	} else
+		value = 0;
+
+	/* We allow configurations that don't work at both speeds.
+	 * If we run into a lowspeed Linux system, treat it the same
+	 * as full speed ... it's the function drivers that will need
+	 * to avoid bulk and ISO transfers.
+	 */
+	if (!config->fullspeed && function->descriptors)
+		config->fullspeed = true;
+	if (!config->highspeed && function->hs_descriptors)
+		config->highspeed = true;
+
+done:
+	if (value)
+		DBG(config->cdev, "adding '%s'/%p --> %d\n",
+				function->name, function, value);
+	return value;
+}
+
+/**
+ * usb_interface_id() - allocate an unused interface ID
+ * @config: configuration associated with the interface
+ * @function: function handling the interface
+ * Context: single threaded during gadget setup
+ *
+ * usb_interface_id() is called from usb_function.bind() callbacks to
+ * allocate new interface IDs.  The function driver will then store that
+ * ID in interface, association, CDC union, and other descriptors.  It
+ * will also handle any control requests targetted at that interface,
+ * particularly changing its altsetting via set_alt().  There may
+ * also be class-specific or vendor-specific requests to handle.
+ *
+ * All interface identifier should be allocated using this routine, to
+ * ensure that for example different functions don't wrongly assign
+ * different meanings to the same identifier.  Note that since interface
+ * identifers are configuration-specific, functions used in more than
+ * one configuration (or more than once in a given configuration) need
+ * multiple versions of the relevant descriptors.
+ *
+ * Returns the interface ID which was allocated; or -ENODEV if no
+ * more interface IDs can be allocated.
+ */
+int __init usb_interface_id(struct usb_configuration *config,
+		struct usb_function *function)
+{
+	unsigned id = config->next_interface_id;
+
+	if (id < MAX_CONFIG_INTERFACES) {
+		config->interface[id] = function;
+		config->next_interface_id = id + 1;
+		return id;
+	}
+	return -ENODEV;
+}
+
+static int config_buf(struct usb_configuration *config,
+		enum usb_device_speed speed, void *buf, u8 type)
+{
+	struct usb_config_descriptor	*c = buf;
+	void				*next = buf + USB_DT_CONFIG_SIZE;
+	int				len = USB_BUFSIZ - USB_DT_CONFIG_SIZE;
+	struct usb_function		*f;
+	int				status;
+
+	/* write the config descriptor */
+	c = buf;
+	c->bLength = USB_DT_CONFIG_SIZE;
+	c->bDescriptorType = type;
+	/* wTotalLength is written later */
+	c->bNumInterfaces = config->next_interface_id;
+	c->bConfigurationValue = config->bConfigurationValue;
+	c->iConfiguration = config->iConfiguration;
+	c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes;
+	c->bMaxPower = config->bMaxPower;
+
+	/* There may be e.g. OTG descriptors */
+	if (config->descriptors) {
+		status = usb_descriptor_fillbuf(next, len,
+				config->descriptors);
+		if (status < 0)
+			return status;
+		len -= status;
+		next += status;
+	}
+
+	/* add each function's descriptors */
+	list_for_each_entry(f, &config->functions, list) {
+		struct usb_descriptor_header **descriptors;
+
+		if (speed == USB_SPEED_HIGH)
+			descriptors = f->hs_descriptors;
+		else
+			descriptors = f->descriptors;
+		if (!descriptors)
+			continue;
+		status = usb_descriptor_fillbuf(next, len,
+			(const struct usb_descriptor_header **) descriptors);
+		if (status < 0)
+			return status;
+		len -= status;
+		next += status;
+	}
+
+	len = next - buf;
+	c->wTotalLength = cpu_to_le16(len);
+	return len;
+}
+
+static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
+{
+	struct usb_gadget		*gadget = cdev->gadget;
+	struct usb_configuration	*c;
+	u8				type = w_value >> 8;
+	enum usb_device_speed		speed = USB_SPEED_UNKNOWN;
+
+	if (gadget_is_dualspeed(gadget)) {
+		int			hs = 0;
+
+		if (gadget->speed == USB_SPEED_HIGH)
+			hs = 1;
+		if (type == USB_DT_OTHER_SPEED_CONFIG)
+			hs = !hs;
+		if (hs)
+			speed = USB_SPEED_HIGH;
+
+	}
+
+	/* This is a lookup by config *INDEX* */
+	w_value &= 0xff;
+	list_for_each_entry(c, &cdev->configs, list) {
+		/* ignore configs that won't work at this speed */
+		if (speed == USB_SPEED_HIGH) {
+			if (!c->highspeed)
+				continue;
+		} else {
+			if (!c->fullspeed)
+				continue;
+		}
+		if (w_value == 0)
+			return config_buf(c, speed, cdev->req->buf, type);
+		w_value--;
+	}
+	return -EINVAL;
+}
+
+static int count_configs(struct usb_composite_dev *cdev, unsigned type)
+{
+	struct usb_gadget		*gadget = cdev->gadget;
+	struct usb_configuration	*c;
+	unsigned			count = 0;
+	int				hs = 0;
+
+	if (gadget_is_dualspeed(gadget)) {
+		if (gadget->speed == USB_SPEED_HIGH)
+			hs = 1;
+		if (type == USB_DT_DEVICE_QUALIFIER)
+			hs = !hs;
+	}
+	list_for_each_entry(c, &cdev->configs, list) {
+		/* ignore configs that won't work at this speed */
+		if (hs) {
+			if (!c->highspeed)
+				continue;
+		} else {
+			if (!c->fullspeed)
+				continue;
+		}
+		count++;
+	}
+	return count;
+}
+
+static void device_qual(struct usb_composite_dev *cdev)
+{
+	struct usb_qualifier_descriptor	*qual = cdev->req->buf;
+
+	qual->bLength = sizeof(*qual);
+	qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER;
+	/* POLICY: same bcdUSB and device type info at both speeds */
+	qual->bcdUSB = cdev->desc.bcdUSB;
+	qual->bDeviceClass = cdev->desc.bDeviceClass;
+	qual->bDeviceSubClass = cdev->desc.bDeviceSubClass;
+	qual->bDeviceProtocol = cdev->desc.bDeviceProtocol;
+	/* ASSUME same EP0 fifo size at both speeds */
+	qual->bMaxPacketSize0 = cdev->desc.bMaxPacketSize0;
+	qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER);
+	qual->bRESERVED = 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void reset_config(struct usb_composite_dev *cdev)
+{
+	struct usb_function		*f;
+
+	DBG(cdev, "reset config\n");
+
+	list_for_each_entry(f, &cdev->config->functions, list) {
+		if (f->disable)
+			f->disable(f);
+	}
+	cdev->config = NULL;
+}
+
+static int set_config(struct usb_composite_dev *cdev,
+		const struct usb_ctrlrequest *ctrl, unsigned number)
+{
+	struct usb_gadget	*gadget = cdev->gadget;
+	struct usb_configuration *c = NULL;
+	int			result = -EINVAL;
+	unsigned		power = gadget_is_otg(gadget) ? 8 : 100;
+	int			tmp;
+
+	if (cdev->config)
+		reset_config(cdev);
+
+	if (number) {
+		list_for_each_entry(c, &cdev->configs, list) {
+			if (c->bConfigurationValue == number) {
+				result = 0;
+				break;
+			}
+		}
+		if (result < 0)
+			goto done;
+	} else
+		result = 0;
+
+	INFO(cdev, "%s speed config #%d: %s\n",
+		({ char *speed;
+		switch (gadget->speed) {
+		case USB_SPEED_LOW:	speed = "low"; break;
+		case USB_SPEED_FULL:	speed = "full"; break;
+		case USB_SPEED_HIGH:	speed = "high"; break;
+		default:		speed = "?"; break;
+		} ; speed; }), number, c ? c->label : "unconfigured");
+
+	if (!c)
+		goto done;
+
+	cdev->config = c;
+
+	/* Initialize all interfaces by setting them to altsetting zero. */
+	for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) {
+		struct usb_function	*f = c->interface[tmp];
+
+		if (!f)
+			break;
+
+		result = f->set_alt(f, tmp, 0);
+		if (result < 0) {
+			DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n",
+					tmp, f->name, f, result);
+
+			reset_config(cdev);
+			goto done;
+		}
+	}
+
+	/* when we return, be sure our power usage is valid */
+	power = 2 * c->bMaxPower;
+done:
+	usb_gadget_vbus_draw(gadget, power);
+	return result;
+}
+
+/**
+ * usb_add_config() - add a configuration to a device.
+ * @cdev: wraps the USB gadget
+ * @config: the configuration, with bConfigurationValue assigned
+ * Context: single threaded during gadget setup
+ *
+ * One of the main tasks of a composite driver's bind() routine is to
+ * add each of the configurations it supports, using this routine.
+ *
+ * This function returns the value of the configuration's bind(), which
+ * is zero for success else a negative errno value.  Binding configurations
+ * assigns global resources including string IDs, and per-configuration
+ * resources such as interface IDs and endpoints.
+ */
+int __init usb_add_config(struct usb_composite_dev *cdev,
+		struct usb_configuration *config)
+{
+	int				status = -EINVAL;
+	struct usb_configuration	*c;
+
+	DBG(cdev, "adding config #%u '%s'/%p\n",
+			config->bConfigurationValue,
+			config->label, config);
+
+	if (!config->bConfigurationValue || !config->bind)
+		goto done;
+
+	/* Prevent duplicate configuration identifiers */
+	list_for_each_entry(c, &cdev->configs, list) {
+		if (c->bConfigurationValue == config->bConfigurationValue) {
+			status = -EBUSY;
+			goto done;
+		}
+	}
+
+	config->cdev = cdev;
+	list_add_tail(&config->list, &cdev->configs);
+
+	INIT_LIST_HEAD(&config->functions);
+	config->next_interface_id = 0;
+
+	status = config->bind(config);
+	if (status < 0) {
+		list_del(&config->list);
+		config->cdev = NULL;
+	} else {
+		unsigned	i;
+
+		DBG(cdev, "cfg %d/%p speeds:%s%s\n",
+			config->bConfigurationValue, config,
+			config->highspeed ? " high" : "",
+			config->fullspeed
+				? (gadget_is_dualspeed(cdev->gadget)
+					? " full"
+					: " full/low")
+				: "");
+
+		for (i = 0; i < MAX_CONFIG_INTERFACES; i++) {
+			struct usb_function	*f = config->interface[i];
+
+			if (!f)
+				continue;
+			DBG(cdev, "  interface %d = %s/%p\n",
+				i, f->name, f);
+		}
+	}
+
+	/* set_alt(), or next config->bind(), sets up
+	 * ep->driver_data as needed.
+	 */
+	usb_ep_autoconfig_reset(cdev->gadget);
+
+done:
+	if (status)
+		DBG(cdev, "added config '%s'/%u --> %d\n", config->label,
+				config->bConfigurationValue, status);
+	return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* We support strings in multiple languages ... string descriptor zero
+ * says which languages are supported.  The typical case will be that
+ * only one language (probably English) is used, with I18N handled on
+ * the host side.
+ */
+
+static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf)
+{
+	const struct usb_gadget_strings	*s;
+	u16				language;
+	__le16				*tmp;
+
+	while (*sp) {
+		s = *sp;
+		language = cpu_to_le16(s->language);
+		for (tmp = buf; *tmp && tmp < &buf[126]; tmp++) {
+			if (*tmp == language)
+				goto repeat;
+		}
+		*tmp++ = language;
+repeat:
+		sp++;
+	}
+}
+
+static int lookup_string(
+	struct usb_gadget_strings	**sp,
+	void				*buf,
+	u16				language,
+	int				id
+)
+{
+	struct usb_gadget_strings	*s;
+	int				value;
+
+	while (*sp) {
+		s = *sp++;
+		if (s->language != language)
+			continue;
+		value = usb_gadget_get_string(s, id, buf);
+		if (value > 0)
+			return value;
+	}
+	return -EINVAL;
+}
+
+static int get_string(struct usb_composite_dev *cdev,
+		void *buf, u16 language, int id)
+{
+	struct usb_configuration	*c;
+	struct usb_function		*f;
+	int				len;
+
+	/* Yes, not only is USB's I18N support probably more than most
+	 * folk will ever care about ... also, it's all supported here.
+	 * (Except for UTF8 support for Unicode's "Astral Planes".)
+	 */
+
+	/* 0 == report all available language codes */
+	if (id == 0) {
+		struct usb_string_descriptor	*s = buf;
+		struct usb_gadget_strings	**sp;
+
+		memset(s, 0, 256);
+		s->bDescriptorType = USB_DT_STRING;
+
+		sp = composite->strings;
+		if (sp)
+			collect_langs(sp, s->wData);
+
+		list_for_each_entry(c, &cdev->configs, list) {
+			sp = c->strings;
+			if (sp)
+				collect_langs(sp, s->wData);
+
+			list_for_each_entry(f, &c->functions, list) {
+				sp = f->strings;
+				if (sp)
+					collect_langs(sp, s->wData);
+			}
+		}
+
+		for (len = 0; s->wData[len] && len <= 126; len++)
+			continue;
+		if (!len)
+			return -EINVAL;
+
+		s->bLength = 2 * (len + 1);
+		return s->bLength;
+	}
+
+	/* Otherwise, look up and return a specified string.  String IDs
+	 * are device-scoped, so we look up each string table we're told
+	 * about.  These lookups are infrequent; simpler-is-better here.
+	 */
+	if (composite->strings) {
+		len = lookup_string(composite->strings, buf, language, id);
+		if (len > 0)
+			return len;
+	}
+	list_for_each_entry(c, &cdev->configs, list) {
+		if (c->strings) {
+			len = lookup_string(c->strings, buf, language, id);
+			if (len > 0)
+				return len;
+		}
+		list_for_each_entry(f, &c->functions, list) {
+			if (!f->strings)
+				continue;
+			len = lookup_string(f->strings, buf, language, id);
+			if (len > 0)
+				return len;
+		}
+	}
+	return -EINVAL;
+}
+
+/**
+ * usb_string_id() - allocate an unused string ID
+ * @cdev: the device whose string descriptor IDs are being allocated
+ * Context: single threaded during gadget setup
+ *
+ * @usb_string_id() is called from bind() callbacks to allocate
+ * string IDs.  Drivers for functions, configurations, or gadgets will
+ * then store that ID in the appropriate descriptors and string table.
+ *
+ * All string identifier should be allocated using this routine, to
+ * ensure that for example different functions don't wrongly assign
+ * different meanings to the same identifier.
+ */
+int __init usb_string_id(struct usb_composite_dev *cdev)
+{
+	if (cdev->next_string_id < 254) {
+		/* string id 0 is reserved */
+		cdev->next_string_id++;
+		return cdev->next_string_id;
+	}
+	return -ENODEV;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	if (req->status || req->actual != req->length)
+		DBG((struct usb_composite_dev *) ep->driver_data,
+				"setup complete --> %d, %d/%d\n",
+				req->status, req->actual, req->length);
+}
+
+/*
+ * The setup() callback implements all the ep0 functionality that's
+ * not handled lower down, in hardware or the hardware driver(like
+ * device and endpoint feature flags, and their status).  It's all
+ * housekeeping for the gadget function we're implementing.  Most of
+ * the work is in config and function specific setup.
+ */
+static int
+composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
+	struct usb_request		*req = cdev->req;
+	int				value = -EOPNOTSUPP;
+	u16				w_index = le16_to_cpu(ctrl->wIndex);
+	u16				w_value = le16_to_cpu(ctrl->wValue);
+	u16				w_length = le16_to_cpu(ctrl->wLength);
+	struct usb_function		*f = NULL;
+
+	/* partial re-init of the response message; the function or the
+	 * gadget might need to intercept e.g. a control-OUT completion
+	 * when we delegate to it.
+	 */
+	req->zero = 0;
+	req->complete = composite_setup_complete;
+	req->length = USB_BUFSIZ;
+	gadget->ep0->driver_data = cdev;
+
+	switch (ctrl->bRequest) {
+
+	/* we handle all standard USB descriptors */
+	case USB_REQ_GET_DESCRIPTOR:
+		if (ctrl->bRequestType != USB_DIR_IN)
+			goto unknown;
+		switch (w_value >> 8) {
+
+		case USB_DT_DEVICE:
+			cdev->desc.bNumConfigurations =
+				count_configs(cdev, USB_DT_DEVICE);
+			value = min(w_length, (u16) sizeof cdev->desc);
+			memcpy(req->buf, &cdev->desc, value);
+			break;
+		case USB_DT_DEVICE_QUALIFIER:
+			if (!gadget_is_dualspeed(gadget))
+				break;
+			device_qual(cdev);
+			value = min_t(int, w_length,
+				sizeof(struct usb_qualifier_descriptor));
+			break;
+		case USB_DT_OTHER_SPEED_CONFIG:
+			if (!gadget_is_dualspeed(gadget))
+				break;
+			/* FALLTHROUGH */
+		case USB_DT_CONFIG:
+			value = config_desc(cdev, w_value);
+			if (value >= 0)
+				value = min(w_length, (u16) value);
+			break;
+		case USB_DT_STRING:
+			value = get_string(cdev, req->buf,
+					w_index, w_value & 0xff);
+			if (value >= 0)
+				value = min(w_length, (u16) value);
+			break;
+		}
+		break;
+
+	/* any number of configs can work */
+	case USB_REQ_SET_CONFIGURATION:
+		if (ctrl->bRequestType != 0)
+			goto unknown;
+		if (gadget_is_otg(gadget)) {
+			if (gadget->a_hnp_support)
+				DBG(cdev, "HNP available\n");
+			else if (gadget->a_alt_hnp_support)
+				DBG(cdev, "HNP on another port\n");
+			else
+				VDBG(cdev, "HNP inactive\n");
+		}
+		spin_lock(&cdev->lock);
+		value = set_config(cdev, ctrl, w_value);
+		spin_unlock(&cdev->lock);
+		break;
+	case USB_REQ_GET_CONFIGURATION:
+		if (ctrl->bRequestType != USB_DIR_IN)
+			goto unknown;
+		if (cdev->config)
+			*(u8 *)req->buf = cdev->config->bConfigurationValue;
+		else
+			*(u8 *)req->buf = 0;
+		value = min(w_length, (u16) 1);
+		break;
+
+	/* function drivers must handle get/set altsetting; if there's
+	 * no get() method, we know only altsetting zero works.
+	 */
+	case USB_REQ_SET_INTERFACE:
+		if (ctrl->bRequestType != USB_RECIP_INTERFACE)
+			goto unknown;
+		if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES)
+			break;
+		f = cdev->config->interface[w_index];
+		if (!f)
+			break;
+		if (w_value && !f->get_alt)
+			break;
+		value = f->set_alt(f, w_index, w_value);
+		break;
+	case USB_REQ_GET_INTERFACE:
+		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
+			goto unknown;
+		if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES)
+			break;
+		f = cdev->config->interface[w_index];
+		if (!f)
+			break;
+		/* lots of interfaces only need altsetting zero... */
+		value = f->get_alt ? f->get_alt(f, w_index) : 0;
+		if (value < 0)
+			break;
+		*((u8 *)req->buf) = value;
+		value = min(w_length, (u16) 1);
+		break;
+	default:
+unknown:
+		VDBG(cdev,
+			"non-core control req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+
+		/* functions always handle their interfaces ... punt other
+		 * recipients (endpoint, other, WUSB, ...) to the current
+		 * configuration code.
+		 *
+		 * REVISIT it could make sense to let the composite device
+		 * take such requests too, if that's ever needed:  to work
+		 * in config 0, etc.
+		 */
+		if ((ctrl->bRequestType & USB_RECIP_MASK)
+				== USB_RECIP_INTERFACE) {
+			f = cdev->config->interface[w_index];
+			if (f && f->setup)
+				value = f->setup(f, ctrl);
+			else
+				f = NULL;
+		}
+		if (value < 0 && !f) {
+			struct usb_configuration	*c;
+
+			c = cdev->config;
+			if (c && c->setup)
+				value = c->setup(c, ctrl);
+		}
+
+		goto done;
+	}
+
+	/* respond with data transfer before status phase? */
+	if (value >= 0) {
+		req->length = value;
+		req->zero = value < w_length;
+		value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0) {
+			DBG(cdev, "ep_queue --> %d\n", value);
+			req->status = 0;
+			composite_setup_complete(gadget->ep0, req);
+		}
+	}
+
+done:
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+static void composite_disconnect(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
+	unsigned long			flags;
+
+	/* REVISIT:  should we have config and device level
+	 * disconnect callbacks?
+	 */
+	spin_lock_irqsave(&cdev->lock, flags);
+	if (cdev->config)
+		reset_config(cdev);
+	spin_unlock_irqrestore(&cdev->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void /* __init_or_exit */
+composite_unbind(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
+
+	/* composite_disconnect() must already have been called
+	 * by the underlying peripheral controller driver!
+	 * so there's no i/o concurrency that could affect the
+	 * state protected by cdev->lock.
+	 */
+	WARN_ON(cdev->config);
+
+	while (!list_empty(&cdev->configs)) {
+		struct usb_configuration	*c;
+
+		c = list_first_entry(&cdev->configs,
+				struct usb_configuration, list);
+		while (!list_empty(&c->functions)) {
+			struct usb_function		*f;
+
+			f = list_first_entry(&c->functions,
+					struct usb_function, list);
+			list_del(&f->list);
+			if (f->unbind) {
+				DBG(cdev, "unbind function '%s'/%p\n",
+						f->name, f);
+				f->unbind(c, f);
+				/* may free memory for "f" */
+			}
+		}
+		list_del(&c->list);
+		if (c->unbind) {
+			DBG(cdev, "unbind config '%s'/%p\n", c->label, c);
+			c->unbind(c);
+			/* may free memory for "c" */
+		}
+	}
+	if (composite->unbind)
+		composite->unbind(cdev);
+
+	if (cdev->req) {
+		kfree(cdev->req->buf);
+		usb_ep_free_request(gadget->ep0, cdev->req);
+	}
+	kfree(cdev);
+	set_gadget_data(gadget, NULL);
+	composite = NULL;
+}
+
+static void __init
+string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s)
+{
+	struct usb_string		*str = tab->strings;
+
+	for (str = tab->strings; str->s; str++) {
+		if (str->id == id) {
+			str->s = s;
+			return;
+		}
+	}
+}
+
+static void __init
+string_override(struct usb_gadget_strings **tab, u8 id, const char *s)
+{
+	while (*tab) {
+		string_override_one(*tab, id, s);
+		tab++;
+	}
+}
+
+static int __init composite_bind(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev	*cdev;
+	int				status = -ENOMEM;
+
+	cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
+	if (!cdev)
+		return status;
+
+	spin_lock_init(&cdev->lock);
+	cdev->gadget = gadget;
+	set_gadget_data(gadget, cdev);
+	INIT_LIST_HEAD(&cdev->configs);
+
+	/* preallocate control response and buffer */
+	cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
+	if (!cdev->req)
+		goto fail;
+	cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
+	if (!cdev->req->buf)
+		goto fail;
+	cdev->req->complete = composite_setup_complete;
+	gadget->ep0->driver_data = cdev;
+
+	cdev->bufsiz = USB_BUFSIZ;
+	cdev->driver = composite;
+
+	usb_gadget_set_selfpowered(gadget);
+
+	/* interface and string IDs start at zero via kzalloc.
+	 * we force endpoints to start unassigned; few controller
+	 * drivers will zero ep->driver_data.
+	 */
+	usb_ep_autoconfig_reset(cdev->gadget);
+
+	/* composite gadget needs to assign strings for whole device (like
+	 * serial number), register function drivers, potentially update
+	 * power state and consumption, etc
+	 */
+	status = composite->bind(cdev);
+	if (status < 0)
+		goto fail;
+
+	cdev->desc = *composite->dev;
+	cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+
+	/* standardized runtime overrides for device ID data */
+	if (idVendor)
+		cdev->desc.idVendor = cpu_to_le16(idVendor);
+	if (idProduct)
+		cdev->desc.idProduct = cpu_to_le16(idProduct);
+	if (bcdDevice)
+		cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
+
+	/* strings can't be assigned before bind() allocates the
+	 * releavnt identifiers
+	 */
+	if (cdev->desc.iManufacturer && iManufacturer)
+		string_override(composite->strings,
+			cdev->desc.iManufacturer, iManufacturer);
+	if (cdev->desc.iProduct && iProduct)
+		string_override(composite->strings,
+			cdev->desc.iProduct, iProduct);
+	if (cdev->desc.iSerialNumber && iSerialNumber)
+		string_override(composite->strings,
+			cdev->desc.iSerialNumber, iSerialNumber);
+
+	INFO(cdev, "%s ready\n", composite->name);
+	return 0;
+
+fail:
+	composite_unbind(gadget);
+	return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+composite_suspend(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
+	struct usb_function		*f;
+
+	/* REVISIT:  should we have config and device level
+	 * suspend/resume callbacks?
+	 */
+	DBG(cdev, "suspend\n");
+	if (cdev->config) {
+		list_for_each_entry(f, &cdev->config->functions, list) {
+			if (f->suspend)
+				f->suspend(f);
+		}
+	}
+}
+
+static void
+composite_resume(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
+	struct usb_function		*f;
+
+	/* REVISIT:  should we have config and device level
+	 * suspend/resume callbacks?
+	 */
+	DBG(cdev, "resume\n");
+	if (cdev->config) {
+		list_for_each_entry(f, &cdev->config->functions, list) {
+			if (f->resume)
+				f->resume(f);
+		}
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_gadget_driver composite_driver = {
+	.speed		= USB_SPEED_HIGH,
+
+	.bind		= composite_bind,
+	.unbind		= __exit_p(composite_unbind),
+
+	.setup		= composite_setup,
+	.disconnect	= composite_disconnect,
+
+	.suspend	= composite_suspend,
+	.resume		= composite_resume,
+
+	.driver	= {
+		.owner		= THIS_MODULE,
+	},
+};
+
+/**
+ * usb_composite_register() - register a composite driver
+ * @driver: the driver to register
+ * Context: single threaded during gadget setup
+ *
+ * This function is used to register drivers using the composite driver
+ * framework.  The return value is zero, or a negative errno value.
+ * Those values normally come from the driver's @bind method, which does
+ * all the work of setting up the driver to match the hardware.
+ *
+ * On successful return, the gadget is ready to respond to requests from
+ * the host, unless one of its components invokes usb_gadget_disconnect()
+ * while it was binding.  That would usually be done in order to wait for
+ * some userspace participation.
+ */
+int __init usb_composite_register(struct usb_composite_driver *driver)
+{
+	if (!driver || !driver->dev || !driver->bind || composite)
+		return -EINVAL;
+
+	if (!driver->name)
+		driver->name = "composite";
+	composite_driver.function =  (char *) driver->name;
+	composite_driver.driver.name = driver->name;
+	composite = driver;
+
+	return usb_gadget_register_driver(&composite_driver);
+}
+
+/**
+ * usb_composite_unregister() - unregister a composite driver
+ * @driver: the driver to unregister
+ *
+ * This function is used to unregister drivers using the composite
+ * driver framework.
+ */
+void __exit usb_composite_unregister(struct usb_composite_driver *driver)
+{
+	if (composite != driver)
+		return;
+	usb_gadget_unregister_driver(&composite_driver);
+}
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index a4e54b2..1ca1c32 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -96,7 +96,7 @@ int usb_gadget_config_buf(
 	/* config descriptor first */
 	if (length < USB_DT_CONFIG_SIZE || !desc)
 		return -EINVAL;
-	*cp = *config; 
+	*cp = *config;
 
 	/* then interface/endpoint/class/vendor/... */
 	len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
@@ -115,3 +115,77 @@ int usb_gadget_config_buf(
 	return len;
 }
 
+/**
+ * usb_copy_descriptors - copy a vector of USB descriptors
+ * @src: null-terminated vector to copy
+ * Context: initialization code, which may sleep
+ *
+ * This makes a copy of a vector of USB descriptors.  Its primary use
+ * is to support usb_function objects which can have multiple copies,
+ * each needing different descriptors.  Functions may have static
+ * tables of descriptors, which are used as templates and customized
+ * with identifiers (for interfaces, strings, endpoints, and more)
+ * as needed by a given function instance.
+ */
+struct usb_descriptor_header **__init
+usb_copy_descriptors(struct usb_descriptor_header **src)
+{
+	struct usb_descriptor_header **tmp;
+	unsigned bytes;
+	unsigned n_desc;
+	void *mem;
+	struct usb_descriptor_header **ret;
+
+	/* count descriptors and their sizes; then add vector size */
+	for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++)
+		bytes += (*tmp)->bLength;
+	bytes += (n_desc + 1) * sizeof(*tmp);
+
+	mem = kmalloc(bytes, GFP_KERNEL);
+	if (!mem)
+		return NULL;
+
+	/* fill in pointers starting at "tmp",
+	 * to descriptors copied starting at "mem";
+	 * and return "ret"
+	 */
+	tmp = mem;
+	ret = mem;
+	mem += (n_desc + 1) * sizeof(*tmp);
+	while (*src) {
+		memcpy(mem, *src, (*src)->bLength);
+		*tmp = mem;
+		tmp++;
+		mem += (*src)->bLength;
+		src++;
+	}
+	*tmp = NULL;
+
+	return ret;
+}
+
+/**
+ * usb_find_endpoint - find a copy of an endpoint descriptor
+ * @src: original vector of descriptors
+ * @copy: copy of @src
+ * @ep: endpoint descriptor found in @src
+ *
+ * This returns the copy of the @match descriptor made for @copy.  Its
+ * intended use is to help remembering the endpoint descriptor to use
+ * when enabling a given endpoint.
+ */
+struct usb_endpoint_descriptor *__init
+usb_find_endpoint(
+	struct usb_descriptor_header **src,
+	struct usb_descriptor_header **copy,
+	struct usb_endpoint_descriptor *match
+)
+{
+	while (*src) {
+		if (*src == (void *) match)
+			return (void *)*copy;
+		src++;
+		copy++;
+	}
+	return NULL;
+}
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 4203619..7600a0c 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -542,13 +542,14 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
 		req->req.context = dum;
 		req->req.complete = fifo_complete;
 
+		list_add_tail(&req->queue, &ep->queue);
 		spin_unlock (&dum->lock);
 		_req->actual = _req->length;
 		_req->status = 0;
 		_req->complete (_ep, _req);
 		spin_lock (&dum->lock);
-	}
-	list_add_tail (&req->queue, &ep->queue);
+	}  else
+		list_add_tail(&req->queue, &ep->queue);
 	spin_unlock_irqrestore (&dum->lock, flags);
 
 	/* real hardware would likely enable transfers here, in case
@@ -862,7 +863,7 @@ static int dummy_udc_probe (struct platform_device *pdev)
 	/* maybe claim OTG support, though we won't complete HNP */
 	dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
 
-	strcpy (dum->gadget.dev.bus_id, "gadget");
+	dev_set_name(&dum->gadget.dev, "gadget");
 	dum->gadget.dev.parent = &pdev->dev;
 	dum->gadget.dev.release = dummy_gadget_release;
 	rc = device_register (&dum->gadget.dev);
@@ -1865,7 +1866,7 @@ static int dummy_hcd_probe(struct platform_device *pdev)
 
 	dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
 
-	hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, pdev->dev.bus_id);
+	hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev));
 	if (!hcd)
 		return -ENOMEM;
 	the_controller = hcd_to_dummy (hcd);
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 8bdad22..9462e30 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -159,6 +159,7 @@ ep_matches (
 	/* MATCH!! */
 
 	/* report address */
+	desc->bEndpointAddress &= USB_DIR_IN;
 	if (isdigit (ep->name [2])) {
 		u8	num = simple_strtol (&ep->name [2], NULL, 10);
 		desc->bEndpointAddress |= num;
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 8d61ea6..bcac2e6 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -1,8 +1,9 @@
 /*
  * ether.c -- Ethernet gadget driver, with CDC and non-CDC options
  *
- * Copyright (C) 2003-2005 David Brownell
+ * Copyright (C) 2003-2005,2008 David Brownell
  * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,18 +24,9 @@
 
 #include <linux/kernel.h>
 #include <linux/utsname.h>
-#include <linux/device.h>
-#include <linux/ctype.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
 
-#include <linux/usb/ch9.h>
-#include <linux/usb/cdc.h>
-#include <linux/usb/gadget.h>
+#include "u_ether.h"
 
-#include "gadget_chips.h"
-
-/*-------------------------------------------------------------------------*/
 
 /*
  * Ethernet gadget driver -- with CDC and non-CDC options
@@ -46,7 +38,11 @@
  * this USB-IF standard as its open-systems interoperability solution;
  * most host side USB stacks (except from Microsoft) support it.
  *
- * There's some hardware that can't talk CDC.  We make that hardware
+ * This is sometimes called "CDC ECM" (Ethernet Control Model) to support
+ * TLA-soup.  "CDC ACM" (Abstract Control Model) is for modems, and a new
+ * "CDC EEM" (Ethernet Emulation Model) is starting to spread.
+ *
+ * There's some hardware that can't talk CDC ECM.  We make that hardware
  * implement a "minimalist" vendor-agnostic CDC core:  same framing, but
  * link-level setup only requires activating the configuration.  Only the
  * endpoint descriptors, and product/vendor IDs, are relevant; no control
@@ -64,70 +60,40 @@
  * A third option is also in use.  Rather than CDC Ethernet, or something
  * simpler, Microsoft pushes their own approach: RNDIS.  The published
  * RNDIS specs are ambiguous and appear to be incomplete, and are also
- * needlessly complex.
+ * needlessly complex.  They borrow more from CDC ACM than CDC ECM.
  */
 
 #define DRIVER_DESC		"Ethernet Gadget"
-#define DRIVER_VERSION		"May Day 2005"
-
-static const char shortname [] = "ether";
-static const char driver_desc [] = DRIVER_DESC;
-
-#define RX_EXTRA	20		/* guard against rx overflows */
-
-#include "rndis.h"
+#define DRIVER_VERSION		"Memorial Day 2008"
 
-#ifndef	CONFIG_USB_ETH_RNDIS
-#define rndis_uninit(x)		do{}while(0)
-#define rndis_deregister(c)	do{}while(0)
-#define rndis_exit()		do{}while(0)
+#ifdef CONFIG_USB_ETH_RNDIS
+#define PREFIX			"RNDIS/"
+#else
+#define PREFIX			""
 #endif
 
-/* CDC and RNDIS support the same host-chosen outgoing packet filters. */
-#define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
-			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
-			|USB_CDC_PACKET_TYPE_PROMISCUOUS \
-			|USB_CDC_PACKET_TYPE_DIRECTED)
-
-
-/*-------------------------------------------------------------------------*/
-
-struct eth_dev {
-	spinlock_t		lock;
-	struct usb_gadget	*gadget;
-	struct usb_request	*req;		/* for control responses */
-	struct usb_request	*stat_req;	/* for cdc & rndis status */
-
-	u8			config;
-	struct usb_ep		*in_ep, *out_ep, *status_ep;
-	const struct usb_endpoint_descriptor
-				*in, *out, *status;
-
-	spinlock_t		req_lock;
-	struct list_head	tx_reqs, rx_reqs;
-
-	struct net_device	*net;
-	struct net_device_stats	stats;
-	atomic_t		tx_qlen;
-
-	struct work_struct	work;
-	unsigned		zlp:1;
-	unsigned		cdc:1;
-	unsigned		rndis:1;
-	unsigned		suspended:1;
-	u16			cdc_filter;
-	unsigned long		todo;
-#define	WORK_RX_MEMORY		0
-	int			rndis_config;
-	u8			host_mac [ETH_ALEN];
-};
-
-/* This version autoconfigures as much as possible at run-time.
+/*
+ * This driver aims for interoperability by using CDC ECM unless
+ *
+ *		can_support_ecm()
+ *
+ * returns false, in which case it supports the CDC Subset.  By default,
+ * that returns true; most hardware has no problems with CDC ECM, that's
+ * a good default.  Previous versions of this driver had no default; this
+ * version changes that, removing overhead for new controller support.
  *
- * It also ASSUMES a self-powered device, without remote wakeup,
- * although remote wakeup support would make sense.
+ *	IF YOUR HARDWARE CAN'T SUPPORT CDC ECM, UPDATE THAT ROUTINE!
  */
 
+static inline bool has_rndis(void)
+{
+#ifdef	CONFIG_USB_ETH_RNDIS
+	return true;
+#else
+	return false;
+#endif
+}
+
 /*-------------------------------------------------------------------------*/
 
 /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
@@ -137,8 +103,8 @@ struct eth_dev {
 /* Thanks to NetChip Technologies for donating this product ID.
  * It's for devices with only CDC Ethernet configurations.
  */
-#define CDC_VENDOR_NUM	0x0525		/* NetChip */
-#define CDC_PRODUCT_NUM	0xa4a1		/* Linux-USB Ethernet Gadget */
+#define CDC_VENDOR_NUM		0x0525	/* NetChip */
+#define CDC_PRODUCT_NUM		0xa4a1	/* Linux-USB Ethernet Gadget */
 
 /* For hardware that can't talk CDC, we use the same vendor ID that
  * ARM Linux has used for ethernet-over-usb, both with sa1100 and
@@ -162,274 +128,9 @@ struct eth_dev {
 #define RNDIS_VENDOR_NUM	0x0525	/* NetChip */
 #define RNDIS_PRODUCT_NUM	0xa4a2	/* Ethernet/RNDIS Gadget */
 
-
-/* Some systems will want different product identifers published in the
- * device descriptor, either numbers or strings or both.  These string
- * parameters are in UTF-8 (superset of ASCII's 7 bit characters).
- */
-
-static ushort idVendor;
-module_param(idVendor, ushort, S_IRUGO);
-MODULE_PARM_DESC(idVendor, "USB Vendor ID");
-
-static ushort idProduct;
-module_param(idProduct, ushort, S_IRUGO);
-MODULE_PARM_DESC(idProduct, "USB Product ID");
-
-static ushort bcdDevice;
-module_param(bcdDevice, ushort, S_IRUGO);
-MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
-
-static char *iManufacturer;
-module_param(iManufacturer, charp, S_IRUGO);
-MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
-
-static char *iProduct;
-module_param(iProduct, charp, S_IRUGO);
-MODULE_PARM_DESC(iProduct, "USB Product string");
-
-static char *iSerialNumber;
-module_param(iSerialNumber, charp, S_IRUGO);
-MODULE_PARM_DESC(iSerialNumber, "SerialNumber");
-
-/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
-static char *dev_addr;
-module_param(dev_addr, charp, S_IRUGO);
-MODULE_PARM_DESC(dev_addr, "Device Ethernet Address");
-
-/* this address is invisible to ifconfig */
-static char *host_addr;
-module_param(host_addr, charp, S_IRUGO);
-MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Include CDC support if we could run on CDC-capable hardware. */
-
-#ifdef CONFIG_USB_GADGET_NET2280
-#define	DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_DUMMY_HCD
-#define	DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_GOKU
-#define	DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_LH7A40X
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_MQ11XX
-#define	DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_OMAP
-#define	DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_N9604
-#define	DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_S3C2410
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_AT91
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_MUSBHSFC
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_ATMEL_USBA
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_FSL_USB2
-#define DEV_CONFIG_CDC
-#endif
-
-/* For CDC-incapable hardware, choose the simple cdc subset.
- * Anything that talks bulk (without notable bugs) can do this.
- */
-#ifdef CONFIG_USB_GADGET_PXA2XX
-#define	DEV_CONFIG_SUBSET
-#endif
-
-#ifdef CONFIG_USB_GADGET_PXA27X
-#define	DEV_CONFIG_SUBSET
-#endif
-
-#ifdef CONFIG_USB_GADGET_SUPERH
-#define	DEV_CONFIG_SUBSET
-#endif
-
-#ifdef CONFIG_USB_GADGET_SA1100
-/* use non-CDC for backwards compatibility */
-#define	DEV_CONFIG_SUBSET
-#endif
-
-#ifdef CONFIG_USB_GADGET_M66592
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_AMD5536UDC
-#define	DEV_CONFIG_CDC
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-/* "main" config is either CDC, or its simple subset */
-static inline int is_cdc(struct eth_dev *dev)
-{
-#if	!defined(DEV_CONFIG_SUBSET)
-	return 1;		/* only cdc possible */
-#elif	!defined (DEV_CONFIG_CDC)
-	return 0;		/* only subset possible */
-#else
-	return dev->cdc;	/* depends on what hardware we found */
-#endif
-}
-
-/* "secondary" RNDIS config may sometimes be activated */
-static inline int rndis_active(struct eth_dev *dev)
-{
-#ifdef	CONFIG_USB_ETH_RNDIS
-	return dev->rndis;
-#else
-	return 0;
-#endif
-}
-
-#define	subset_active(dev)	(!is_cdc(dev) && !rndis_active(dev))
-#define	cdc_active(dev)		( is_cdc(dev) && !rndis_active(dev))
-
-
-
-#define DEFAULT_QLEN	2	/* double buffering by default */
-
-/* peak bulk transfer bits-per-second */
-#define	HS_BPS		(13 * 512 * 8 * 1000 * 8)
-#define	FS_BPS		(19 *  64 * 1 * 1000 * 8)
-
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-#define	DEVSPEED	USB_SPEED_HIGH
-
-static unsigned qmult = 5;
-module_param (qmult, uint, S_IRUGO|S_IWUSR);
-
-
-/* for dual-speed hardware, use deeper queues at highspeed */
-#define qlen(gadget) \
-	(DEFAULT_QLEN*((gadget->speed == USB_SPEED_HIGH) ? qmult : 1))
-
-static inline int BITRATE(struct usb_gadget *g)
-{
-	return (g->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS;
-}
-
-#else	/* full speed (low speed doesn't do bulk) */
-
-#define qmult		1
-
-#define	DEVSPEED	USB_SPEED_FULL
-
-#define qlen(gadget) DEFAULT_QLEN
-
-static inline int BITRATE(struct usb_gadget *g)
-{
-	return FS_BPS;
-}
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-#define xprintk(d,level,fmt,args...) \
-	printk(level "%s: " fmt , (d)->net->name , ## args)
-
-#ifdef DEBUG
-#undef DEBUG
-#define DEBUG(dev,fmt,args...) \
-	xprintk(dev , KERN_DEBUG , fmt , ## args)
-#else
-#define DEBUG(dev,fmt,args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#ifdef VERBOSE_DEBUG
-#define VDEBUG	DEBUG
-#else
-#define VDEBUG(dev,fmt,args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#define ERROR(dev,fmt,args...) \
-	xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
-	xprintk(dev , KERN_WARNING , fmt , ## args)
-#define INFO(dev,fmt,args...) \
-	xprintk(dev , KERN_INFO , fmt , ## args)
-
 /*-------------------------------------------------------------------------*/
 
-/* USB DRIVER HOOKUP (to the hardware driver, below us), mostly
- * ep0 implementation:  descriptors, config management, setup().
- * also optional class-specific notification interrupt transfer.
- */
-
-/*
- * DESCRIPTORS ... most are static, but strings and (full) configuration
- * descriptors are built on demand.  For now we do either full CDC, or
- * our simple subset, with RNDIS as an optional second configuration.
- *
- * RNDIS includes some CDC ACM descriptors ... like CDC Ethernet.  But
- * the class descriptors match a modem (they're ignored; it's really just
- * Ethernet functionality), they don't need the NOP altsetting, and the
- * status transfer endpoint isn't optional.
- */
-
-#define STRING_MANUFACTURER		1
-#define STRING_PRODUCT			2
-#define STRING_ETHADDR			3
-#define STRING_DATA			4
-#define STRING_CONTROL			5
-#define STRING_RNDIS_CONTROL		6
-#define STRING_CDC			7
-#define STRING_SUBSET			8
-#define STRING_RNDIS			9
-#define STRING_SERIALNUMBER		10
-
-/* holds our biggest descriptor (or RNDIS response) */
-#define USB_BUFSIZ	256
-
-/*
- * This device advertises one configuration, eth_config, unless RNDIS
- * is enabled (rndis_config) on hardware supporting at least two configs.
- *
- * NOTE:  Controllers like superh_udc should probably be able to use
- * an RNDIS-only configuration.
- *
- * FIXME define some higher-powered configurations to make it easier
- * to recharge batteries ...
- */
-
-#define DEV_CONFIG_VALUE	1	/* cdc or subset */
-#define DEV_RNDIS_CONFIG_VALUE	2	/* rndis; optional */
-
-static struct usb_device_descriptor
-device_desc = {
+static struct usb_device_descriptor device_desc = {
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
 
@@ -438,2220 +139,234 @@ device_desc = {
 	.bDeviceClass =		USB_CLASS_COMM,
 	.bDeviceSubClass =	0,
 	.bDeviceProtocol =	0,
+	/* .bMaxPacketSize0 = f(hardware) */
 
+	/* Vendor and product id defaults change according to what configs
+	 * we support.  (As does bNumConfigurations.)  These values can
+	 * also be overridden by module parameters.
+	 */
 	.idVendor =		__constant_cpu_to_le16 (CDC_VENDOR_NUM),
 	.idProduct =		__constant_cpu_to_le16 (CDC_PRODUCT_NUM),
-	.iManufacturer =	STRING_MANUFACTURER,
-	.iProduct =		STRING_PRODUCT,
+	/* .bcdDevice = f(hardware) */
+	/* .iManufacturer = DYNAMIC */
+	/* .iProduct = DYNAMIC */
+	/* NO SERIAL NUMBER */
 	.bNumConfigurations =	1,
 };
 
-static struct usb_otg_descriptor
-otg_descriptor = {
+static struct usb_otg_descriptor otg_descriptor = {
 	.bLength =		sizeof otg_descriptor,
 	.bDescriptorType =	USB_DT_OTG,
 
-	.bmAttributes =		USB_OTG_SRP,
-};
-
-static struct usb_config_descriptor
-eth_config = {
-	.bLength =		sizeof eth_config,
-	.bDescriptorType =	USB_DT_CONFIG,
-
-	/* compute wTotalLength on the fly */
-	.bNumInterfaces =	2,
-	.bConfigurationValue =	DEV_CONFIG_VALUE,
-	.iConfiguration =	STRING_CDC,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =		50,
-};
-
-#ifdef	CONFIG_USB_ETH_RNDIS
-static struct usb_config_descriptor
-rndis_config = {
-	.bLength =              sizeof rndis_config,
-	.bDescriptorType =      USB_DT_CONFIG,
-
-	/* compute wTotalLength on the fly */
-	.bNumInterfaces =       2,
-	.bConfigurationValue =  DEV_RNDIS_CONFIG_VALUE,
-	.iConfiguration =       STRING_RNDIS,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =            50,
-};
-#endif
-
-/*
- * Compared to the simple CDC subset, the full CDC Ethernet model adds
- * three class descriptors, two interface descriptors, optional status
- * endpoint.  Both have a "data" interface and two bulk endpoints.
- * There are also differences in how control requests are handled.
- *
- * RNDIS shares a lot with CDC-Ethernet, since it's a variant of the
- * CDC-ACM (modem) spec.  Unfortunately MSFT's RNDIS driver is buggy; it
- * may hang or oops.  Since bugfixes (or accurate specs, letting Linux
- * work around those bugs) are unlikely to ever come from MSFT, you may
- * wish to avoid using RNDIS.
- *
- * MCCI offers an alternative to RNDIS if you need to connect to Windows
- * but have hardware that can't support CDC Ethernet.   We add descriptors
- * to present the CDC Subset as a (nonconformant) CDC MDLM variant called
- * "SAFE".  That borrows from both CDC Ethernet and CDC MDLM.  You can
- * get those drivers from MCCI, or bundled with various products.
- */
-
-#ifdef	DEV_CONFIG_CDC
-static struct usb_interface_descriptor
-control_intf = {
-	.bLength =		sizeof control_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	0,
-	/* status endpoint is optional; this may be patched later */
-	.bNumEndpoints =	1,
-	.bInterfaceClass =	USB_CLASS_COMM,
-	.bInterfaceSubClass =	USB_CDC_SUBCLASS_ETHERNET,
-	.bInterfaceProtocol =	USB_CDC_PROTO_NONE,
-	.iInterface =		STRING_CONTROL,
-};
-#endif
-
-#ifdef	CONFIG_USB_ETH_RNDIS
-static const struct usb_interface_descriptor
-rndis_control_intf = {
-	.bLength =              sizeof rndis_control_intf,
-	.bDescriptorType =      USB_DT_INTERFACE,
-
-	.bInterfaceNumber =     0,
-	.bNumEndpoints =        1,
-	.bInterfaceClass =      USB_CLASS_COMM,
-	.bInterfaceSubClass =   USB_CDC_SUBCLASS_ACM,
-	.bInterfaceProtocol =   USB_CDC_ACM_PROTO_VENDOR,
-	.iInterface =           STRING_RNDIS_CONTROL,
-};
-#endif
-
-static const struct usb_cdc_header_desc header_desc = {
-	.bLength =		sizeof header_desc,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
-
-	.bcdCDC =		__constant_cpu_to_le16 (0x0110),
-};
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-
-static const struct usb_cdc_union_desc union_desc = {
-	.bLength =		sizeof union_desc,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
-
-	.bMasterInterface0 =	0,	/* index of control interface */
-	.bSlaveInterface0 =	1,	/* index of DATA interface */
-};
-
-#endif	/* CDC || RNDIS */
-
-#ifdef	CONFIG_USB_ETH_RNDIS
-
-static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = {
-	.bLength =		sizeof call_mgmt_descriptor,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_CALL_MANAGEMENT_TYPE,
-
-	.bmCapabilities =	0x00,
-	.bDataInterface =	0x01,
-};
-
-static const struct usb_cdc_acm_descriptor acm_descriptor = {
-	.bLength =		sizeof acm_descriptor,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
-
-	.bmCapabilities =	0x00,
-};
-
-#endif
-
-#ifndef DEV_CONFIG_CDC
-
-/* "SAFE" loosely follows CDC WMC MDLM, violating the spec in various
- * ways:  data endpoints live in the control interface, there's no data
- * interface, and it's not used to talk to a cell phone radio.
- */
-
-static const struct usb_cdc_mdlm_desc mdlm_desc = {
-	.bLength =		sizeof mdlm_desc,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_MDLM_TYPE,
-
-	.bcdVersion =		__constant_cpu_to_le16(0x0100),
-	.bGUID = {
-		0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
-		0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
-	},
-};
-
-/* since "usb_cdc_mdlm_detail_desc" is a variable length structure, we
- * can't really use its struct.  All we do here is say that we're using
- * the submode of "SAFE" which directly matches the CDC Subset.
- */
-static const u8 mdlm_detail_desc[] = {
-	6,
-	USB_DT_CS_INTERFACE,
-	USB_CDC_MDLM_DETAIL_TYPE,
-
-	0,	/* "SAFE" */
-	0,	/* network control capabilities (none) */
-	0,	/* network data capabilities ("raw" encapsulation) */
-};
-
-#endif
-
-static const struct usb_cdc_ether_desc ether_desc = {
-	.bLength =		sizeof ether_desc,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_ETHERNET_TYPE,
-
-	/* this descriptor actually adds value, surprise! */
-	.iMACAddress =		STRING_ETHADDR,
-	.bmEthernetStatistics =	__constant_cpu_to_le32 (0), /* no statistics */
-	.wMaxSegmentSize =	__constant_cpu_to_le16 (ETH_FRAME_LEN),
-	.wNumberMCFilters =	__constant_cpu_to_le16 (0),
-	.bNumberPowerFilters =	0,
-};
-
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-
-/* include the status endpoint if we can, even where it's optional.
- * use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
- * packet, to simplify cancellation; and a big transfer interval, to
- * waste less bandwidth.
- *
- * some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even
- * if they ignore the connect/disconnect notifications that real aether
- * can provide.  more advanced cdc configurations might want to support
- * encapsulated commands (vendor-specific, using control-OUT).
- *
- * RNDIS requires the status endpoint, since it uses that encapsulation
- * mechanism for its funky RPC scheme.
- */
-
-#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
-#define STATUS_BYTECOUNT		16	/* 8 byte header + data */
-
-static struct usb_endpoint_descriptor
-fs_status_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (STATUS_BYTECOUNT),
-	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
-};
-#endif
-
-#ifdef	DEV_CONFIG_CDC
-
-/* the default data interface has no endpoints ... */
-
-static const struct usb_interface_descriptor
-data_nop_intf = {
-	.bLength =		sizeof data_nop_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	1,
-	.bAlternateSetting =	0,
-	.bNumEndpoints =	0,
-	.bInterfaceClass =	USB_CLASS_CDC_DATA,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-};
-
-/* ... but the "real" data interface has two bulk endpoints */
-
-static const struct usb_interface_descriptor
-data_intf = {
-	.bLength =		sizeof data_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	1,
-	.bAlternateSetting =	1,
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_CDC_DATA,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-	.iInterface =		STRING_DATA,
-};
-
-#endif
-
-#ifdef	CONFIG_USB_ETH_RNDIS
-
-/* RNDIS doesn't activate by changing to the "real" altsetting */
-
-static const struct usb_interface_descriptor
-rndis_data_intf = {
-	.bLength =		sizeof rndis_data_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	1,
-	.bAlternateSetting =	0,
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_CDC_DATA,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-	.iInterface =		STRING_DATA,
-};
-
-#endif
-
-#ifdef DEV_CONFIG_SUBSET
-
-/*
- * "Simple" CDC-subset option is a simple vendor-neutral model that most
- * full speed controllers can handle:  one interface, two bulk endpoints.
- *
- * To assist host side drivers, we fancy it up a bit, and add descriptors
- * so some host side drivers will understand it as a "SAFE" variant.
- */
-
-static const struct usb_interface_descriptor
-subset_data_intf = {
-	.bLength =		sizeof subset_data_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	0,
-	.bAlternateSetting =	0,
-	.bNumEndpoints =	2,
-	.bInterfaceClass =      USB_CLASS_COMM,
-	.bInterfaceSubClass =	USB_CDC_SUBCLASS_MDLM,
-	.bInterfaceProtocol =	0,
-	.iInterface =		STRING_DATA,
-};
-
-#endif	/* SUBSET */
-
-
-static struct usb_endpoint_descriptor
-fs_source_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_endpoint_descriptor
-fs_sink_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_OUT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	/* REVISIT SRP-only hardware is possible, although
+	 * it would not be called "OTG" ...
+	 */
+	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
 };
 
-static const struct usb_descriptor_header *fs_eth_function [11] = {
+static const struct usb_descriptor_header *otg_desc[] = {
 	(struct usb_descriptor_header *) &otg_descriptor,
-#ifdef DEV_CONFIG_CDC
-	/* "cdc" mode descriptors */
-	(struct usb_descriptor_header *) &control_intf,
-	(struct usb_descriptor_header *) &header_desc,
-	(struct usb_descriptor_header *) &union_desc,
-	(struct usb_descriptor_header *) &ether_desc,
-	/* NOTE: status endpoint may need to be removed */
-	(struct usb_descriptor_header *) &fs_status_desc,
-	/* data interface, with altsetting */
-	(struct usb_descriptor_header *) &data_nop_intf,
-	(struct usb_descriptor_header *) &data_intf,
-	(struct usb_descriptor_header *) &fs_source_desc,
-	(struct usb_descriptor_header *) &fs_sink_desc,
 	NULL,
-#endif /* DEV_CONFIG_CDC */
 };
 
-static inline void __init fs_subset_descriptors(void)
-{
-#ifdef DEV_CONFIG_SUBSET
-	/* behavior is "CDC Subset"; extra descriptors say "SAFE" */
-	fs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
-	fs_eth_function[2] = (struct usb_descriptor_header *) &header_desc;
-	fs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc;
-	fs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc;
-	fs_eth_function[5] = (struct usb_descriptor_header *) &ether_desc;
-	fs_eth_function[6] = (struct usb_descriptor_header *) &fs_source_desc;
-	fs_eth_function[7] = (struct usb_descriptor_header *) &fs_sink_desc;
-	fs_eth_function[8] = NULL;
-#else
-	fs_eth_function[1] = NULL;
-#endif
-}
 
-#ifdef	CONFIG_USB_ETH_RNDIS
-static const struct usb_descriptor_header *fs_rndis_function [] = {
-	(struct usb_descriptor_header *) &otg_descriptor,
-	/* control interface matches ACM, not Ethernet */
-	(struct usb_descriptor_header *) &rndis_control_intf,
-	(struct usb_descriptor_header *) &header_desc,
-	(struct usb_descriptor_header *) &call_mgmt_descriptor,
-	(struct usb_descriptor_header *) &acm_descriptor,
-	(struct usb_descriptor_header *) &union_desc,
-	(struct usb_descriptor_header *) &fs_status_desc,
-	/* data interface has no altsetting */
-	(struct usb_descriptor_header *) &rndis_data_intf,
-	(struct usb_descriptor_header *) &fs_source_desc,
-	(struct usb_descriptor_header *) &fs_sink_desc,
-	NULL,
-};
-#endif
-
-/*
- * usb 2.0 devices need to expose both high speed and full speed
- * descriptors, unless they only run at full speed.
- */
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-static struct usb_endpoint_descriptor
-hs_status_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (STATUS_BYTECOUNT),
-	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
-};
-#endif /* DEV_CONFIG_CDC */
-
-static struct usb_endpoint_descriptor
-hs_source_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
-};
-
-static struct usb_endpoint_descriptor
-hs_sink_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
-};
+/* string IDs are assigned dynamically */
 
-static struct usb_qualifier_descriptor
-dev_qualifier = {
-	.bLength =		sizeof dev_qualifier,
-	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
+#define STRING_MANUFACTURER_IDX		0
+#define STRING_PRODUCT_IDX		1
 
-	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
-	.bDeviceClass =		USB_CLASS_COMM,
+static char manufacturer[50];
 
-	.bNumConfigurations =	1,
+static struct usb_string strings_dev[] = {
+	[STRING_MANUFACTURER_IDX].s = manufacturer,
+	[STRING_PRODUCT_IDX].s = PREFIX DRIVER_DESC,
+	{  } /* end of list */
 };
 
-static const struct usb_descriptor_header *hs_eth_function [11] = {
-	(struct usb_descriptor_header *) &otg_descriptor,
-#ifdef DEV_CONFIG_CDC
-	/* "cdc" mode descriptors */
-	(struct usb_descriptor_header *) &control_intf,
-	(struct usb_descriptor_header *) &header_desc,
-	(struct usb_descriptor_header *) &union_desc,
-	(struct usb_descriptor_header *) &ether_desc,
-	/* NOTE: status endpoint may need to be removed */
-	(struct usb_descriptor_header *) &hs_status_desc,
-	/* data interface, with altsetting */
-	(struct usb_descriptor_header *) &data_nop_intf,
-	(struct usb_descriptor_header *) &data_intf,
-	(struct usb_descriptor_header *) &hs_source_desc,
-	(struct usb_descriptor_header *) &hs_sink_desc,
-	NULL,
-#endif /* DEV_CONFIG_CDC */
+static struct usb_gadget_strings stringtab_dev = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_dev,
 };
 
-static inline void __init hs_subset_descriptors(void)
-{
-#ifdef DEV_CONFIG_SUBSET
-	/* behavior is "CDC Subset"; extra descriptors say "SAFE" */
-	hs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
-	hs_eth_function[2] = (struct usb_descriptor_header *) &header_desc;
-	hs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc;
-	hs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc;
-	hs_eth_function[5] = (struct usb_descriptor_header *) &ether_desc;
-	hs_eth_function[6] = (struct usb_descriptor_header *) &hs_source_desc;
-	hs_eth_function[7] = (struct usb_descriptor_header *) &hs_sink_desc;
-	hs_eth_function[8] = NULL;
-#else
-	hs_eth_function[1] = NULL;
-#endif
-}
-
-#ifdef	CONFIG_USB_ETH_RNDIS
-static const struct usb_descriptor_header *hs_rndis_function [] = {
-	(struct usb_descriptor_header *) &otg_descriptor,
-	/* control interface matches ACM, not Ethernet */
-	(struct usb_descriptor_header *) &rndis_control_intf,
-	(struct usb_descriptor_header *) &header_desc,
-	(struct usb_descriptor_header *) &call_mgmt_descriptor,
-	(struct usb_descriptor_header *) &acm_descriptor,
-	(struct usb_descriptor_header *) &union_desc,
-	(struct usb_descriptor_header *) &hs_status_desc,
-	/* data interface has no altsetting */
-	(struct usb_descriptor_header *) &rndis_data_intf,
-	(struct usb_descriptor_header *) &hs_source_desc,
-	(struct usb_descriptor_header *) &hs_sink_desc,
+static struct usb_gadget_strings *dev_strings[] = {
+	&stringtab_dev,
 	NULL,
 };
-#endif
-
-
-/* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *
-ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
-		struct usb_endpoint_descriptor *fs)
-{
-	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
-		return hs;
-	return fs;
-}
 
+static u8 hostaddr[ETH_ALEN];
 
 /*-------------------------------------------------------------------------*/
 
-/* descriptors that are built on-demand */
-
-static char				manufacturer [50];
-static char				product_desc [40] = DRIVER_DESC;
-static char				serial_number [20];
-
-/* address that the host will use ... usually assigned at random */
-static char				ethaddr [2 * ETH_ALEN + 1];
-
-/* static strings, in UTF-8 */
-static struct usb_string		strings [] = {
-	{ STRING_MANUFACTURER,	manufacturer, },
-	{ STRING_PRODUCT,	product_desc, },
-	{ STRING_SERIALNUMBER,	serial_number, },
-	{ STRING_DATA,		"Ethernet Data", },
-	{ STRING_ETHADDR,	ethaddr, },
-#ifdef	DEV_CONFIG_CDC
-	{ STRING_CDC,		"CDC Ethernet", },
-	{ STRING_CONTROL,	"CDC Communications Control", },
-#endif
-#ifdef	DEV_CONFIG_SUBSET
-	{ STRING_SUBSET,	"CDC Ethernet Subset", },
-#endif
-#ifdef	CONFIG_USB_ETH_RNDIS
-	{ STRING_RNDIS,		"RNDIS", },
-	{ STRING_RNDIS_CONTROL,	"RNDIS Communications Control", },
-#endif
-	{  }		/* end of list */
-};
-
-static struct usb_gadget_strings	stringtab = {
-	.language	= 0x0409,	/* en-us */
-	.strings	= strings,
-};
-
 /*
- * one config, two interfaces:  control, data.
- * complications: class descriptors, and an altsetting.
- */
-static int
-config_buf(struct usb_gadget *g, u8 *buf, u8 type, unsigned index, int is_otg)
-{
-	int					len;
-	const struct usb_config_descriptor	*config;
-	const struct usb_descriptor_header	**function;
-	int					hs = 0;
-
-	if (gadget_is_dualspeed(g)) {
-		hs = (g->speed == USB_SPEED_HIGH);
-		if (type == USB_DT_OTHER_SPEED_CONFIG)
-			hs = !hs;
-	}
-#define which_fn(t)	(hs ? hs_ ## t ## _function : fs_ ## t ## _function)
-
-	if (index >= device_desc.bNumConfigurations)
-		return -EINVAL;
-
-#ifdef	CONFIG_USB_ETH_RNDIS
-	/* list the RNDIS config first, to make Microsoft's drivers
-	 * happy. DOCSIS 1.0 needs this too.
-	 */
-	if (device_desc.bNumConfigurations == 2 && index == 0) {
-		config = &rndis_config;
-		function = which_fn (rndis);
-	} else
-#endif
-	{
-		config = &eth_config;
-		function = which_fn (eth);
-	}
-
-	/* for now, don't advertise srp-only devices */
-	if (!is_otg)
-		function++;
-
-	len = usb_gadget_config_buf (config, buf, USB_BUFSIZ, function);
-	if (len < 0)
-		return len;
-	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
-	return len;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void eth_start (struct eth_dev *dev, gfp_t gfp_flags);
-static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags);
-
-static int
-set_ether_config (struct eth_dev *dev, gfp_t gfp_flags)
-{
-	int					result = 0;
-	struct usb_gadget			*gadget = dev->gadget;
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-	/* status endpoint used for RNDIS and (optionally) CDC */
-	if (!subset_active(dev) && dev->status_ep) {
-		dev->status = ep_desc (gadget, &hs_status_desc,
-						&fs_status_desc);
-		dev->status_ep->driver_data = dev;
-
-		result = usb_ep_enable (dev->status_ep, dev->status);
-		if (result != 0) {
-			DEBUG (dev, "enable %s --> %d\n",
-				dev->status_ep->name, result);
-			goto done;
-		}
-	}
-#endif
-
-	dev->in = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
-	dev->in_ep->driver_data = dev;
-
-	dev->out = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
-	dev->out_ep->driver_data = dev;
-
-	/* With CDC,  the host isn't allowed to use these two data
-	 * endpoints in the default altsetting for the interface.
-	 * so we don't activate them yet.  Reset from SET_INTERFACE.
-	 *
-	 * Strictly speaking RNDIS should work the same: activation is
-	 * a side effect of setting a packet filter.  Deactivation is
-	 * from REMOTE_NDIS_HALT_MSG, reset from REMOTE_NDIS_RESET_MSG.
-	 */
-	if (!cdc_active(dev)) {
-		result = usb_ep_enable (dev->in_ep, dev->in);
-		if (result != 0) {
-			DEBUG(dev, "enable %s --> %d\n",
-				dev->in_ep->name, result);
-			goto done;
-		}
-
-		result = usb_ep_enable (dev->out_ep, dev->out);
-		if (result != 0) {
-			DEBUG (dev, "enable %s --> %d\n",
-				dev->out_ep->name, result);
-			goto done;
-		}
-	}
-
-done:
-	if (result == 0)
-		result = alloc_requests (dev, qlen (gadget), gfp_flags);
-
-	/* on error, disable any endpoints  */
-	if (result < 0) {
-		if (!subset_active(dev) && dev->status_ep)
-			(void) usb_ep_disable (dev->status_ep);
-		dev->status = NULL;
-		(void) usb_ep_disable (dev->in_ep);
-		(void) usb_ep_disable (dev->out_ep);
-		dev->in = NULL;
-		dev->out = NULL;
-	}
-
-	/* activate non-CDC configs right away
-	 * this isn't strictly according to the RNDIS spec
-	 */
-	else if (!cdc_active (dev)) {
-		netif_carrier_on (dev->net);
-		if (netif_running (dev->net)) {
-			spin_unlock (&dev->lock);
-			eth_start (dev, GFP_ATOMIC);
-			spin_lock (&dev->lock);
-		}
-	}
-
-	if (result == 0)
-		DEBUG (dev, "qlen %d\n", qlen (gadget));
-
-	/* caller is responsible for cleanup on error */
-	return result;
-}
-
-static void eth_reset_config (struct eth_dev *dev)
-{
-	struct usb_request	*req;
-
-	if (dev->config == 0)
-		return;
-
-	DEBUG (dev, "%s\n", __func__);
-
-	netif_stop_queue (dev->net);
-	netif_carrier_off (dev->net);
-	rndis_uninit(dev->rndis_config);
-
-	/* disable endpoints, forcing (synchronous) completion of
-	 * pending i/o.  then free the requests.
-	 */
-	if (dev->in) {
-		usb_ep_disable (dev->in_ep);
-		spin_lock(&dev->req_lock);
-		while (likely (!list_empty (&dev->tx_reqs))) {
-			req = container_of (dev->tx_reqs.next,
-						struct usb_request, list);
-			list_del (&req->list);
-
-			spin_unlock(&dev->req_lock);
-			usb_ep_free_request (dev->in_ep, req);
-			spin_lock(&dev->req_lock);
-		}
-		spin_unlock(&dev->req_lock);
-	}
-	if (dev->out) {
-		usb_ep_disable (dev->out_ep);
-		spin_lock(&dev->req_lock);
-		while (likely (!list_empty (&dev->rx_reqs))) {
-			req = container_of (dev->rx_reqs.next,
-						struct usb_request, list);
-			list_del (&req->list);
-
-			spin_unlock(&dev->req_lock);
-			usb_ep_free_request (dev->out_ep, req);
-			spin_lock(&dev->req_lock);
-		}
-		spin_unlock(&dev->req_lock);
-	}
-
-	if (dev->status) {
-		usb_ep_disable (dev->status_ep);
-	}
-	dev->rndis = 0;
-	dev->cdc_filter = 0;
-	dev->config = 0;
-}
-
-/* change our operational config.  must agree with the code
- * that returns config descriptors, and altsetting code.
+ * We may not have an RNDIS configuration, but if we do it needs to be
+ * the first one present.  That's to make Microsoft's drivers happy,
+ * and to follow DOCSIS 1.0 (cable modem standard).
  */
-static int
-eth_set_config (struct eth_dev *dev, unsigned number, gfp_t gfp_flags)
+static int __init rndis_do_config(struct usb_configuration *c)
 {
-	int			result = 0;
-	struct usb_gadget	*gadget = dev->gadget;
-
-	if (gadget_is_sa1100 (gadget)
-			&& dev->config
-			&& atomic_read (&dev->tx_qlen) != 0) {
-		/* tx fifo is full, but we can't clear it...*/
-		INFO (dev, "can't change configurations\n");
-		return -ESPIPE;
-	}
-	eth_reset_config (dev);
-
-	switch (number) {
-	case DEV_CONFIG_VALUE:
-		result = set_ether_config (dev, gfp_flags);
-		break;
-#ifdef	CONFIG_USB_ETH_RNDIS
-	case DEV_RNDIS_CONFIG_VALUE:
-		dev->rndis = 1;
-		result = set_ether_config (dev, gfp_flags);
-		break;
-#endif
-	default:
-		result = -EINVAL;
-		/* FALL THROUGH */
-	case 0:
-		break;
-	}
-
-	if (result) {
-		if (number)
-			eth_reset_config (dev);
-		usb_gadget_vbus_draw(dev->gadget,
-				gadget_is_otg(dev->gadget) ? 8 : 100);
-	} else {
-		char *speed;
-		unsigned power;
-
-		power = 2 * eth_config.bMaxPower;
-		usb_gadget_vbus_draw(dev->gadget, power);
+	/* FIXME alloc iConfiguration string, set it in c->strings */
 
-		switch (gadget->speed) {
-		case USB_SPEED_FULL:	speed = "full"; break;
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-		case USB_SPEED_HIGH:	speed = "high"; break;
-#endif
-		default:		speed = "?"; break;
-		}
-
-		dev->config = number;
-		INFO (dev, "%s speed config #%d: %d mA, %s, using %s\n",
-				speed, number, power, driver_desc,
-				rndis_active(dev)
-					? "RNDIS"
-					: (cdc_active(dev)
-						? "CDC Ethernet"
-						: "CDC Ethernet Subset"));
+	if (gadget_is_otg(c->cdev->gadget)) {
+		c->descriptors = otg_desc;
+		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
-	return result;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	DEV_CONFIG_CDC
 
-/* The interrupt endpoint is used in CDC networking models (Ethernet, ATM)
- * only to notify the host about link status changes (which we support) or
- * report completion of some encapsulated command (as used in RNDIS).  Since
- * we want this CDC Ethernet code to be vendor-neutral, we don't use that
- * command mechanism; and only one status request is ever queued.
- */
-
-static void eth_status_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct usb_cdc_notification	*event = req->buf;
-	int				value = req->status;
-	struct eth_dev			*dev = ep->driver_data;
-
-	/* issue the second notification if host reads the first */
-	if (event->bNotificationType == USB_CDC_NOTIFY_NETWORK_CONNECTION
-			&& value == 0) {
-		__le32	*data = req->buf + sizeof *event;
-
-		event->bmRequestType = 0xA1;
-		event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
-		event->wValue = __constant_cpu_to_le16 (0);
-		event->wIndex = __constant_cpu_to_le16 (1);
-		event->wLength = __constant_cpu_to_le16 (8);
-
-		/* SPEED_CHANGE data is up/down speeds in bits/sec */
-		data [0] = data [1] = cpu_to_le32 (BITRATE (dev->gadget));
-
-		req->length = STATUS_BYTECOUNT;
-		value = usb_ep_queue (ep, req, GFP_ATOMIC);
-		DEBUG (dev, "send SPEED_CHANGE --> %d\n", value);
-		if (value == 0)
-			return;
-	} else if (value != -ECONNRESET)
-		DEBUG (dev, "event %02x --> %d\n",
-			event->bNotificationType, value);
-	req->context = NULL;
+	return rndis_bind_config(c, hostaddr);
 }
 
-static void issue_start_status (struct eth_dev *dev)
-{
-	struct usb_request		*req = dev->stat_req;
-	struct usb_cdc_notification	*event;
-	int				value;
-
-	DEBUG (dev, "%s, flush old status first\n", __func__);
-
-	/* flush old status
-	 *
-	 * FIXME ugly idiom, maybe we'd be better with just
-	 * a "cancel the whole queue" primitive since any
-	 * unlink-one primitive has way too many error modes.
-	 * here, we "know" toggle is already clear...
-	 *
-	 * FIXME iff req->context != null just dequeue it
-	 */
-	usb_ep_disable (dev->status_ep);
-	usb_ep_enable (dev->status_ep, dev->status);
-
-	/* 3.8.1 says to issue first NETWORK_CONNECTION, then
-	 * a SPEED_CHANGE.  could be useful in some configs.
-	 */
-	event = req->buf;
-	event->bmRequestType = 0xA1;
-	event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
-	event->wValue = __constant_cpu_to_le16 (1);	/* connected */
-	event->wIndex = __constant_cpu_to_le16 (1);
-	event->wLength = 0;
-
-	req->length = sizeof *event;
-	req->complete = eth_status_complete;
-	req->context = dev;
-
-	value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC);
-	if (value < 0)
-		DEBUG (dev, "status buf queue --> %d\n", value);
-}
-
-#endif
+static struct usb_configuration rndis_config_driver = {
+	.label			= "RNDIS",
+	.bind			= rndis_do_config,
+	.bConfigurationValue	= 2,
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower		= 1,	/* 2 mA, minimal */
+};
 
 /*-------------------------------------------------------------------------*/
 
-static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	if (req->status || req->actual != req->length)
-		DEBUG ((struct eth_dev *) ep->driver_data,
-				"setup complete --> %d, %d/%d\n",
-				req->status, req->actual, req->length);
-}
-
-#ifdef CONFIG_USB_ETH_RNDIS
-
-static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	if (req->status || req->actual != req->length)
-		DEBUG ((struct eth_dev *) ep->driver_data,
-			"rndis response complete --> %d, %d/%d\n",
-			req->status, req->actual, req->length);
-
-	/* done sending after USB_CDC_GET_ENCAPSULATED_RESPONSE */
-}
-
-static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct eth_dev          *dev = ep->driver_data;
-	int			status;
-
-	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
-	spin_lock(&dev->lock);
-	status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
-	if (status < 0)
-		ERROR(dev, "%s: rndis parse error %d\n", __func__, status);
-	spin_unlock(&dev->lock);
-}
-
-#endif	/* RNDIS */
-
 /*
- * The setup() callback implements all the ep0 functionality that's not
- * handled lower down.  CDC has a number of less-common features:
- *
- *  - two interfaces:  control, and ethernet data
- *  - Ethernet data interface has two altsettings:  default, and active
- *  - class-specific descriptors for the control interface
- *  - class-specific control requests
+ * We _always_ have an ECM or CDC Subset configuration.
  */
-static int
-eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+static int __init eth_do_config(struct usb_configuration *c)
 {
-	struct eth_dev		*dev = get_gadget_data (gadget);
-	struct usb_request	*req = dev->req;
-	int			value = -EOPNOTSUPP;
-	u16			wIndex = le16_to_cpu(ctrl->wIndex);
-	u16			wValue = le16_to_cpu(ctrl->wValue);
-	u16			wLength = le16_to_cpu(ctrl->wLength);
-
-	/* descriptors just go into the pre-allocated ep0 buffer,
-	 * while config change events may enable network traffic.
-	 */
-	req->complete = eth_setup_complete;
-	switch (ctrl->bRequest) {
-
-	case USB_REQ_GET_DESCRIPTOR:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			break;
-		switch (wValue >> 8) {
-
-		case USB_DT_DEVICE:
-			value = min (wLength, (u16) sizeof device_desc);
-			memcpy (req->buf, &device_desc, value);
-			break;
-		case USB_DT_DEVICE_QUALIFIER:
-			if (!gadget_is_dualspeed(gadget))
-				break;
-			value = min (wLength, (u16) sizeof dev_qualifier);
-			memcpy (req->buf, &dev_qualifier, value);
-			break;
-
-		case USB_DT_OTHER_SPEED_CONFIG:
-			if (!gadget_is_dualspeed(gadget))
-				break;
-			// FALLTHROUGH
-		case USB_DT_CONFIG:
-			value = config_buf(gadget, req->buf,
-					wValue >> 8,
-					wValue & 0xff,
-					gadget_is_otg(gadget));
-			if (value >= 0)
-				value = min (wLength, (u16) value);
-			break;
-
-		case USB_DT_STRING:
-			value = usb_gadget_get_string (&stringtab,
-					wValue & 0xff, req->buf);
-			if (value >= 0)
-				value = min (wLength, (u16) value);
-			break;
-		}
-		break;
-
-	case USB_REQ_SET_CONFIGURATION:
-		if (ctrl->bRequestType != 0)
-			break;
-		if (gadget->a_hnp_support)
-			DEBUG (dev, "HNP available\n");
-		else if (gadget->a_alt_hnp_support)
-			DEBUG (dev, "HNP needs a different root port\n");
-		spin_lock (&dev->lock);
-		value = eth_set_config (dev, wValue, GFP_ATOMIC);
-		spin_unlock (&dev->lock);
-		break;
-	case USB_REQ_GET_CONFIGURATION:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			break;
-		*(u8 *)req->buf = dev->config;
-		value = min (wLength, (u16) 1);
-		break;
-
-	case USB_REQ_SET_INTERFACE:
-		if (ctrl->bRequestType != USB_RECIP_INTERFACE
-				|| !dev->config
-				|| wIndex > 1)
-			break;
-		if (!cdc_active(dev) && wIndex != 0)
-			break;
-		spin_lock (&dev->lock);
-
-		/* PXA hardware partially handles SET_INTERFACE;
-		 * we need to kluge around that interference.
-		 */
-		if (gadget_is_pxa (gadget)) {
-			value = eth_set_config (dev, DEV_CONFIG_VALUE,
-						GFP_ATOMIC);
-			goto done_set_intf;
-		}
-
-#ifdef DEV_CONFIG_CDC
-		switch (wIndex) {
-		case 0:		/* control/master intf */
-			if (wValue != 0)
-				break;
-			if (dev->status) {
-				usb_ep_disable (dev->status_ep);
-				usb_ep_enable (dev->status_ep, dev->status);
-			}
-			value = 0;
-			break;
-		case 1:		/* data intf */
-			if (wValue > 1)
-				break;
-			usb_ep_disable (dev->in_ep);
-			usb_ep_disable (dev->out_ep);
-
-			/* CDC requires the data transfers not be done from
-			 * the default interface setting ... also, setting
-			 * the non-default interface resets filters etc.
-			 */
-			if (wValue == 1) {
-				if (!cdc_active (dev))
-					break;
-				usb_ep_enable (dev->in_ep, dev->in);
-				usb_ep_enable (dev->out_ep, dev->out);
-				dev->cdc_filter = DEFAULT_FILTER;
-				netif_carrier_on (dev->net);
-				if (dev->status)
-					issue_start_status (dev);
-				if (netif_running (dev->net)) {
-					spin_unlock (&dev->lock);
-					eth_start (dev, GFP_ATOMIC);
-					spin_lock (&dev->lock);
-				}
-			} else {
-				netif_stop_queue (dev->net);
-				netif_carrier_off (dev->net);
-			}
-			value = 0;
-			break;
-		}
-#else
-		/* FIXME this is wrong, as is the assumption that
-		 * all non-PXA hardware talks real CDC ...
-		 */
-		dev_warn (&gadget->dev, "set_interface ignored!\n");
-#endif /* DEV_CONFIG_CDC */
-
-done_set_intf:
-		spin_unlock (&dev->lock);
-		break;
-	case USB_REQ_GET_INTERFACE:
-		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)
-				|| !dev->config
-				|| wIndex > 1)
-			break;
-		if (!(cdc_active(dev) || rndis_active(dev)) && wIndex != 0)
-			break;
-
-		/* for CDC, iff carrier is on, data interface is active. */
-		if (rndis_active(dev) || wIndex != 1)
-			*(u8 *)req->buf = 0;
-		else
-			*(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0;
-		value = min (wLength, (u16) 1);
-		break;
-
-#ifdef DEV_CONFIG_CDC
-	case USB_CDC_SET_ETHERNET_PACKET_FILTER:
-		/* see 6.2.30: no data, wIndex = interface,
-		 * wValue = packet filter bitmap
-		 */
-		if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
-				|| !cdc_active(dev)
-				|| wLength != 0
-				|| wIndex > 1)
-			break;
-		DEBUG (dev, "packet filter %02x\n", wValue);
-		dev->cdc_filter = wValue;
-		value = 0;
-		break;
-
-	/* and potentially:
-	 * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
-	 * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
-	 * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
-	 * case USB_CDC_GET_ETHERNET_STATISTIC:
-	 */
-
-#endif /* DEV_CONFIG_CDC */
+	/* FIXME alloc iConfiguration string, set it in c->strings */
 
-#ifdef CONFIG_USB_ETH_RNDIS
-	/* RNDIS uses the CDC command encapsulation mechanism to implement
-	 * an RPC scheme, with much getting/setting of attributes by OID.
-	 */
-	case USB_CDC_SEND_ENCAPSULATED_COMMAND:
-		if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
-				|| !rndis_active(dev)
-				|| wLength > USB_BUFSIZ
-				|| wValue
-				|| rndis_control_intf.bInterfaceNumber
-					!= wIndex)
-			break;
-		/* read the request, then process it */
-		value = wLength;
-		req->complete = rndis_command_complete;
-		/* later, rndis_control_ack () sends a notification */
-		break;
-
-	case USB_CDC_GET_ENCAPSULATED_RESPONSE:
-		if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)
-					== ctrl->bRequestType
-				&& rndis_active(dev)
-				// && wLength >= 0x0400
-				&& !wValue
-				&& rndis_control_intf.bInterfaceNumber
-					== wIndex) {
-			u8 *buf;
-			u32 n;
-
-			/* return the result */
-			buf = rndis_get_next_response(dev->rndis_config, &n);
-			if (buf) {
-				memcpy(req->buf, buf, n);
-				req->complete = rndis_response_complete;
-				rndis_free_response(dev->rndis_config, buf);
-				value = n;
-			}
-			/* else stalls ... spec says to avoid that */
-		}
-		break;
-#endif	/* RNDIS */
-
-	default:
-		VDEBUG (dev,
-			"unknown control req%02x.%02x v%04x i%04x l%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			wValue, wIndex, wLength);
+	if (gadget_is_otg(c->cdev->gadget)) {
+		c->descriptors = otg_desc;
+		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	/* respond with data transfer before status phase? */
-	if (value >= 0) {
-		req->length = value;
-		req->zero = value < wLength
-				&& (value % gadget->ep0->maxpacket) == 0;
-		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
-		if (value < 0) {
-			DEBUG (dev, "ep_queue --> %d\n", value);
-			req->status = 0;
-			eth_setup_complete (gadget->ep0, req);
-		}
-	}
-
-	/* host either stalls (value < 0) or reports success */
-	return value;
-}
-
-static void
-eth_disconnect (struct usb_gadget *gadget)
-{
-	struct eth_dev		*dev = get_gadget_data (gadget);
-	unsigned long		flags;
-
-	spin_lock_irqsave (&dev->lock, flags);
-	netif_stop_queue (dev->net);
-	netif_carrier_off (dev->net);
-	eth_reset_config (dev);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	/* FIXME RNDIS should enter RNDIS_UNINITIALIZED */
-
-	/* next we may get setup() calls to enumerate new connections;
-	 * or an unbind() during shutdown (including removing module).
-	 */
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* NETWORK DRIVER HOOKUP (to the layer above this driver) */
-
-static int eth_change_mtu (struct net_device *net, int new_mtu)
-{
-	struct eth_dev	*dev = netdev_priv(net);
-
-	if (dev->rndis)
-		return -EBUSY;
-
-	if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN)
-		return -ERANGE;
-	/* no zero-length packet read wanted after mtu-sized packets */
-	if (((new_mtu + sizeof (struct ethhdr)) % dev->in_ep->maxpacket) == 0)
-		return -EDOM;
-	net->mtu = new_mtu;
-	return 0;
-}
-
-static struct net_device_stats *eth_get_stats (struct net_device *net)
-{
-	return &((struct eth_dev *)netdev_priv(net))->stats;
-}
-
-static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
-{
-	struct eth_dev	*dev = netdev_priv(net);
-	strlcpy(p->driver, shortname, sizeof p->driver);
-	strlcpy(p->version, DRIVER_VERSION, sizeof p->version);
-	strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version);
-	strlcpy (p->bus_info, dev->gadget->dev.bus_id, sizeof p->bus_info);
-}
-
-static u32 eth_get_link(struct net_device *net)
-{
-	struct eth_dev	*dev = netdev_priv(net);
-	return dev->gadget->speed != USB_SPEED_UNKNOWN;
-}
-
-static struct ethtool_ops ops = {
-	.get_drvinfo = eth_get_drvinfo,
-	.get_link = eth_get_link
-};
-
-static void defer_kevent (struct eth_dev *dev, int flag)
-{
-	if (test_and_set_bit (flag, &dev->todo))
-		return;
-	if (!schedule_work (&dev->work))
-		ERROR (dev, "kevent %d may have been dropped\n", flag);
+	if (can_support_ecm(c->cdev->gadget))
+		return ecm_bind_config(c, hostaddr);
 	else
-		DEBUG (dev, "kevent %d scheduled\n", flag);
-}
-
-static void rx_complete (struct usb_ep *ep, struct usb_request *req);
-
-static int
-rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
-{
-	struct sk_buff		*skb;
-	int			retval = -ENOMEM;
-	size_t			size;
-
-	/* Padding up to RX_EXTRA handles minor disagreements with host.
-	 * Normally we use the USB "terminate on short read" convention;
-	 * so allow up to (N*maxpacket), since that memory is normally
-	 * already allocated.  Some hardware doesn't deal well with short
-	 * reads (e.g. DMA must be N*maxpacket), so for now don't trim a
-	 * byte off the end (to force hardware errors on overflow).
-	 *
-	 * RNDIS uses internal framing, and explicitly allows senders to
-	 * pad to end-of-packet.  That's potentially nice for speed,
-	 * but means receivers can't recover synch on their own.
-	 */
-	size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA);
-	size += dev->out_ep->maxpacket - 1;
-	if (rndis_active(dev))
-		size += sizeof (struct rndis_packet_msg_type);
-	size -= size % dev->out_ep->maxpacket;
-
-	skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
-	if (skb == NULL) {
-		DEBUG (dev, "no rx skb\n");
-		goto enomem;
-	}
-
-	/* Some platforms perform better when IP packets are aligned,
-	 * but on at least one, checksumming fails otherwise.  Note:
-	 * RNDIS headers involve variable numbers of LE32 values.
-	 */
-	skb_reserve(skb, NET_IP_ALIGN);
-
-	req->buf = skb->data;
-	req->length = size;
-	req->complete = rx_complete;
-	req->context = skb;
-
-	retval = usb_ep_queue (dev->out_ep, req, gfp_flags);
-	if (retval == -ENOMEM)
-enomem:
-		defer_kevent (dev, WORK_RX_MEMORY);
-	if (retval) {
-		DEBUG (dev, "rx submit --> %d\n", retval);
-		if (skb)
-			dev_kfree_skb_any(skb);
-		spin_lock(&dev->req_lock);
-		list_add (&req->list, &dev->rx_reqs);
-		spin_unlock(&dev->req_lock);
-	}
-	return retval;
-}
-
-static void rx_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct sk_buff	*skb = req->context;
-	struct eth_dev	*dev = ep->driver_data;
-	int		status = req->status;
-
-	switch (status) {
-
-	/* normal completion */
-	case 0:
-		skb_put (skb, req->actual);
-		/* we know MaxPacketsPerTransfer == 1 here */
-		if (rndis_active(dev))
-			status = rndis_rm_hdr (skb);
-		if (status < 0
-				|| ETH_HLEN > skb->len
-				|| skb->len > ETH_FRAME_LEN) {
-			dev->stats.rx_errors++;
-			dev->stats.rx_length_errors++;
-			DEBUG (dev, "rx length %d\n", skb->len);
-			break;
-		}
-
-		skb->protocol = eth_type_trans (skb, dev->net);
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += skb->len;
-
-		/* no buffer copies needed, unless hardware can't
-		 * use skb buffers.
-		 */
-		status = netif_rx (skb);
-		skb = NULL;
-		break;
-
-	/* software-driven interface shutdown */
-	case -ECONNRESET:		// unlink
-	case -ESHUTDOWN:		// disconnect etc
-		VDEBUG (dev, "rx shutdown, code %d\n", status);
-		goto quiesce;
-
-	/* for hardware automagic (such as pxa) */
-	case -ECONNABORTED:		// endpoint reset
-		DEBUG (dev, "rx %s reset\n", ep->name);
-		defer_kevent (dev, WORK_RX_MEMORY);
-quiesce:
-		dev_kfree_skb_any (skb);
-		goto clean;
-
-	/* data overrun */
-	case -EOVERFLOW:
-		dev->stats.rx_over_errors++;
-		// FALLTHROUGH
-
-	default:
-		dev->stats.rx_errors++;
-		DEBUG (dev, "rx status %d\n", status);
-		break;
-	}
-
-	if (skb)
-		dev_kfree_skb_any (skb);
-	if (!netif_running (dev->net)) {
-clean:
-		spin_lock(&dev->req_lock);
-		list_add (&req->list, &dev->rx_reqs);
-		spin_unlock(&dev->req_lock);
-		req = NULL;
-	}
-	if (req)
-		rx_submit (dev, req, GFP_ATOMIC);
-}
-
-static int prealloc (struct list_head *list, struct usb_ep *ep,
-			unsigned n, gfp_t gfp_flags)
-{
-	unsigned		i;
-	struct usb_request	*req;
-
-	if (!n)
-		return -ENOMEM;
-
-	/* queue/recycle up to N requests */
-	i = n;
-	list_for_each_entry (req, list, list) {
-		if (i-- == 0)
-			goto extra;
-	}
-	while (i--) {
-		req = usb_ep_alloc_request (ep, gfp_flags);
-		if (!req)
-			return list_empty (list) ? -ENOMEM : 0;
-		list_add (&req->list, list);
-	}
-	return 0;
-
-extra:
-	/* free extras */
-	for (;;) {
-		struct list_head	*next;
-
-		next = req->list.next;
-		list_del (&req->list);
-		usb_ep_free_request (ep, req);
-
-		if (next == list)
-			break;
-
-		req = container_of (next, struct usb_request, list);
-	}
-	return 0;
-}
-
-static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags)
-{
-	int status;
-
-	spin_lock(&dev->req_lock);
-	status = prealloc (&dev->tx_reqs, dev->in_ep, n, gfp_flags);
-	if (status < 0)
-		goto fail;
-	status = prealloc (&dev->rx_reqs, dev->out_ep, n, gfp_flags);
-	if (status < 0)
-		goto fail;
-	goto done;
-fail:
-	DEBUG (dev, "can't alloc requests\n");
-done:
-	spin_unlock(&dev->req_lock);
-	return status;
-}
-
-static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags)
-{
-	struct usb_request	*req;
-	unsigned long		flags;
-
-	/* fill unused rxq slots with some skb */
-	spin_lock_irqsave(&dev->req_lock, flags);
-	while (!list_empty (&dev->rx_reqs)) {
-		req = container_of (dev->rx_reqs.next,
-				struct usb_request, list);
-		list_del_init (&req->list);
-		spin_unlock_irqrestore(&dev->req_lock, flags);
-
-		if (rx_submit (dev, req, gfp_flags) < 0) {
-			defer_kevent (dev, WORK_RX_MEMORY);
-			return;
-		}
-
-		spin_lock_irqsave(&dev->req_lock, flags);
-	}
-	spin_unlock_irqrestore(&dev->req_lock, flags);
-}
-
-static void eth_work (struct work_struct *work)
-{
-	struct eth_dev	*dev = container_of(work, struct eth_dev, work);
-
-	if (test_and_clear_bit (WORK_RX_MEMORY, &dev->todo)) {
-		if (netif_running (dev->net))
-			rx_fill (dev, GFP_KERNEL);
-	}
-
-	if (dev->todo)
-		DEBUG (dev, "work done, flags = 0x%lx\n", dev->todo);
-}
-
-static void tx_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct sk_buff	*skb = req->context;
-	struct eth_dev	*dev = ep->driver_data;
-
-	switch (req->status) {
-	default:
-		dev->stats.tx_errors++;
-		VDEBUG (dev, "tx err %d\n", req->status);
-		/* FALLTHROUGH */
-	case -ECONNRESET:		// unlink
-	case -ESHUTDOWN:		// disconnect etc
-		break;
-	case 0:
-		dev->stats.tx_bytes += skb->len;
-	}
-	dev->stats.tx_packets++;
-
-	spin_lock(&dev->req_lock);
-	list_add (&req->list, &dev->tx_reqs);
-	spin_unlock(&dev->req_lock);
-	dev_kfree_skb_any (skb);
-
-	atomic_dec (&dev->tx_qlen);
-	if (netif_carrier_ok (dev->net))
-		netif_wake_queue (dev->net);
-}
-
-static inline int eth_is_promisc (struct eth_dev *dev)
-{
-	/* no filters for the CDC subset; always promisc */
-	if (subset_active (dev))
-		return 1;
-	return dev->cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
-}
-
-static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
-{
-	struct eth_dev		*dev = netdev_priv(net);
-	int			length = skb->len;
-	int			retval;
-	struct usb_request	*req = NULL;
-	unsigned long		flags;
-
-	/* apply outgoing CDC or RNDIS filters */
-	if (!eth_is_promisc (dev)) {
-		u8		*dest = skb->data;
-
-		if (is_multicast_ether_addr(dest)) {
-			u16	type;
-
-			/* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
-			 * SET_ETHERNET_MULTICAST_FILTERS requests
-			 */
-			if (is_broadcast_ether_addr(dest))
-				type = USB_CDC_PACKET_TYPE_BROADCAST;
-			else
-				type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
-			if (!(dev->cdc_filter & type)) {
-				dev_kfree_skb_any (skb);
-				return 0;
-			}
-		}
-		/* ignores USB_CDC_PACKET_TYPE_DIRECTED */
-	}
-
-	spin_lock_irqsave(&dev->req_lock, flags);
-	/*
-	 * this freelist can be empty if an interrupt triggered disconnect()
-	 * and reconfigured the gadget (shutting down this queue) after the
-	 * network stack decided to xmit but before we got the spinlock.
-	 */
-	if (list_empty(&dev->tx_reqs)) {
-		spin_unlock_irqrestore(&dev->req_lock, flags);
-		return 1;
-	}
-
-	req = container_of (dev->tx_reqs.next, struct usb_request, list);
-	list_del (&req->list);
-
-	/* temporarily stop TX queue when the freelist empties */
-	if (list_empty (&dev->tx_reqs))
-		netif_stop_queue (net);
-	spin_unlock_irqrestore(&dev->req_lock, flags);
-
-	/* no buffer copies needed, unless the network stack did it
-	 * or the hardware can't use skb buffers.
-	 * or there's not enough space for any RNDIS headers we need
-	 */
-	if (rndis_active(dev)) {
-		struct sk_buff	*skb_rndis;
-
-		skb_rndis = skb_realloc_headroom (skb,
-				sizeof (struct rndis_packet_msg_type));
-		if (!skb_rndis)
-			goto drop;
-
-		dev_kfree_skb_any (skb);
-		skb = skb_rndis;
-		rndis_add_hdr (skb);
-		length = skb->len;
-	}
-	req->buf = skb->data;
-	req->context = skb;
-	req->complete = tx_complete;
-
-	/* use zlp framing on tx for strict CDC-Ether conformance,
-	 * though any robust network rx path ignores extra padding.
-	 * and some hardware doesn't like to write zlps.
-	 */
-	req->zero = 1;
-	if (!dev->zlp && (length % dev->in_ep->maxpacket) == 0)
-		length++;
-
-	req->length = length;
-
-	/* throttle highspeed IRQ rate back slightly */
-	if (gadget_is_dualspeed(dev->gadget))
-		req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
-			? ((atomic_read(&dev->tx_qlen) % qmult) != 0)
-			: 0;
-
-	retval = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC);
-	switch (retval) {
-	default:
-		DEBUG (dev, "tx queue err %d\n", retval);
-		break;
-	case 0:
-		net->trans_start = jiffies;
-		atomic_inc (&dev->tx_qlen);
-	}
-
-	if (retval) {
-drop:
-		dev->stats.tx_dropped++;
-		dev_kfree_skb_any (skb);
-		spin_lock_irqsave(&dev->req_lock, flags);
-		if (list_empty (&dev->tx_reqs))
-			netif_start_queue (net);
-		list_add (&req->list, &dev->tx_reqs);
-		spin_unlock_irqrestore(&dev->req_lock, flags);
-	}
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_USB_ETH_RNDIS
-
-/* The interrupt endpoint is used in RNDIS to notify the host when messages
- * other than data packets are available ... notably the REMOTE_NDIS_*_CMPLT
- * messages, but also REMOTE_NDIS_INDICATE_STATUS_MSG and potentially even
- * REMOTE_NDIS_KEEPALIVE_MSG.
- *
- * The RNDIS control queue is processed by GET_ENCAPSULATED_RESPONSE, and
- * normally just one notification will be queued.
- */
-
-static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, gfp_t);
-static void eth_req_free (struct usb_ep *ep, struct usb_request *req);
-
-static void
-rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct eth_dev          *dev = ep->driver_data;
-
-	if (req->status || req->actual != req->length)
-		DEBUG (dev,
-			"rndis control ack complete --> %d, %d/%d\n",
-			req->status, req->actual, req->length);
-	req->context = NULL;
-
-	if (req != dev->stat_req)
-		eth_req_free(ep, req);
-}
-
-static int rndis_control_ack (struct net_device *net)
-{
-	struct eth_dev          *dev = netdev_priv(net);
-	int                     length;
-	struct usb_request      *resp = dev->stat_req;
-
-	/* in case RNDIS calls this after disconnect */
-	if (!dev->status) {
-		DEBUG (dev, "status ENODEV\n");
-		return -ENODEV;
-	}
-
-	/* in case queue length > 1 */
-	if (resp->context) {
-		resp = eth_req_alloc (dev->status_ep, 8, GFP_ATOMIC);
-		if (!resp)
-			return -ENOMEM;
-	}
-
-	/* Send RNDIS RESPONSE_AVAILABLE notification;
-	 * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too
-	 */
-	resp->length = 8;
-	resp->complete = rndis_control_ack_complete;
-	resp->context = dev;
-
-	*((__le32 *) resp->buf) = __constant_cpu_to_le32 (1);
-	*((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);
-
-	length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC);
-	if (length < 0) {
-		resp->status = 0;
-		rndis_control_ack_complete (dev->status_ep, resp);
-	}
-
-	return 0;
-}
-
-#else
-
-#define	rndis_control_ack	NULL
-
-#endif	/* RNDIS */
-
-static void eth_start (struct eth_dev *dev, gfp_t gfp_flags)
-{
-	DEBUG (dev, "%s\n", __func__);
-
-	/* fill the rx queue */
-	rx_fill (dev, gfp_flags);
-
-	/* and open the tx floodgates */
-	atomic_set (&dev->tx_qlen, 0);
-	netif_wake_queue (dev->net);
-	if (rndis_active(dev)) {
-		rndis_set_param_medium (dev->rndis_config,
-					NDIS_MEDIUM_802_3,
-					BITRATE(dev->gadget)/100);
-		(void) rndis_signal_connect (dev->rndis_config);
-	}
-}
-
-static int eth_open (struct net_device *net)
-{
-	struct eth_dev		*dev = netdev_priv(net);
-
-	DEBUG (dev, "%s\n", __func__);
-	if (netif_carrier_ok (dev->net))
-		eth_start (dev, GFP_KERNEL);
-	return 0;
+		return geth_bind_config(c, hostaddr);
 }
 
-static int eth_stop (struct net_device *net)
-{
-	struct eth_dev		*dev = netdev_priv(net);
-
-	VDEBUG (dev, "%s\n", __func__);
-	netif_stop_queue (net);
-
-	DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
-		dev->stats.rx_packets, dev->stats.tx_packets,
-		dev->stats.rx_errors, dev->stats.tx_errors
-		);
-
-	/* ensure there are no more active requests */
-	if (dev->config) {
-		usb_ep_disable (dev->in_ep);
-		usb_ep_disable (dev->out_ep);
-		if (netif_carrier_ok (dev->net)) {
-			DEBUG (dev, "host still using in/out endpoints\n");
-			// FIXME idiom may leave toggle wrong here
-			usb_ep_enable (dev->in_ep, dev->in);
-			usb_ep_enable (dev->out_ep, dev->out);
-		}
-		if (dev->status_ep) {
-			usb_ep_disable (dev->status_ep);
-			usb_ep_enable (dev->status_ep, dev->status);
-		}
-	}
-
-	if (rndis_active(dev)) {
-		rndis_set_param_medium(dev->rndis_config, NDIS_MEDIUM_802_3, 0);
-		(void) rndis_signal_disconnect (dev->rndis_config);
-	}
-
-	return 0;
-}
+static struct usb_configuration eth_config_driver = {
+	/* .label = f(hardware) */
+	.bind			= eth_do_config,
+	.bConfigurationValue	= 1,
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower		= 1,	/* 2 mA, minimal */
+};
 
 /*-------------------------------------------------------------------------*/
 
-static struct usb_request *
-eth_req_alloc (struct usb_ep *ep, unsigned size, gfp_t gfp_flags)
+static int __init eth_bind(struct usb_composite_dev *cdev)
 {
-	struct usb_request	*req;
-
-	req = usb_ep_alloc_request (ep, gfp_flags);
-	if (!req)
-		return NULL;
-
-	req->buf = kmalloc (size, gfp_flags);
-	if (!req->buf) {
-		usb_ep_free_request (ep, req);
-		req = NULL;
-	}
-	return req;
-}
-
-static void
-eth_req_free (struct usb_ep *ep, struct usb_request *req)
-{
-	kfree (req->buf);
-	usb_ep_free_request (ep, req);
-}
-
-
-static void /* __init_or_exit */
-eth_unbind (struct usb_gadget *gadget)
-{
-	struct eth_dev		*dev = get_gadget_data (gadget);
-
-	DEBUG (dev, "unbind\n");
-	rndis_deregister (dev->rndis_config);
-	rndis_exit ();
-
-	/* we've already been disconnected ... no i/o is active */
-	if (dev->req) {
-		eth_req_free (gadget->ep0, dev->req);
-		dev->req = NULL;
-	}
-	if (dev->stat_req) {
-		eth_req_free (dev->status_ep, dev->stat_req);
-		dev->stat_req = NULL;
-	}
-
-	unregister_netdev (dev->net);
-	free_netdev(dev->net);
-
-	/* assuming we used keventd, it must quiesce too */
-	flush_scheduled_work ();
-	set_gadget_data (gadget, NULL);
-}
-
-static u8 __init nibble (unsigned char c)
-{
-	if (likely (isdigit (c)))
-		return c - '0';
-	c = toupper (c);
-	if (likely (isxdigit (c)))
-		return 10 + c - 'A';
-	return 0;
-}
+	int			gcnum;
+	struct usb_gadget	*gadget = cdev->gadget;
+	int			status;
 
-static int __init get_ether_addr(const char *str, u8 *dev_addr)
-{
-	if (str) {
-		unsigned	i;
+	/* set up network link layer */
+	status = gether_setup(cdev->gadget, hostaddr);
+	if (status < 0)
+		return status;
 
-		for (i = 0; i < 6; i++) {
-			unsigned char num;
+	/* set up main config label and device descriptor */
+	if (can_support_ecm(cdev->gadget)) {
+		/* ECM */
+		eth_config_driver.label = "CDC Ethernet (ECM)";
+	} else {
+		/* CDC Subset */
+		eth_config_driver.label = "CDC Subset/SAFE";
 
-			if((*str == '.') || (*str == ':'))
-				str++;
-			num = nibble(*str++) << 4;
-			num |= (nibble(*str++));
-			dev_addr [i] = num;
-		}
-		if (is_valid_ether_addr (dev_addr))
-			return 0;
+		device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM),
+		device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM),
+		device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
 	}
-	random_ether_addr(dev_addr);
-	return 1;
-}
-
-static int __init
-eth_bind (struct usb_gadget *gadget)
-{
-	struct eth_dev		*dev;
-	struct net_device	*net;
-	u8			cdc = 1, zlp = 1, rndis = 1;
-	struct usb_ep		*in_ep, *out_ep, *status_ep = NULL;
-	int			status = -ENOMEM;
-	int			gcnum;
-
-	/* these flags are only ever cleared; compiler take note */
-#ifndef	DEV_CONFIG_CDC
-	cdc = 0;
-#endif
-#ifndef	CONFIG_USB_ETH_RNDIS
-	rndis = 0;
-#endif
 
-	/* Because most host side USB stacks handle CDC Ethernet, that
-	 * standard protocol is _strongly_ preferred for interop purposes.
-	 * (By everyone except Microsoft.)
-	 */
-	if (gadget_is_pxa (gadget)) {
-		/* pxa doesn't support altsettings */
-		cdc = 0;
-	} else if (gadget_is_musbhdrc(gadget)) {
-		/* reduce tx dma overhead by avoiding special cases */
-		zlp = 0;
-	} else if (gadget_is_sh(gadget)) {
-		/* sh doesn't support multiple interfaces or configs */
-		cdc = 0;
-		rndis = 0;
-	} else if (gadget_is_sa1100 (gadget)) {
-		/* hardware can't write zlps */
-		zlp = 0;
-		/* sa1100 CAN do CDC, without status endpoint ... we use
-		 * non-CDC to be compatible with ARM Linux-2.4 "usb-eth".
-		 */
-		cdc = 0;
+	if (has_rndis()) {
+		/* RNDIS plus ECM-or-Subset */
+		device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM),
+		device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM),
+		device_desc.bNumConfigurations = 2;
 	}
 
-	gcnum = usb_gadget_controller_number (gadget);
+	gcnum = usb_gadget_controller_number(gadget);
 	if (gcnum >= 0)
-		device_desc.bcdDevice = cpu_to_le16 (0x0200 + gcnum);
+		device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
 	else {
-		/* can't assume CDC works.  don't want to default to
-		 * anything less functional on CDC-capable hardware,
-		 * so we fail in this case.
+		/* We assume that can_support_ecm() tells the truth;
+		 * but if the controller isn't recognized at all then
+		 * that assumption is a bit more likely to be wrong.
 		 */
-		dev_err (&gadget->dev,
-			"controller '%s' not recognized\n",
-			gadget->name);
-		return -ENODEV;
-	}
-	snprintf (manufacturer, sizeof manufacturer, "%s %s/%s",
-		init_utsname()->sysname, init_utsname()->release,
-		gadget->name);
-
-	/* If there's an RNDIS configuration, that's what Windows wants to
-	 * be using ... so use these product IDs here and in the "linux.inf"
-	 * needed to install MSFT drivers.  Current Linux kernels will use
-	 * the second configuration if it's CDC Ethernet, and need some help
-	 * to choose the right configuration otherwise.
-	 */
-	if (rndis) {
-		device_desc.idVendor =
-			__constant_cpu_to_le16(RNDIS_VENDOR_NUM);
-		device_desc.idProduct =
-			__constant_cpu_to_le16(RNDIS_PRODUCT_NUM);
-		snprintf (product_desc, sizeof product_desc,
-			"RNDIS/%s", driver_desc);
-
-	/* CDC subset ... recognized by Linux since 2.4.10, but Windows
-	 * drivers aren't widely available.  (That may be improved by
-	 * supporting one submode of the "SAFE" variant of MDLM.)
-	 */
-	} else if (!cdc) {
-		device_desc.idVendor =
-			__constant_cpu_to_le16(SIMPLE_VENDOR_NUM);
-		device_desc.idProduct =
-			__constant_cpu_to_le16(SIMPLE_PRODUCT_NUM);
-	}
-
-	/* support optional vendor/distro customization */
-	if (idVendor) {
-		if (!idProduct) {
-			dev_err (&gadget->dev, "idVendor needs idProduct!\n");
-			return -ENODEV;
-		}
-		device_desc.idVendor = cpu_to_le16(idVendor);
-		device_desc.idProduct = cpu_to_le16(idProduct);
-		if (bcdDevice)
-			device_desc.bcdDevice = cpu_to_le16(bcdDevice);
-	}
-	if (iManufacturer)
-		strlcpy (manufacturer, iManufacturer, sizeof manufacturer);
-	if (iProduct)
-		strlcpy (product_desc, iProduct, sizeof product_desc);
-	if (iSerialNumber) {
-		device_desc.iSerialNumber = STRING_SERIALNUMBER,
-		strlcpy(serial_number, iSerialNumber, sizeof serial_number);
-	}
-
-	/* all we really need is bulk IN/OUT */
-	usb_ep_autoconfig_reset (gadget);
-	in_ep = usb_ep_autoconfig (gadget, &fs_source_desc);
-	if (!in_ep) {
-autoconf_fail:
-		dev_err (&gadget->dev,
-			"can't autoconfigure on %s\n",
-			gadget->name);
-		return -ENODEV;
-	}
-	in_ep->driver_data = in_ep;	/* claim */
-
-	out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
-	if (!out_ep)
-		goto autoconf_fail;
-	out_ep->driver_data = out_ep;	/* claim */
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-	/* CDC Ethernet control interface doesn't require a status endpoint.
-	 * Since some hosts expect one, try to allocate one anyway.
-	 */
-	if (cdc || rndis) {
-		status_ep = usb_ep_autoconfig (gadget, &fs_status_desc);
-		if (status_ep) {
-			status_ep->driver_data = status_ep;	/* claim */
-		} else if (rndis) {
-			dev_err (&gadget->dev,
-				"can't run RNDIS on %s\n",
-				gadget->name);
-			return -ENODEV;
-#ifdef DEV_CONFIG_CDC
-		/* pxa25x only does CDC subset; often used with RNDIS */
-		} else if (cdc) {
-			control_intf.bNumEndpoints = 0;
-			/* FIXME remove endpoint from descriptor list */
-#endif
-		}
-	}
-#endif
-
-	/* one config:  cdc, else minimal subset */
-	if (!cdc) {
-		eth_config.bNumInterfaces = 1;
-		eth_config.iConfiguration = STRING_SUBSET;
-
-		/* use functions to set these up, in case we're built to work
-		 * with multiple controllers and must override CDC Ethernet.
-		 */
-		fs_subset_descriptors();
-		hs_subset_descriptors();
-	}
-
-	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-	usb_gadget_set_selfpowered (gadget);
-
-	/* For now RNDIS is always a second config */
-	if (rndis)
-		device_desc.bNumConfigurations = 2;
-
-	if (gadget_is_dualspeed(gadget)) {
-		if (rndis)
-			dev_qualifier.bNumConfigurations = 2;
-		else if (!cdc)
-			dev_qualifier.bDeviceClass = USB_CLASS_VENDOR_SPEC;
-
-		/* assumes ep0 uses the same value for both speeds ... */
-		dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
-
-		/* and that all endpoints are dual-speed */
-		hs_source_desc.bEndpointAddress =
-				fs_source_desc.bEndpointAddress;
-		hs_sink_desc.bEndpointAddress =
-				fs_sink_desc.bEndpointAddress;
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-		if (status_ep)
-			hs_status_desc.bEndpointAddress =
-					fs_status_desc.bEndpointAddress;
-#endif
+		WARNING(cdev, "controller '%s' not recognized; trying %s\n",
+				gadget->name,
+				eth_config_driver.label);
+		device_desc.bcdDevice =
+			__constant_cpu_to_le16(0x0300 | 0x0099);
 	}
 
-	if (gadget_is_otg(gadget)) {
-		otg_descriptor.bmAttributes |= USB_OTG_HNP,
-		eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-		eth_config.bMaxPower = 4;
-#ifdef	CONFIG_USB_ETH_RNDIS
-		rndis_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-		rndis_config.bMaxPower = 4;
-#endif
-	}
-
-	net = alloc_etherdev (sizeof *dev);
-	if (!net)
-		return status;
-	dev = netdev_priv(net);
-	spin_lock_init (&dev->lock);
-	spin_lock_init (&dev->req_lock);
-	INIT_WORK (&dev->work, eth_work);
-	INIT_LIST_HEAD (&dev->tx_reqs);
-	INIT_LIST_HEAD (&dev->rx_reqs);
-
-	/* network device setup */
-	dev->net = net;
-	strcpy (net->name, "usb%d");
-	dev->cdc = cdc;
-	dev->zlp = zlp;
 
-	dev->in_ep = in_ep;
-	dev->out_ep = out_ep;
-	dev->status_ep = status_ep;
-
-	/* Module params for these addresses should come from ID proms.
-	 * The host side address is used with CDC and RNDIS, and commonly
-	 * ends up in a persistent config database.  It's not clear if
-	 * host side code for the SAFE thing cares -- its original BLAN
-	 * thing didn't, Sharp never assigned those addresses on Zaurii.
+	/* Allocate string descriptor numbers ... note that string
+	 * contents can be overridden by the composite_dev glue.
 	 */
-	if (get_ether_addr(dev_addr, net->dev_addr))
-		dev_warn(&gadget->dev,
-			"using random %s ethernet address\n", "self");
-	if (get_ether_addr(host_addr, dev->host_mac))
-		dev_warn(&gadget->dev,
-			"using random %s ethernet address\n", "host");
-	snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
-		dev->host_mac [0], dev->host_mac [1],
-		dev->host_mac [2], dev->host_mac [3],
-		dev->host_mac [4], dev->host_mac [5]);
-
-	if (rndis) {
-		status = rndis_init();
-		if (status < 0) {
-			dev_err (&gadget->dev, "can't init RNDIS, %d\n",
-				status);
-			goto fail;
-		}
-	}
 
-	net->change_mtu = eth_change_mtu;
-	net->get_stats = eth_get_stats;
-	net->hard_start_xmit = eth_start_xmit;
-	net->open = eth_open;
-	net->stop = eth_stop;
-	// watchdog_timeo, tx_timeout ...
-	// set_multicast_list
-	SET_ETHTOOL_OPS(net, &ops);
+	/* device descriptor strings: manufacturer, product */
+	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
+		init_utsname()->sysname, init_utsname()->release,
+		gadget->name);
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail;
+	strings_dev[STRING_MANUFACTURER_IDX].id = status;
+	device_desc.iManufacturer = status;
 
-	/* preallocate control message data and buffer */
-	dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ, GFP_KERNEL);
-	if (!dev->req)
+	status = usb_string_id(cdev);
+	if (status < 0)
 		goto fail;
-	dev->req->complete = eth_setup_complete;
+	strings_dev[STRING_PRODUCT_IDX].id = status;
+	device_desc.iProduct = status;
 
-	/* ... and maybe likewise for status transfer */
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-	if (dev->status_ep) {
-		dev->stat_req = eth_req_alloc (dev->status_ep,
-					STATUS_BYTECOUNT, GFP_KERNEL);
-		if (!dev->stat_req) {
-			eth_req_free (gadget->ep0, dev->req);
+	/* register our configuration(s); RNDIS first, if it's used */
+	if (has_rndis()) {
+		status = usb_add_config(cdev, &rndis_config_driver);
+		if (status < 0)
 			goto fail;
-		}
-		dev->stat_req->context = NULL;
 	}
-#endif
-
-	/* finish hookup to lower layer ... */
-	dev->gadget = gadget;
-	set_gadget_data (gadget, dev);
-	gadget->ep0->driver_data = dev;
 
-	/* two kinds of host-initiated state changes:
-	 *  - iff DATA transfer is active, carrier is "on"
-	 *  - tx queueing enabled if open *and* carrier is "on"
-	 */
-	netif_stop_queue (dev->net);
-	netif_carrier_off (dev->net);
-
-	SET_NETDEV_DEV (dev->net, &gadget->dev);
-	status = register_netdev (dev->net);
+	status = usb_add_config(cdev, &eth_config_driver);
 	if (status < 0)
-		goto fail1;
-
-	INFO (dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
-	INFO (dev, "using %s, OUT %s IN %s%s%s\n", gadget->name,
-		out_ep->name, in_ep->name,
-		status_ep ? " STATUS " : "",
-		status_ep ? status_ep->name : ""
-		);
-	INFO (dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
-		net->dev_addr [0], net->dev_addr [1],
-		net->dev_addr [2], net->dev_addr [3],
-		net->dev_addr [4], net->dev_addr [5]);
-
-	if (cdc || rndis)
-		INFO (dev, "HOST MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
-			dev->host_mac [0], dev->host_mac [1],
-			dev->host_mac [2], dev->host_mac [3],
-			dev->host_mac [4], dev->host_mac [5]);
-
-	if (rndis) {
-		u32	vendorID = 0;
-
-		/* FIXME RNDIS vendor id == "vendor NIC code" == ? */
-
-		dev->rndis_config = rndis_register (rndis_control_ack);
-		if (dev->rndis_config < 0) {
-fail0:
-			unregister_netdev (dev->net);
-			status = -ENODEV;
-			goto fail;
-		}
+		goto fail;
 
-		/* these set up a lot of the OIDs that RNDIS needs */
-		rndis_set_host_mac (dev->rndis_config, dev->host_mac);
-		if (rndis_set_param_dev (dev->rndis_config, dev->net,
-					 &dev->stats, &dev->cdc_filter))
-			goto fail0;
-		if (rndis_set_param_vendor(dev->rndis_config, vendorID,
-					manufacturer))
-			goto fail0;
-		if (rndis_set_param_medium(dev->rndis_config,
-					NDIS_MEDIUM_802_3, 0))
-			goto fail0;
-		INFO (dev, "RNDIS ready\n");
-	}
+	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC);
 
-	return status;
+	return 0;
 
-fail1:
-	dev_dbg(&gadget->dev, "register_netdev failed, %d\n", status);
 fail:
-	eth_unbind (gadget);
+	gether_cleanup();
 	return status;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static void
-eth_suspend (struct usb_gadget *gadget)
-{
-	struct eth_dev		*dev = get_gadget_data (gadget);
-
-	DEBUG (dev, "suspend\n");
-	dev->suspended = 1;
-}
-
-static void
-eth_resume (struct usb_gadget *gadget)
+static int __exit eth_unbind(struct usb_composite_dev *cdev)
 {
-	struct eth_dev		*dev = get_gadget_data (gadget);
-
-	DEBUG (dev, "resume\n");
-	dev->suspended = 0;
+	gether_cleanup();
+	return 0;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static struct usb_gadget_driver eth_driver = {
-	.speed		= DEVSPEED,
-
-	.function	= (char *) driver_desc,
+static struct usb_composite_driver eth_driver = {
+	.name		= "g_ether",
+	.dev		= &device_desc,
+	.strings	= dev_strings,
 	.bind		= eth_bind,
-	.unbind		= eth_unbind,
-
-	.setup		= eth_setup,
-	.disconnect	= eth_disconnect,
-
-	.suspend	= eth_suspend,
-	.resume		= eth_resume,
-
-	.driver	= {
-		.name		= (char *) shortname,
-		.owner		= THIS_MODULE,
-	},
+	.unbind		= __exit_p(eth_unbind),
 };
 
-MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_AUTHOR ("David Brownell, Benedikt Spanger");
-MODULE_LICENSE ("GPL");
+MODULE_DESCRIPTION(PREFIX DRIVER_DESC);
+MODULE_AUTHOR("David Brownell, Benedikt Spanger");
+MODULE_LICENSE("GPL");
 
-
-static int __init init (void)
+static int __init init(void)
 {
-	return usb_gadget_register_driver (&eth_driver);
+	return usb_composite_register(&eth_driver);
 }
-module_init (init);
+module_init(init);
 
-static void __exit cleanup (void)
+static void __exit cleanup(void)
 {
-	usb_gadget_unregister_driver (&eth_driver);
+	usb_composite_unregister(&eth_driver);
 }
-module_exit (cleanup);
-
+module_exit(cleanup);
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
new file mode 100644
index 0000000..5ee1590
--- /dev/null
+++ b/drivers/usb/gadget/f_acm.c
@@ -0,0 +1,759 @@
+/*
+ * f_acm.c -- USB CDC serial (ACM) function driver
+ *
+ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2008 by David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of that License or (at your option) any later version.
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+#include "u_serial.h"
+#include "gadget_chips.h"
+
+
+/*
+ * This CDC ACM function support just wraps control functions and
+ * notifications around the generic serial-over-usb code.
+ *
+ * Because CDC ACM is standardized by the USB-IF, many host operating
+ * systems have drivers for it.  Accordingly, ACM is the preferred
+ * interop solution for serial-port type connections.  The control
+ * models are often not necessary, and in any case don't do much in
+ * this bare-bones implementation.
+ *
+ * Note that even MS-Windows has some support for ACM.  However, that
+ * support is somewhat broken because when you use ACM in a composite
+ * device, having multiple interfaces confuses the poor OS.  It doesn't
+ * seem to understand CDC Union descriptors.  The new "association"
+ * descriptors (roughly equivalent to CDC Unions) may sometimes help.
+ */
+
+struct acm_ep_descs {
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+	struct usb_endpoint_descriptor	*notify;
+};
+
+struct f_acm {
+	struct gserial			port;
+	u8				ctrl_id, data_id;
+	u8				port_num;
+
+	u8				pending;
+
+	/* lock is mostly for pending and notify_req ... they get accessed
+	 * by callbacks both from tty (open/close/break) under its spinlock,
+	 * and notify_req.complete() which can't use that lock.
+	 */
+	spinlock_t			lock;
+
+	struct acm_ep_descs		fs;
+	struct acm_ep_descs		hs;
+
+	struct usb_ep			*notify;
+	struct usb_endpoint_descriptor	*notify_desc;
+	struct usb_request		*notify_req;
+
+	struct usb_cdc_line_coding	port_line_coding;	/* 8-N-1 etc */
+
+	/* SetControlLineState request -- CDC 1.1 section 6.2.14 (INPUT) */
+	u16				port_handshake_bits;
+#define ACM_CTRL_RTS	(1 << 1)	/* unused with full duplex */
+#define ACM_CTRL_DTR	(1 << 0)	/* host is ready for data r/w */
+
+	/* SerialState notification -- CDC 1.1 section 6.3.5 (OUTPUT) */
+	u16				serial_state;
+#define ACM_CTRL_OVERRUN	(1 << 6)
+#define ACM_CTRL_PARITY		(1 << 5)
+#define ACM_CTRL_FRAMING	(1 << 4)
+#define ACM_CTRL_RI		(1 << 3)
+#define ACM_CTRL_BRK		(1 << 2)
+#define ACM_CTRL_DSR		(1 << 1)
+#define ACM_CTRL_DCD		(1 << 0)
+};
+
+static inline struct f_acm *func_to_acm(struct usb_function *f)
+{
+	return container_of(f, struct f_acm, port.func);
+}
+
+static inline struct f_acm *port_to_acm(struct gserial *p)
+{
+	return container_of(p, struct f_acm, port);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* notification endpoint uses smallish and infrequent fixed-size messages */
+
+#define GS_LOG2_NOTIFY_INTERVAL		5	/* 1 << 5 == 32 msec */
+#define GS_NOTIFY_MAXPACKET		10	/* notification + 2 bytes */
+
+/* interface and class descriptors: */
+
+static struct usb_interface_descriptor acm_control_interface_desc __initdata = {
+	.bLength =		USB_DT_INTERFACE_SIZE,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	/* .bInterfaceNumber = DYNAMIC */
+	.bNumEndpoints =	1,
+	.bInterfaceClass =	USB_CLASS_COMM,
+	.bInterfaceSubClass =	USB_CDC_SUBCLASS_ACM,
+	.bInterfaceProtocol =	USB_CDC_ACM_PROTO_AT_V25TER,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_interface_descriptor acm_data_interface_desc __initdata = {
+	.bLength =		USB_DT_INTERFACE_SIZE,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	/* .bInterfaceNumber = DYNAMIC */
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_CDC_DATA,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc acm_header_desc __initdata = {
+	.bLength =		sizeof(acm_header_desc),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
+	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_call_mgmt_descriptor
+acm_call_mgmt_descriptor __initdata = {
+	.bLength =		sizeof(acm_call_mgmt_descriptor),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_CALL_MANAGEMENT_TYPE,
+	.bmCapabilities =	0,
+	/* .bDataInterface = DYNAMIC */
+};
+
+static struct usb_cdc_acm_descriptor acm_descriptor __initdata = {
+	.bLength =		sizeof(acm_descriptor),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
+	.bmCapabilities =	USB_CDC_CAP_LINE,
+};
+
+static struct usb_cdc_union_desc acm_union_desc __initdata = {
+	.bLength =		sizeof(acm_union_desc),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
+	/* .bMasterInterface0 =	DYNAMIC */
+	/* .bSlaveInterface0 =	DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor acm_fs_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	__constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
+	.bInterval =		1 << GS_LOG2_NOTIFY_INTERVAL,
+};
+
+static struct usb_endpoint_descriptor acm_fs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor acm_fs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *acm_fs_function[] __initdata = {
+	(struct usb_descriptor_header *) &acm_control_interface_desc,
+	(struct usb_descriptor_header *) &acm_header_desc,
+	(struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &acm_descriptor,
+	(struct usb_descriptor_header *) &acm_union_desc,
+	(struct usb_descriptor_header *) &acm_fs_notify_desc,
+	(struct usb_descriptor_header *) &acm_data_interface_desc,
+	(struct usb_descriptor_header *) &acm_fs_in_desc,
+	(struct usb_descriptor_header *) &acm_fs_out_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor acm_hs_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	__constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
+	.bInterval =		GS_LOG2_NOTIFY_INTERVAL+4,
+};
+
+static struct usb_endpoint_descriptor acm_hs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *acm_hs_function[] __initdata = {
+	(struct usb_descriptor_header *) &acm_control_interface_desc,
+	(struct usb_descriptor_header *) &acm_header_desc,
+	(struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &acm_descriptor,
+	(struct usb_descriptor_header *) &acm_union_desc,
+	(struct usb_descriptor_header *) &acm_hs_notify_desc,
+	(struct usb_descriptor_header *) &acm_data_interface_desc,
+	(struct usb_descriptor_header *) &acm_hs_in_desc,
+	(struct usb_descriptor_header *) &acm_hs_out_desc,
+	NULL,
+};
+
+/* string descriptors: */
+
+#define ACM_CTRL_IDX	0
+#define ACM_DATA_IDX	1
+
+/* static strings, in UTF-8 */
+static struct usb_string acm_string_defs[] = {
+	[ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
+	[ACM_DATA_IDX].s = "CDC ACM Data",
+	{  /* ZEROES END LIST */ },
+};
+
+static struct usb_gadget_strings acm_string_table = {
+	.language =		0x0409,	/* en-us */
+	.strings =		acm_string_defs,
+};
+
+static struct usb_gadget_strings *acm_strings[] = {
+	&acm_string_table,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* ACM control ... data handling is delegated to tty library code.
+ * The main task of this function is to activate and deactivate
+ * that code based on device state; track parameters like line
+ * speed, handshake state, and so on; and issue notifications.
+ */
+
+static void acm_complete_set_line_coding(struct usb_ep *ep,
+		struct usb_request *req)
+{
+	struct f_acm	*acm = ep->driver_data;
+	struct usb_composite_dev *cdev = acm->port.func.config->cdev;
+
+	if (req->status != 0) {
+		DBG(cdev, "acm ttyGS%d completion, err %d\n",
+				acm->port_num, req->status);
+		return;
+	}
+
+	/* normal completion */
+	if (req->actual != sizeof(acm->port_line_coding)) {
+		DBG(cdev, "acm ttyGS%d short resp, len %d\n",
+				acm->port_num, req->actual);
+		usb_ep_set_halt(ep);
+	} else {
+		struct usb_cdc_line_coding	*value = req->buf;
+
+		/* REVISIT:  we currently just remember this data.
+		 * If we change that, (a) validate it first, then
+		 * (b) update whatever hardware needs updating,
+		 * (c) worry about locking.  This is information on
+		 * the order of 9600-8-N-1 ... most of which means
+		 * nothing unless we control a real RS232 line.
+		 */
+		acm->port_line_coding = *value;
+	}
+}
+
+static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct f_acm		*acm = func_to_acm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct usb_request	*req = cdev->req;
+	int			value = -EOPNOTSUPP;
+	u16			w_index = le16_to_cpu(ctrl->wIndex);
+	u16			w_value = le16_to_cpu(ctrl->wValue);
+	u16			w_length = le16_to_cpu(ctrl->wLength);
+
+	/* composite driver infrastructure handles everything except
+	 * CDC class messages; interface activation uses set_alt().
+	 *
+	 * Note CDC spec table 4 lists the ACM request profile.  It requires
+	 * encapsulated command support ... we don't handle any, and respond
+	 * to them by stalling.  Options include get/set/clear comm features
+	 * (not that useful) and SEND_BREAK.
+	 */
+	switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+
+	/* SET_LINE_CODING ... just read and save what the host sends */
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_REQ_SET_LINE_CODING:
+		if (w_length != sizeof(struct usb_cdc_line_coding)
+				|| w_index != acm->ctrl_id)
+			goto invalid;
+
+		value = w_length;
+		cdev->gadget->ep0->driver_data = acm;
+		req->complete = acm_complete_set_line_coding;
+		break;
+
+	/* GET_LINE_CODING ... return what host sent, or initial value */
+	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_REQ_GET_LINE_CODING:
+		if (w_index != acm->ctrl_id)
+			goto invalid;
+
+		value = min_t(unsigned, w_length,
+				sizeof(struct usb_cdc_line_coding));
+		memcpy(req->buf, &acm->port_line_coding, value);
+		break;
+
+	/* SET_CONTROL_LINE_STATE ... save what the host sent */
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_REQ_SET_CONTROL_LINE_STATE:
+		if (w_index != acm->ctrl_id)
+			goto invalid;
+
+		value = 0;
+
+		/* FIXME we should not allow data to flow until the
+		 * host sets the ACM_CTRL_DTR bit; and when it clears
+		 * that bit, we should return to that no-flow state.
+		 */
+		acm->port_handshake_bits = w_value;
+		break;
+
+	default:
+invalid:
+		VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+	}
+
+	/* respond with data transfer or status phase? */
+	if (value >= 0) {
+		DBG(cdev, "acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n",
+			acm->port_num, ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+		req->zero = 0;
+		req->length = value;
+		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0)
+			ERROR(cdev, "acm response on ttyGS%d, err %d\n",
+					acm->port_num, value);
+	}
+
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_acm		*acm = func_to_acm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	/* we know alt == 0, so this is an activation or a reset */
+
+	if (intf == acm->ctrl_id) {
+		if (acm->notify->driver_data) {
+			VDBG(cdev, "reset acm control interface %d\n", intf);
+			usb_ep_disable(acm->notify);
+		} else {
+			VDBG(cdev, "init acm ctrl interface %d\n", intf);
+			acm->notify_desc = ep_choose(cdev->gadget,
+					acm->hs.notify,
+					acm->fs.notify);
+		}
+		usb_ep_enable(acm->notify, acm->notify_desc);
+		acm->notify->driver_data = acm;
+
+	} else if (intf == acm->data_id) {
+		if (acm->port.in->driver_data) {
+			DBG(cdev, "reset acm ttyGS%d\n", acm->port_num);
+			gserial_disconnect(&acm->port);
+		} else {
+			DBG(cdev, "activate acm ttyGS%d\n", acm->port_num);
+			acm->port.in_desc = ep_choose(cdev->gadget,
+					acm->hs.in, acm->fs.in);
+			acm->port.out_desc = ep_choose(cdev->gadget,
+					acm->hs.out, acm->fs.out);
+		}
+		gserial_connect(&acm->port, acm->port_num);
+
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+static void acm_disable(struct usb_function *f)
+{
+	struct f_acm	*acm = func_to_acm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	DBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num);
+	gserial_disconnect(&acm->port);
+	usb_ep_disable(acm->notify);
+	acm->notify->driver_data = NULL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * acm_cdc_notify - issue CDC notification to host
+ * @acm: wraps host to be notified
+ * @type: notification type
+ * @value: Refer to cdc specs, wValue field.
+ * @data: data to be sent
+ * @length: size of data
+ * Context: irqs blocked, acm->lock held, acm_notify_req non-null
+ *
+ * Returns zero on sucess or a negative errno.
+ *
+ * See section 6.3.5 of the CDC 1.1 specification for information
+ * about the only notification we issue:  SerialState change.
+ */
+static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value,
+		void *data, unsigned length)
+{
+	struct usb_ep			*ep = acm->notify;
+	struct usb_request		*req;
+	struct usb_cdc_notification	*notify;
+	const unsigned			len = sizeof(*notify) + length;
+	void				*buf;
+	int				status;
+
+	req = acm->notify_req;
+	acm->notify_req = NULL;
+	acm->pending = false;
+
+	req->length = len;
+	notify = req->buf;
+	buf = notify + 1;
+
+	notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
+			| USB_RECIP_INTERFACE;
+	notify->bNotificationType = type;
+	notify->wValue = cpu_to_le16(value);
+	notify->wIndex = cpu_to_le16(acm->ctrl_id);
+	notify->wLength = cpu_to_le16(length);
+	memcpy(buf, data, length);
+
+	status = usb_ep_queue(ep, req, GFP_ATOMIC);
+	if (status < 0) {
+		ERROR(acm->port.func.config->cdev,
+				"acm ttyGS%d can't notify serial state, %d\n",
+				acm->port_num, status);
+		acm->notify_req = req;
+	}
+
+	return status;
+}
+
+static int acm_notify_serial_state(struct f_acm *acm)
+{
+	struct usb_composite_dev *cdev = acm->port.func.config->cdev;
+	int			status;
+
+	spin_lock(&acm->lock);
+	if (acm->notify_req) {
+		DBG(cdev, "acm ttyGS%d serial state %04x\n",
+				acm->port_num, acm->serial_state);
+		status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
+				0, &acm->serial_state, sizeof(acm->serial_state));
+	} else {
+		acm->pending = true;
+		status = 0;
+	}
+	spin_unlock(&acm->lock);
+	return status;
+}
+
+static void acm_cdc_notify_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_acm		*acm = req->context;
+	u8			doit = false;
+
+	/* on this call path we do NOT hold the port spinlock,
+	 * which is why ACM needs its own spinlock
+	 */
+	spin_lock(&acm->lock);
+	if (req->status != -ESHUTDOWN)
+		doit = acm->pending;
+	acm->notify_req = req;
+	spin_unlock(&acm->lock);
+
+	if (doit)
+		acm_notify_serial_state(acm);
+}
+
+/* connect == the TTY link is open */
+
+static void acm_connect(struct gserial *port)
+{
+	struct f_acm		*acm = port_to_acm(port);
+
+	acm->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD;
+	acm_notify_serial_state(acm);
+}
+
+static void acm_disconnect(struct gserial *port)
+{
+	struct f_acm		*acm = port_to_acm(port);
+
+	acm->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD);
+	acm_notify_serial_state(acm);
+}
+
+static int acm_send_break(struct gserial *port, int duration)
+{
+	struct f_acm		*acm = port_to_acm(port);
+	u16			state;
+
+	state = acm->serial_state;
+	state &= ~ACM_CTRL_BRK;
+	if (duration)
+		state |= ACM_CTRL_BRK;
+
+	acm->serial_state = state;
+	return acm_notify_serial_state(acm);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* ACM function driver setup/binding */
+static int __init
+acm_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_acm		*acm = func_to_acm(f);
+	int			status;
+	struct usb_ep		*ep;
+
+	/* allocate instance-specific interface IDs, and patch descriptors */
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	acm->ctrl_id = status;
+
+	acm_control_interface_desc.bInterfaceNumber = status;
+	acm_union_desc .bMasterInterface0 = status;
+
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	acm->data_id = status;
+
+	acm_data_interface_desc.bInterfaceNumber = status;
+	acm_union_desc.bSlaveInterface0 = status;
+	acm_call_mgmt_descriptor.bDataInterface = status;
+
+	status = -ENODEV;
+
+	/* allocate instance-specific endpoints */
+	ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc);
+	if (!ep)
+		goto fail;
+	acm->port.in = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc);
+	if (!ep)
+		goto fail;
+	acm->port.out = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc);
+	if (!ep)
+		goto fail;
+	acm->notify = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	/* allocate notification */
+	acm->notify_req = gs_alloc_req(ep,
+			sizeof(struct usb_cdc_notification) + 2,
+			GFP_KERNEL);
+	if (!acm->notify_req)
+		goto fail;
+
+	acm->notify_req->complete = acm_cdc_notify_complete;
+	acm->notify_req->context = acm;
+
+	/* copy descriptors, and track endpoint copies */
+	f->descriptors = usb_copy_descriptors(acm_fs_function);
+	if (!f->descriptors)
+		goto fail;
+
+	acm->fs.in = usb_find_endpoint(acm_fs_function,
+			f->descriptors, &acm_fs_in_desc);
+	acm->fs.out = usb_find_endpoint(acm_fs_function,
+			f->descriptors, &acm_fs_out_desc);
+	acm->fs.notify = usb_find_endpoint(acm_fs_function,
+			f->descriptors, &acm_fs_notify_desc);
+
+	/* support all relevant hardware speeds... we expect that when
+	 * hardware is dual speed, all bulk-capable endpoints work at
+	 * both speeds
+	 */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		acm_hs_in_desc.bEndpointAddress =
+				acm_fs_in_desc.bEndpointAddress;
+		acm_hs_out_desc.bEndpointAddress =
+				acm_fs_out_desc.bEndpointAddress;
+		acm_hs_notify_desc.bEndpointAddress =
+				acm_fs_notify_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
+
+		acm->hs.in = usb_find_endpoint(acm_hs_function,
+				f->hs_descriptors, &acm_hs_in_desc);
+		acm->hs.out = usb_find_endpoint(acm_hs_function,
+				f->hs_descriptors, &acm_hs_out_desc);
+		acm->hs.notify = usb_find_endpoint(acm_hs_function,
+				f->hs_descriptors, &acm_hs_notify_desc);
+	}
+
+	DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+			acm->port_num,
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			acm->port.in->name, acm->port.out->name,
+			acm->notify->name);
+	return 0;
+
+fail:
+	if (acm->notify_req)
+		gs_free_req(acm->notify, acm->notify_req);
+
+	/* we might as well release our claims on endpoints */
+	if (acm->notify)
+		acm->notify->driver_data = NULL;
+	if (acm->port.out)
+		acm->port.out->driver_data = NULL;
+	if (acm->port.in)
+		acm->port.in->driver_data = NULL;
+
+	ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
+
+	return status;
+}
+
+static void
+acm_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_acm		*acm = func_to_acm(f);
+
+	if (gadget_is_dualspeed(c->cdev->gadget))
+		usb_free_descriptors(f->hs_descriptors);
+	usb_free_descriptors(f->descriptors);
+	gs_free_req(acm->notify, acm->notify_req);
+	kfree(acm);
+}
+
+/* Some controllers can't support CDC ACM ... */
+static inline bool can_support_cdc(struct usb_configuration *c)
+{
+	/* SH3 doesn't support multiple interfaces */
+	if (gadget_is_sh(c->cdev->gadget))
+		return false;
+
+	/* sa1100 doesn't have a third interrupt endpoint */
+	if (gadget_is_sa1100(c->cdev->gadget))
+		return false;
+
+	/* everything else is *probably* fine ... */
+	return true;
+}
+
+/**
+ * acm_bind_config - add a CDC ACM function to a configuration
+ * @c: the configuration to support the CDC ACM instance
+ * @port_num: /dev/ttyGS* port this interface will use
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gserial_setup() with enough ports to
+ * handle all the ones it binds.  Caller is also responsible
+ * for calling @gserial_cleanup() before module unload.
+ */
+int __init acm_bind_config(struct usb_configuration *c, u8 port_num)
+{
+	struct f_acm	*acm;
+	int		status;
+
+	if (!can_support_cdc(c))
+		return -EINVAL;
+
+	/* REVISIT might want instance-specific strings to help
+	 * distinguish instances ...
+	 */
+
+	/* maybe allocate device-global string IDs, and patch descriptors */
+	if (acm_string_defs[ACM_CTRL_IDX].id == 0) {
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		acm_string_defs[ACM_CTRL_IDX].id = status;
+
+		acm_control_interface_desc.iInterface = status;
+
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		acm_string_defs[ACM_DATA_IDX].id = status;
+
+		acm_data_interface_desc.iInterface = status;
+	}
+
+	/* allocate and initialize one new instance */
+	acm = kzalloc(sizeof *acm, GFP_KERNEL);
+	if (!acm)
+		return -ENOMEM;
+
+	spin_lock_init(&acm->lock);
+
+	acm->port_num = port_num;
+
+	acm->port.connect = acm_connect;
+	acm->port.disconnect = acm_disconnect;
+	acm->port.send_break = acm_send_break;
+
+	acm->port.func.name = "acm";
+	acm->port.func.strings = acm_strings;
+	/* descriptors are per-instance copies */
+	acm->port.func.bind = acm_bind;
+	acm->port.func.unbind = acm_unbind;
+	acm->port.func.set_alt = acm_set_alt;
+	acm->port.func.setup = acm_setup;
+	acm->port.func.disable = acm_disable;
+
+	status = usb_add_function(c, &acm->port.func);
+	if (status)
+		kfree(acm);
+	return status;
+}
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
new file mode 100644
index 0000000..a2b5c09
--- /dev/null
+++ b/drivers/usb/gadget/f_ecm.c
@@ -0,0 +1,831 @@
+/*
+ * f_ecm.c -- USB CDC Ethernet (ECM) link function driver
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+
+#include "u_ether.h"
+
+
+/*
+ * This function is a "CDC Ethernet Networking Control Model" (CDC ECM)
+ * Ethernet link.  The data transfer model is simple (packets sent and
+ * received over bulk endpoints using normal short packet termination),
+ * and the control model exposes various data and optional notifications.
+ *
+ * ECM is well standardized and (except for Microsoft) supported by most
+ * operating systems with USB host support.  It's the preferred interop
+ * solution for Ethernet over USB, at least for firmware based solutions.
+ * (Hardware solutions tend to be more minimalist.)  A newer and simpler
+ * "Ethernet Emulation Model" (CDC EEM) hasn't yet caught on.
+ *
+ * Note that ECM requires the use of "alternate settings" for its data
+ * interface.  This means that the set_alt() method has real work to do,
+ * and also means that a get_alt() method is required.
+ */
+
+struct ecm_ep_descs {
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+	struct usb_endpoint_descriptor	*notify;
+};
+
+enum ecm_notify_state {
+	ECM_NOTIFY_NONE,		/* don't notify */
+	ECM_NOTIFY_CONNECT,		/* issue CONNECT next */
+	ECM_NOTIFY_SPEED,		/* issue SPEED_CHANGE next */
+};
+
+struct f_ecm {
+	struct gether			port;
+	u8				ctrl_id, data_id;
+
+	char				ethaddr[14];
+
+	struct ecm_ep_descs		fs;
+	struct ecm_ep_descs		hs;
+
+	struct usb_ep			*notify;
+	struct usb_endpoint_descriptor	*notify_desc;
+	struct usb_request		*notify_req;
+	u8				notify_state;
+	bool				is_open;
+
+	/* FIXME is_open needs some irq-ish locking
+	 * ... possibly the same as port.ioport
+	 */
+};
+
+static inline struct f_ecm *func_to_ecm(struct usb_function *f)
+{
+	return container_of(f, struct f_ecm, port.func);
+}
+
+/* peak (theoretical) bulk transfer rate in bits-per-second */
+static inline unsigned bitrate(struct usb_gadget *g)
+{
+	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+		return 13 * 512 * 8 * 1000 * 8;
+	else
+		return 19 *  64 * 1 * 1000 * 8;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Include the status endpoint if we can, even though it's optional.
+ *
+ * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
+ * packet, to simplify cancellation; and a big transfer interval, to
+ * waste less bandwidth.
+ *
+ * Some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even
+ * if they ignore the connect/disconnect notifications that real aether
+ * can provide.  More advanced cdc configurations might want to support
+ * encapsulated commands (vendor-specific, using control-OUT).
+ */
+
+#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
+#define STATUS_BYTECOUNT		16	/* 8 byte header + data */
+
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor ecm_control_intf __initdata = {
+	.bLength =		sizeof ecm_control_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	/* .bInterfaceNumber = DYNAMIC */
+	/* status endpoint is optional; this could be patched later */
+	.bNumEndpoints =	1,
+	.bInterfaceClass =	USB_CLASS_COMM,
+	.bInterfaceSubClass =	USB_CDC_SUBCLASS_ETHERNET,
+	.bInterfaceProtocol =	USB_CDC_PROTO_NONE,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc header_desc __initdata = {
+	.bLength =		sizeof header_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
+
+	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_union_desc ecm_union_desc __initdata = {
+	.bLength =		sizeof(ecm_union_desc),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
+	/* .bMasterInterface0 =	DYNAMIC */
+	/* .bSlaveInterface0 =	DYNAMIC */
+};
+
+static struct usb_cdc_ether_desc ether_desc __initdata = {
+	.bLength =		sizeof ether_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_ETHERNET_TYPE,
+
+	/* this descriptor actually adds value, surprise! */
+	/* .iMACAddress = DYNAMIC */
+	.bmEthernetStatistics =	__constant_cpu_to_le32(0), /* no statistics */
+	.wMaxSegmentSize =	__constant_cpu_to_le16(ETH_FRAME_LEN),
+	.wNumberMCFilters =	__constant_cpu_to_le16(0),
+	.bNumberPowerFilters =	0,
+};
+
+/* the default data interface has no endpoints ... */
+
+static struct usb_interface_descriptor ecm_data_nop_intf __initdata = {
+	.bLength =		sizeof ecm_data_nop_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bInterfaceNumber =	1,
+	.bAlternateSetting =	0,
+	.bNumEndpoints =	0,
+	.bInterfaceClass =	USB_CLASS_CDC_DATA,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+/* ... but the "real" data interface has two bulk endpoints */
+
+static struct usb_interface_descriptor ecm_data_intf __initdata = {
+	.bLength =		sizeof ecm_data_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bInterfaceNumber =	1,
+	.bAlternateSetting =	1,
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_CDC_DATA,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	__constant_cpu_to_le16(STATUS_BYTECOUNT),
+	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
+};
+
+static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *eth_fs_function[] __initdata = {
+	/* CDC ECM control descriptors */
+	(struct usb_descriptor_header *) &ecm_control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &ecm_union_desc,
+	(struct usb_descriptor_header *) &ether_desc,
+	/* NOTE: status endpoint might need to be removed */
+	(struct usb_descriptor_header *) &fs_notify_desc,
+	/* data interface, altsettings 0 and 1 */
+	(struct usb_descriptor_header *) &ecm_data_nop_intf,
+	(struct usb_descriptor_header *) &ecm_data_intf,
+	(struct usb_descriptor_header *) &fs_in_desc,
+	(struct usb_descriptor_header *) &fs_out_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	__constant_cpu_to_le16(STATUS_BYTECOUNT),
+	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
+};
+static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *eth_hs_function[] __initdata = {
+	/* CDC ECM control descriptors */
+	(struct usb_descriptor_header *) &ecm_control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &ecm_union_desc,
+	(struct usb_descriptor_header *) &ether_desc,
+	/* NOTE: status endpoint might need to be removed */
+	(struct usb_descriptor_header *) &hs_notify_desc,
+	/* data interface, altsettings 0 and 1 */
+	(struct usb_descriptor_header *) &ecm_data_nop_intf,
+	(struct usb_descriptor_header *) &ecm_data_intf,
+	(struct usb_descriptor_header *) &hs_in_desc,
+	(struct usb_descriptor_header *) &hs_out_desc,
+	NULL,
+};
+
+/* string descriptors: */
+
+static struct usb_string ecm_string_defs[] = {
+	[0].s = "CDC Ethernet Control Model (ECM)",
+	[1].s = NULL /* DYNAMIC */,
+	[2].s = "CDC Ethernet Data",
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings ecm_string_table = {
+	.language =		0x0409,	/* en-us */
+	.strings =		ecm_string_defs,
+};
+
+static struct usb_gadget_strings *ecm_strings[] = {
+	&ecm_string_table,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static void ecm_do_notify(struct f_ecm *ecm)
+{
+	struct usb_request		*req = ecm->notify_req;
+	struct usb_cdc_notification	*event;
+	struct usb_composite_dev	*cdev = ecm->port.func.config->cdev;
+	__le32				*data;
+	int				status;
+
+	/* notification already in flight? */
+	if (!req)
+		return;
+
+	event = req->buf;
+	switch (ecm->notify_state) {
+	case ECM_NOTIFY_NONE:
+		return;
+
+	case ECM_NOTIFY_CONNECT:
+		event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
+		if (ecm->is_open)
+			event->wValue = cpu_to_le16(1);
+		else
+			event->wValue = cpu_to_le16(0);
+		event->wLength = 0;
+		req->length = sizeof *event;
+
+		DBG(cdev, "notify connect %s\n",
+				ecm->is_open ? "true" : "false");
+		ecm->notify_state = ECM_NOTIFY_SPEED;
+		break;
+
+	case ECM_NOTIFY_SPEED:
+		event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
+		event->wValue = cpu_to_le16(0);
+		event->wLength = cpu_to_le16(8);
+		req->length = STATUS_BYTECOUNT;
+
+		/* SPEED_CHANGE data is up/down speeds in bits/sec */
+		data = req->buf + sizeof *event;
+		data[0] = cpu_to_le32(bitrate(cdev->gadget));
+		data[1] = data[0];
+
+		DBG(cdev, "notify speed %d\n", bitrate(cdev->gadget));
+		ecm->notify_state = ECM_NOTIFY_NONE;
+		break;
+	}
+	event->bmRequestType = 0xA1;
+	event->wIndex = cpu_to_le16(ecm->ctrl_id);
+
+	ecm->notify_req = NULL;
+	status = usb_ep_queue(ecm->notify, req, GFP_ATOMIC);
+	if (status < 0) {
+		ecm->notify_req = req;
+		DBG(cdev, "notify --> %d\n", status);
+	}
+}
+
+static void ecm_notify(struct f_ecm *ecm)
+{
+	/* NOTE on most versions of Linux, host side cdc-ethernet
+	 * won't listen for notifications until its netdevice opens.
+	 * The first notification then sits in the FIFO for a long
+	 * time, and the second one is queued.
+	 */
+	ecm->notify_state = ECM_NOTIFY_CONNECT;
+	ecm_do_notify(ecm);
+}
+
+static void ecm_notify_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_ecm			*ecm = req->context;
+	struct usb_composite_dev	*cdev = ecm->port.func.config->cdev;
+	struct usb_cdc_notification	*event = req->buf;
+
+	switch (req->status) {
+	case 0:
+		/* no fault */
+		break;
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		ecm->notify_state = ECM_NOTIFY_NONE;
+		break;
+	default:
+		DBG(cdev, "event %02x --> %d\n",
+			event->bNotificationType, req->status);
+		break;
+	}
+	ecm->notify_req = req;
+	ecm_do_notify(ecm);
+}
+
+static int ecm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct f_ecm		*ecm = func_to_ecm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct usb_request	*req = cdev->req;
+	int			value = -EOPNOTSUPP;
+	u16			w_index = le16_to_cpu(ctrl->wIndex);
+	u16			w_value = le16_to_cpu(ctrl->wValue);
+	u16			w_length = le16_to_cpu(ctrl->wLength);
+
+	/* composite driver infrastructure handles everything except
+	 * CDC class messages; interface activation uses set_alt().
+	 */
+	switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_SET_ETHERNET_PACKET_FILTER:
+		/* see 6.2.30: no data, wIndex = interface,
+		 * wValue = packet filter bitmap
+		 */
+		if (w_length != 0 || w_index != ecm->ctrl_id)
+			goto invalid;
+		DBG(cdev, "packet filter %02x\n", w_value);
+		/* REVISIT locking of cdc_filter.  This assumes the UDC
+		 * driver won't have a concurrent packet TX irq running on
+		 * another CPU; or that if it does, this write is atomic...
+		 */
+		ecm->port.cdc_filter = w_value;
+		value = 0;
+		break;
+
+	/* and optionally:
+	 * case USB_CDC_SEND_ENCAPSULATED_COMMAND:
+	 * case USB_CDC_GET_ENCAPSULATED_RESPONSE:
+	 * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
+	 * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
+	 * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
+	 * case USB_CDC_GET_ETHERNET_STATISTIC:
+	 */
+
+	default:
+invalid:
+		DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+	}
+
+	/* respond with data transfer or status phase? */
+	if (value >= 0) {
+		DBG(cdev, "ecm req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+		req->zero = 0;
+		req->length = value;
+		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0)
+			ERROR(cdev, "ecm req %02x.%02x response err %d\n",
+					ctrl->bRequestType, ctrl->bRequest,
+					value);
+	}
+
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+
+static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_ecm		*ecm = func_to_ecm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	/* Control interface has only altsetting 0 */
+	if (intf == ecm->ctrl_id) {
+		if (alt != 0)
+			goto fail;
+
+		if (ecm->notify->driver_data) {
+			VDBG(cdev, "reset ecm control %d\n", intf);
+			usb_ep_disable(ecm->notify);
+		} else {
+			VDBG(cdev, "init ecm ctrl %d\n", intf);
+			ecm->notify_desc = ep_choose(cdev->gadget,
+					ecm->hs.notify,
+					ecm->fs.notify);
+		}
+		usb_ep_enable(ecm->notify, ecm->notify_desc);
+		ecm->notify->driver_data = ecm;
+
+	/* Data interface has two altsettings, 0 and 1 */
+	} else if (intf == ecm->data_id) {
+		if (alt > 1)
+			goto fail;
+
+		if (ecm->port.in_ep->driver_data) {
+			DBG(cdev, "reset ecm\n");
+			gether_disconnect(&ecm->port);
+		}
+
+		if (!ecm->port.in) {
+			DBG(cdev, "init ecm\n");
+			ecm->port.in = ep_choose(cdev->gadget,
+					ecm->hs.in, ecm->fs.in);
+			ecm->port.out = ep_choose(cdev->gadget,
+					ecm->hs.out, ecm->fs.out);
+		}
+
+		/* CDC Ethernet only sends data in non-default altsettings.
+		 * Changing altsettings resets filters, statistics, etc.
+		 */
+		if (alt == 1) {
+			struct net_device	*net;
+
+			/* Enable zlps by default for ECM conformance;
+			 * override for musb_hdrc (avoids txdma ovhead)
+			 * and sa1100 (can't).
+			 */
+			ecm->port.is_zlp_ok = !(
+				   gadget_is_sa1100(cdev->gadget)
+				|| gadget_is_musbhdrc(cdev->gadget)
+				);
+			ecm->port.cdc_filter = DEFAULT_FILTER;
+			DBG(cdev, "activate ecm\n");
+			net = gether_connect(&ecm->port);
+			if (IS_ERR(net))
+				return PTR_ERR(net);
+		}
+
+		/* NOTE this can be a minor disagreement with the ECM spec,
+		 * which says speed notifications will "always" follow
+		 * connection notifications.  But we allow one connect to
+		 * follow another (if the first is in flight), and instead
+		 * just guarantee that a speed notification is always sent.
+		 */
+		ecm_notify(ecm);
+	} else
+		goto fail;
+
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+/* Because the data interface supports multiple altsettings,
+ * this ECM function *MUST* implement a get_alt() method.
+ */
+static int ecm_get_alt(struct usb_function *f, unsigned intf)
+{
+	struct f_ecm		*ecm = func_to_ecm(f);
+
+	if (intf == ecm->ctrl_id)
+		return 0;
+	return ecm->port.in_ep->driver_data ? 1 : 0;
+}
+
+static void ecm_disable(struct usb_function *f)
+{
+	struct f_ecm		*ecm = func_to_ecm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	DBG(cdev, "ecm deactivated\n");
+
+	if (ecm->port.in_ep->driver_data)
+		gether_disconnect(&ecm->port);
+
+	if (ecm->notify->driver_data) {
+		usb_ep_disable(ecm->notify);
+		ecm->notify->driver_data = NULL;
+		ecm->notify_desc = NULL;
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Callbacks let us notify the host about connect/disconnect when the
+ * net device is opened or closed.
+ *
+ * For testing, note that link states on this side include both opened
+ * and closed variants of:
+ *
+ *   - disconnected/unconfigured
+ *   - configured but inactive (data alt 0)
+ *   - configured and active (data alt 1)
+ *
+ * Each needs to be tested with unplug, rmmod, SET_CONFIGURATION, and
+ * SET_INTERFACE (altsetting).  Remember also that "configured" doesn't
+ * imply the host is actually polling the notification endpoint, and
+ * likewise that "active" doesn't imply it's actually using the data
+ * endpoints for traffic.
+ */
+
+static void ecm_open(struct gether *geth)
+{
+	struct f_ecm		*ecm = func_to_ecm(&geth->func);
+
+	DBG(ecm->port.func.config->cdev, "%s\n", __func__);
+
+	ecm->is_open = true;
+	ecm_notify(ecm);
+}
+
+static void ecm_close(struct gether *geth)
+{
+	struct f_ecm		*ecm = func_to_ecm(&geth->func);
+
+	DBG(ecm->port.func.config->cdev, "%s\n", __func__);
+
+	ecm->is_open = false;
+	ecm_notify(ecm);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* ethernet function driver setup/binding */
+
+static int __init
+ecm_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_ecm		*ecm = func_to_ecm(f);
+	int			status;
+	struct usb_ep		*ep;
+
+	/* allocate instance-specific interface IDs */
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	ecm->ctrl_id = status;
+
+	ecm_control_intf.bInterfaceNumber = status;
+	ecm_union_desc.bMasterInterface0 = status;
+
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	ecm->data_id = status;
+
+	ecm_data_nop_intf.bInterfaceNumber = status;
+	ecm_data_intf.bInterfaceNumber = status;
+	ecm_union_desc.bSlaveInterface0 = status;
+
+	status = -ENODEV;
+
+	/* allocate instance-specific endpoints */
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+	if (!ep)
+		goto fail;
+	ecm->port.in_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+	if (!ep)
+		goto fail;
+	ecm->port.out_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	/* NOTE:  a status/notification endpoint is *OPTIONAL* but we
+	 * don't treat it that way.  It's simpler, and some newer CDC
+	 * profiles (wireless handsets) no longer treat it as optional.
+	 */
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc);
+	if (!ep)
+		goto fail;
+	ecm->notify = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	status = -ENOMEM;
+
+	/* allocate notification request and buffer */
+	ecm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
+	if (!ecm->notify_req)
+		goto fail;
+	ecm->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL);
+	if (!ecm->notify_req->buf)
+		goto fail;
+	ecm->notify_req->context = ecm;
+	ecm->notify_req->complete = ecm_notify_complete;
+
+	/* copy descriptors, and track endpoint copies */
+	f->descriptors = usb_copy_descriptors(eth_fs_function);
+	if (!f->descriptors)
+		goto fail;
+
+	ecm->fs.in = usb_find_endpoint(eth_fs_function,
+			f->descriptors, &fs_in_desc);
+	ecm->fs.out = usb_find_endpoint(eth_fs_function,
+			f->descriptors, &fs_out_desc);
+	ecm->fs.notify = usb_find_endpoint(eth_fs_function,
+			f->descriptors, &fs_notify_desc);
+
+	/* support all relevant hardware speeds... we expect that when
+	 * hardware is dual speed, all bulk-capable endpoints work at
+	 * both speeds
+	 */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		hs_in_desc.bEndpointAddress =
+				fs_in_desc.bEndpointAddress;
+		hs_out_desc.bEndpointAddress =
+				fs_out_desc.bEndpointAddress;
+		hs_notify_desc.bEndpointAddress =
+				fs_notify_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
+		if (!f->hs_descriptors)
+			goto fail;
+
+		ecm->hs.in = usb_find_endpoint(eth_hs_function,
+				f->hs_descriptors, &hs_in_desc);
+		ecm->hs.out = usb_find_endpoint(eth_hs_function,
+				f->hs_descriptors, &hs_out_desc);
+		ecm->hs.notify = usb_find_endpoint(eth_hs_function,
+				f->hs_descriptors, &hs_notify_desc);
+	}
+
+	/* NOTE:  all that is done without knowing or caring about
+	 * the network link ... which is unavailable to this code
+	 * until we're activated via set_alt().
+	 */
+
+	ecm->port.open = ecm_open;
+	ecm->port.close = ecm_close;
+
+	DBG(cdev, "CDC Ethernet: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			ecm->port.in_ep->name, ecm->port.out_ep->name,
+			ecm->notify->name);
+	return 0;
+
+fail:
+	if (f->descriptors)
+		usb_free_descriptors(f->descriptors);
+
+	if (ecm->notify_req) {
+		kfree(ecm->notify_req->buf);
+		usb_ep_free_request(ecm->notify, ecm->notify_req);
+	}
+
+	/* we might as well release our claims on endpoints */
+	if (ecm->notify)
+		ecm->notify->driver_data = NULL;
+	if (ecm->port.out)
+		ecm->port.out_ep->driver_data = NULL;
+	if (ecm->port.in)
+		ecm->port.in_ep->driver_data = NULL;
+
+	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+
+	return status;
+}
+
+static void
+ecm_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_ecm		*ecm = func_to_ecm(f);
+
+	DBG(c->cdev, "ecm unbind\n");
+
+	if (gadget_is_dualspeed(c->cdev->gadget))
+		usb_free_descriptors(f->hs_descriptors);
+	usb_free_descriptors(f->descriptors);
+
+	kfree(ecm->notify_req->buf);
+	usb_ep_free_request(ecm->notify, ecm->notify_req);
+
+	ecm_string_defs[1].s = NULL;
+	kfree(ecm);
+}
+
+/**
+ * ecm_bind_config - add CDC Ethernet network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ *	side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup().  Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+int __init ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+	struct f_ecm	*ecm;
+	int		status;
+
+	if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
+		return -EINVAL;
+
+	/* maybe allocate device-global string IDs */
+	if (ecm_string_defs[0].id == 0) {
+
+		/* control interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		ecm_string_defs[0].id = status;
+		ecm_control_intf.iInterface = status;
+
+		/* data interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		ecm_string_defs[2].id = status;
+		ecm_data_intf.iInterface = status;
+
+		/* MAC address */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		ecm_string_defs[1].id = status;
+		ether_desc.iMACAddress = status;
+	}
+
+	/* allocate and initialize one new instance */
+	ecm = kzalloc(sizeof *ecm, GFP_KERNEL);
+	if (!ecm)
+		return -ENOMEM;
+
+	/* export host's Ethernet address in CDC format */
+	snprintf(ecm->ethaddr, sizeof ecm->ethaddr,
+		"%02X%02X%02X%02X%02X%02X",
+		ethaddr[0], ethaddr[1], ethaddr[2],
+		ethaddr[3], ethaddr[4], ethaddr[5]);
+	ecm_string_defs[1].s = ecm->ethaddr;
+
+	ecm->port.cdc_filter = DEFAULT_FILTER;
+
+	ecm->port.func.name = "cdc_ethernet";
+	ecm->port.func.strings = ecm_strings;
+	/* descriptors are per-instance copies */
+	ecm->port.func.bind = ecm_bind;
+	ecm->port.func.unbind = ecm_unbind;
+	ecm->port.func.set_alt = ecm_set_alt;
+	ecm->port.func.get_alt = ecm_get_alt;
+	ecm->port.func.setup = ecm_setup;
+	ecm->port.func.disable = ecm_disable;
+
+	status = usb_add_function(c, &ecm->port.func);
+	if (status) {
+		ecm_string_defs[1].s = NULL;
+		kfree(ecm);
+	}
+	return status;
+}
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
new file mode 100644
index 0000000..eda4cde
--- /dev/null
+++ b/drivers/usb/gadget/f_loopback.c
@@ -0,0 +1,381 @@
+/*
+ * f_loopback.c - USB peripheral loopback configuration driver
+ *
+ * Copyright (C) 2003-2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+
+#include "g_zero.h"
+#include "gadget_chips.h"
+
+
+/*
+ * LOOPBACK FUNCTION ... a testing vehicle for USB peripherals,
+ *
+ * This takes messages of various sizes written OUT to a device, and loops
+ * them back so they can be read IN from it.  It has been used by certain
+ * test applications.  It supports limited testing of data queueing logic.
+ *
+ *
+ * This is currently packaged as a configuration driver, which can't be
+ * combined with other functions to make composite devices.  However, it
+ * can be combined with other independent configurations.
+ */
+struct f_loopback {
+	struct usb_function	function;
+
+	struct usb_ep		*in_ep;
+	struct usb_ep		*out_ep;
+};
+
+static inline struct f_loopback *func_to_loop(struct usb_function *f)
+{
+	return container_of(f, struct f_loopback, function);
+}
+
+static unsigned qlen = 32;
+module_param(qlen, uint, 0);
+MODULE_PARM_DESC(qlenn, "depth of loopback queue");
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_interface_descriptor loopback_intf = {
+	.bLength =		sizeof loopback_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
+	/* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_source_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_sink_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *fs_loopback_descs[] = {
+	(struct usb_descriptor_header *) &loopback_intf,
+	(struct usb_descriptor_header *) &fs_sink_desc,
+	(struct usb_descriptor_header *) &fs_source_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_source_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_sink_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *hs_loopback_descs[] = {
+	(struct usb_descriptor_header *) &loopback_intf,
+	(struct usb_descriptor_header *) &hs_source_desc,
+	(struct usb_descriptor_header *) &hs_sink_desc,
+	NULL,
+};
+
+/* function-specific strings: */
+
+static struct usb_string strings_loopback[] = {
+	[0].s = "loop input to output",
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab_loop = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_loopback,
+};
+
+static struct usb_gadget_strings *loopback_strings[] = {
+	&stringtab_loop,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init
+loopback_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_loopback	*loop = func_to_loop(f);
+	int			id;
+
+	/* allocate interface ID(s) */
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	loopback_intf.bInterfaceNumber = id;
+
+	/* allocate endpoints */
+
+	loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
+	if (!loop->in_ep) {
+autoconf_fail:
+		ERROR(cdev, "%s: can't autoconfigure on %s\n",
+			f->name, cdev->gadget->name);
+		return -ENODEV;
+	}
+	loop->in_ep->driver_data = cdev;	/* claim */
+
+	loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
+	if (!loop->out_ep)
+		goto autoconf_fail;
+	loop->out_ep->driver_data = cdev;	/* claim */
+
+	/* support high speed hardware */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		hs_source_desc.bEndpointAddress =
+				fs_source_desc.bEndpointAddress;
+		hs_sink_desc.bEndpointAddress =
+				fs_sink_desc.bEndpointAddress;
+		f->hs_descriptors = hs_loopback_descs;
+	}
+
+	DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			f->name, loop->in_ep->name, loop->out_ep->name);
+	return 0;
+}
+
+static void
+loopback_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	kfree(func_to_loop(f));
+}
+
+static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_loopback	*loop = ep->driver_data;
+	struct usb_composite_dev *cdev = loop->function.config->cdev;
+	int			status = req->status;
+
+	switch (status) {
+
+	case 0:				/* normal completion? */
+		if (ep == loop->out_ep) {
+			/* loop this OUT packet back IN to the host */
+			req->zero = (req->actual < req->length);
+			req->length = req->actual;
+			status = usb_ep_queue(loop->in_ep, req, GFP_ATOMIC);
+			if (status == 0)
+				return;
+
+			/* "should never get here" */
+			ERROR(cdev, "can't loop %s to %s: %d\n",
+				ep->name, loop->in_ep->name,
+				status);
+		}
+
+		/* queue the buffer for some later OUT packet */
+		req->length = buflen;
+		status = usb_ep_queue(loop->out_ep, req, GFP_ATOMIC);
+		if (status == 0)
+			return;
+
+		/* "should never get here" */
+		/* FALLTHROUGH */
+
+	default:
+		ERROR(cdev, "%s loop complete --> %d, %d/%d\n", ep->name,
+				status, req->actual, req->length);
+		/* FALLTHROUGH */
+
+	/* NOTE:  since this driver doesn't maintain an explicit record
+	 * of requests it submitted (just maintains qlen count), we
+	 * rely on the hardware driver to clean up on disconnect or
+	 * endpoint disable.
+	 */
+	case -ECONNABORTED:		/* hardware forced ep reset */
+	case -ECONNRESET:		/* request dequeued */
+	case -ESHUTDOWN:		/* disconnect from host */
+		free_ep_req(ep, req);
+		return;
+	}
+}
+
+static void disable_loopback(struct f_loopback *loop)
+{
+	struct usb_composite_dev	*cdev;
+
+	cdev = loop->function.config->cdev;
+	disable_endpoints(cdev, loop->in_ep, loop->out_ep);
+	VDBG(cdev, "%s disabled\n", loop->function.name);
+}
+
+static int
+enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
+{
+	int					result = 0;
+	const struct usb_endpoint_descriptor	*src, *sink;
+	struct usb_ep				*ep;
+	struct usb_request			*req;
+	unsigned				i;
+
+	src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc);
+	sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc);
+
+	/* one endpoint writes data back IN to the host */
+	ep = loop->in_ep;
+	result = usb_ep_enable(ep, src);
+	if (result < 0)
+		return result;
+	ep->driver_data = loop;
+
+	/* one endpoint just reads OUT packets */
+	ep = loop->out_ep;
+	result = usb_ep_enable(ep, sink);
+	if (result < 0) {
+fail0:
+		ep = loop->in_ep;
+		usb_ep_disable(ep);
+		ep->driver_data = NULL;
+		return result;
+	}
+	ep->driver_data = loop;
+
+	/* allocate a bunch of read buffers and queue them all at once.
+	 * we buffer at most 'qlen' transfers; fewer if any need more
+	 * than 'buflen' bytes each.
+	 */
+	for (i = 0; i < qlen && result == 0; i++) {
+		req = alloc_ep_req(ep);
+		if (req) {
+			req->complete = loopback_complete;
+			result = usb_ep_queue(ep, req, GFP_ATOMIC);
+			if (result)
+				ERROR(cdev, "%s queue req --> %d\n",
+						ep->name, result);
+		} else {
+			usb_ep_disable(ep);
+			ep->driver_data = NULL;
+			result = -ENOMEM;
+			goto fail0;
+		}
+	}
+
+	DBG(cdev, "%s enabled\n", loop->function.name);
+	return result;
+}
+
+static int loopback_set_alt(struct usb_function *f,
+		unsigned intf, unsigned alt)
+{
+	struct f_loopback	*loop = func_to_loop(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	/* we know alt is zero */
+	if (loop->in_ep->driver_data)
+		disable_loopback(loop);
+	return enable_loopback(cdev, loop);
+}
+
+static void loopback_disable(struct usb_function *f)
+{
+	struct f_loopback	*loop = func_to_loop(f);
+
+	disable_loopback(loop);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __init loopback_bind_config(struct usb_configuration *c)
+{
+	struct f_loopback	*loop;
+	int			status;
+
+	loop = kzalloc(sizeof *loop, GFP_KERNEL);
+	if (!loop)
+		return -ENOMEM;
+
+	loop->function.name = "loopback";
+	loop->function.descriptors = fs_loopback_descs;
+	loop->function.bind = loopback_bind;
+	loop->function.unbind = loopback_unbind;
+	loop->function.set_alt = loopback_set_alt;
+	loop->function.disable = loopback_disable;
+
+	status = usb_add_function(c, &loop->function);
+	if (status)
+		kfree(loop);
+	return status;
+}
+
+static struct usb_configuration loopback_driver = {
+	.label		= "loopback",
+	.strings	= loopback_strings,
+	.bind		= loopback_bind_config,
+	.bConfigurationValue = 2,
+	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower	= 1,	/* 2 mA, minimal */
+	/* .iConfiguration = DYNAMIC */
+};
+
+/**
+ * loopback_add - add a loopback testing configuration to a device
+ * @cdev: the device to support the loopback configuration
+ */
+int __init loopback_add(struct usb_composite_dev *cdev)
+{
+	int id;
+
+	/* allocate string ID(s) */
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+	strings_loopback[0].id = id;
+
+	loopback_intf.iInterface = id;
+	loopback_driver.iConfiguration = id;
+
+	/* support OTG systems */
+	if (gadget_is_otg(cdev->gadget)) {
+		loopback_driver.descriptors = otg_desc;
+		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
+	return usb_add_config(cdev, &loopback_driver);
+}
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
new file mode 100644
index 0000000..659b3d9
--- /dev/null
+++ b/drivers/usb/gadget/f_rndis.c
@@ -0,0 +1,825 @@
+/*
+ * f_rndis.c -- RNDIS link function driver
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+
+#include <asm/atomic.h>
+
+#include "u_ether.h"
+#include "rndis.h"
+
+
+/*
+ * This function is an RNDIS Ethernet port -- a Microsoft protocol that's
+ * been promoted instead of the standard CDC Ethernet.  The published RNDIS
+ * spec is ambiguous, incomplete, and needlessly complex.  Variants such as
+ * ActiveSync have even worse status in terms of specification.
+ *
+ * In short:  it's a protocol controlled by (and for) Microsoft, not for an
+ * Open ecosystem or markets.  Linux supports it *only* because Microsoft
+ * doesn't support the CDC Ethernet standard.
+ *
+ * The RNDIS data transfer model is complex, with multiple Ethernet packets
+ * per USB message, and out of band data.  The control model is built around
+ * what's essentially an "RNDIS RPC" protocol.  It's all wrapped in a CDC ACM
+ * (modem, not Ethernet) veneer, with those ACM descriptors being entirely
+ * useless (they're ignored).  RNDIS expects to be the only function in its
+ * configuration, so it's no real help if you need composite devices; and
+ * it expects to be the first configuration too.
+ *
+ * There is a single technical advantage of RNDIS over CDC Ethernet, if you
+ * discount the fluff that its RPC can be made to deliver: it doesn't need
+ * a NOP altsetting for the data interface.  That lets it work on some of the
+ * "so smart it's stupid" hardware which takes over configuration changes
+ * from the software, and adds restrictions like "no altsettings".
+ *
+ * Unfortunately MSFT's RNDIS drivers are buggy.  They hang or oops, and
+ * have all sorts of contrary-to-specification oddities that can prevent
+ * them from working sanely.  Since bugfixes (or accurate specs, letting
+ * Linux work around those bugs) are unlikely to ever come from MSFT, you
+ * may want to avoid using RNDIS on purely operational grounds.
+ *
+ * Omissions from the RNDIS 1.0 specification include:
+ *
+ *   - Power management ... references data that's scattered around lots
+ *     of other documentation, which is incorrect/incomplete there too.
+ *
+ *   - There are various undocumented protocol requirements, like the need
+ *     to send garbage in some control-OUT messages.
+ *
+ *   - MS-Windows drivers sometimes emit undocumented requests.
+ */
+
+struct rndis_ep_descs {
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+	struct usb_endpoint_descriptor	*notify;
+};
+
+struct f_rndis {
+	struct gether			port;
+	u8				ctrl_id, data_id;
+	u8				ethaddr[ETH_ALEN];
+	int				config;
+
+	struct rndis_ep_descs		fs;
+	struct rndis_ep_descs		hs;
+
+	struct usb_ep			*notify;
+	struct usb_endpoint_descriptor	*notify_desc;
+	struct usb_request		*notify_req;
+	atomic_t			notify_count;
+};
+
+static inline struct f_rndis *func_to_rndis(struct usb_function *f)
+{
+	return container_of(f, struct f_rndis, port.func);
+}
+
+/* peak (theoretical) bulk transfer rate in bits-per-second */
+static unsigned int bitrate(struct usb_gadget *g)
+{
+	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+		return 13 * 512 * 8 * 1000 * 8;
+	else
+		return 19 *  64 * 1 * 1000 * 8;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ */
+
+#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
+#define STATUS_BYTECOUNT		8	/* 8 bytes data */
+
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor rndis_control_intf __initdata = {
+	.bLength =		sizeof rndis_control_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	/* .bInterfaceNumber = DYNAMIC */
+	/* status endpoint is optional; this could be patched later */
+	.bNumEndpoints =	1,
+	.bInterfaceClass =	USB_CLASS_COMM,
+	.bInterfaceSubClass =   USB_CDC_SUBCLASS_ACM,
+	.bInterfaceProtocol =   USB_CDC_ACM_PROTO_VENDOR,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc header_desc __initdata = {
+	.bLength =		sizeof header_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
+
+	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = {
+	.bLength =		sizeof call_mgmt_descriptor,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_CALL_MANAGEMENT_TYPE,
+
+	.bmCapabilities =	0x00,
+	.bDataInterface =	0x01,
+};
+
+static struct usb_cdc_acm_descriptor acm_descriptor __initdata = {
+	.bLength =		sizeof acm_descriptor,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
+
+	.bmCapabilities =	0x00,
+};
+
+static struct usb_cdc_union_desc rndis_union_desc __initdata = {
+	.bLength =		sizeof(rndis_union_desc),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
+	/* .bMasterInterface0 =	DYNAMIC */
+	/* .bSlaveInterface0 =	DYNAMIC */
+};
+
+/* the data interface has two bulk endpoints */
+
+static struct usb_interface_descriptor rndis_data_intf __initdata = {
+	.bLength =		sizeof rndis_data_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	/* .bInterfaceNumber = DYNAMIC */
+	.bAlternateSetting =	1,
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_CDC_DATA,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	__constant_cpu_to_le16(STATUS_BYTECOUNT),
+	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
+};
+
+static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *eth_fs_function[] __initdata = {
+	/* control interface matches ACM, not Ethernet */
+	(struct usb_descriptor_header *) &rndis_control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &acm_descriptor,
+	(struct usb_descriptor_header *) &rndis_union_desc,
+	(struct usb_descriptor_header *) &fs_notify_desc,
+	/* data interface has no altsetting */
+	(struct usb_descriptor_header *) &rndis_data_intf,
+	(struct usb_descriptor_header *) &fs_in_desc,
+	(struct usb_descriptor_header *) &fs_out_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	__constant_cpu_to_le16(STATUS_BYTECOUNT),
+	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
+};
+static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *eth_hs_function[] __initdata = {
+	/* control interface matches ACM, not Ethernet */
+	(struct usb_descriptor_header *) &rndis_control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &acm_descriptor,
+	(struct usb_descriptor_header *) &rndis_union_desc,
+	(struct usb_descriptor_header *) &hs_notify_desc,
+	/* data interface has no altsetting */
+	(struct usb_descriptor_header *) &rndis_data_intf,
+	(struct usb_descriptor_header *) &hs_in_desc,
+	(struct usb_descriptor_header *) &hs_out_desc,
+	NULL,
+};
+
+/* string descriptors: */
+
+static struct usb_string rndis_string_defs[] = {
+	[0].s = "RNDIS Communications Control",
+	[1].s = "RNDIS Ethernet Data",
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings rndis_string_table = {
+	.language =		0x0409,	/* en-us */
+	.strings =		rndis_string_defs,
+};
+
+static struct usb_gadget_strings *rndis_strings[] = {
+	&rndis_string_table,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static struct sk_buff *rndis_add_header(struct sk_buff *skb)
+{
+	skb = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type));
+	if (skb)
+		rndis_add_hdr(skb);
+	return skb;
+}
+
+static void rndis_response_available(void *_rndis)
+{
+	struct f_rndis			*rndis = _rndis;
+	struct usb_request		*req = rndis->notify_req;
+	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;
+	__le32				*data = req->buf;
+	int				status;
+
+	if (atomic_inc_return(&rndis->notify_count))
+		return;
+
+	/* Send RNDIS RESPONSE_AVAILABLE notification; a
+	 * USB_CDC_NOTIFY_RESPONSE_AVAILABLE "should" work too
+	 *
+	 * This is the only notification defined by RNDIS.
+	 */
+	data[0] = cpu_to_le32(1);
+	data[1] = cpu_to_le32(0);
+
+	status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC);
+	if (status) {
+		atomic_dec(&rndis->notify_count);
+		DBG(cdev, "notify/0 --> %d\n", status);
+	}
+}
+
+static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_rndis			*rndis = req->context;
+	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;
+	int				status = req->status;
+
+	/* after TX:
+	 *  - USB_CDC_GET_ENCAPSULATED_RESPONSE (ep0/control)
+	 *  - RNDIS_RESPONSE_AVAILABLE (status/irq)
+	 */
+	switch (status) {
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		/* connection gone */
+		atomic_set(&rndis->notify_count, 0);
+		break;
+	default:
+		DBG(cdev, "RNDIS %s response error %d, %d/%d\n",
+			ep->name, status,
+			req->actual, req->length);
+		/* FALLTHROUGH */
+	case 0:
+		if (ep != rndis->notify)
+			break;
+
+		/* handle multiple pending RNDIS_RESPONSE_AVAILABLE
+		 * notifications by resending until we're done
+		 */
+		if (atomic_dec_and_test(&rndis->notify_count))
+			break;
+		status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC);
+		if (status) {
+			atomic_dec(&rndis->notify_count);
+			DBG(cdev, "notify/1 --> %d\n", status);
+		}
+		break;
+	}
+}
+
+static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_rndis			*rndis = req->context;
+	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;
+	int				status;
+
+	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
+//	spin_lock(&dev->lock);
+	status = rndis_msg_parser(rndis->config, (u8 *) req->buf);
+	if (status < 0)
+		ERROR(cdev, "RNDIS command error %d, %d/%d\n",
+			status, req->actual, req->length);
+//	spin_unlock(&dev->lock);
+}
+
+static int
+rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct f_rndis		*rndis = func_to_rndis(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct usb_request	*req = cdev->req;
+	int			value = -EOPNOTSUPP;
+	u16			w_index = le16_to_cpu(ctrl->wIndex);
+	u16			w_value = le16_to_cpu(ctrl->wValue);
+	u16			w_length = le16_to_cpu(ctrl->wLength);
+
+	/* composite driver infrastructure handles everything except
+	 * CDC class messages; interface activation uses set_alt().
+	 */
+	switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+
+	/* RNDIS uses the CDC command encapsulation mechanism to implement
+	 * an RPC scheme, with much getting/setting of attributes by OID.
+	 */
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_SEND_ENCAPSULATED_COMMAND:
+		if (w_length > req->length || w_value
+				|| w_index != rndis->ctrl_id)
+			goto invalid;
+		/* read the request; process it later */
+		value = w_length;
+		req->complete = rndis_command_complete;
+		req->context = rndis;
+		/* later, rndis_response_available() sends a notification */
+		break;
+
+	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_GET_ENCAPSULATED_RESPONSE:
+		if (w_value || w_index != rndis->ctrl_id)
+			goto invalid;
+		else {
+			u8 *buf;
+			u32 n;
+
+			/* return the result */
+			buf = rndis_get_next_response(rndis->config, &n);
+			if (buf) {
+				memcpy(req->buf, buf, n);
+				req->complete = rndis_response_complete;
+				rndis_free_response(rndis->config, buf);
+				value = n;
+			}
+			/* else stalls ... spec says to avoid that */
+		}
+		break;
+
+	default:
+invalid:
+		VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+	}
+
+	/* respond with data transfer or status phase? */
+	if (value >= 0) {
+		DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+		req->zero = 0;
+		req->length = value;
+		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0)
+			ERROR(cdev, "rndis response on err %d\n", value);
+	}
+
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+
+static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_rndis		*rndis = func_to_rndis(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	/* we know alt == 0 */
+
+	if (intf == rndis->ctrl_id) {
+		if (rndis->notify->driver_data) {
+			VDBG(cdev, "reset rndis control %d\n", intf);
+			usb_ep_disable(rndis->notify);
+		} else {
+			VDBG(cdev, "init rndis ctrl %d\n", intf);
+			rndis->notify_desc = ep_choose(cdev->gadget,
+					rndis->hs.notify,
+					rndis->fs.notify);
+		}
+		usb_ep_enable(rndis->notify, rndis->notify_desc);
+		rndis->notify->driver_data = rndis;
+
+	} else if (intf == rndis->data_id) {
+		struct net_device	*net;
+
+		if (rndis->port.in_ep->driver_data) {
+			DBG(cdev, "reset rndis\n");
+			gether_disconnect(&rndis->port);
+		} else {
+			DBG(cdev, "init rndis\n");
+			rndis->port.in = ep_choose(cdev->gadget,
+					rndis->hs.in, rndis->fs.in);
+			rndis->port.out = ep_choose(cdev->gadget,
+					rndis->hs.out, rndis->fs.out);
+		}
+
+		/* Avoid ZLPs; they can be troublesome. */
+		rndis->port.is_zlp_ok = false;
+
+		/* RNDIS should be in the "RNDIS uninitialized" state,
+		 * either never activated or after rndis_uninit().
+		 *
+		 * We don't want data to flow here until a nonzero packet
+		 * filter is set, at which point it enters "RNDIS data
+		 * initialized" state ... but we do want the endpoints
+		 * to be activated.  It's a strange little state.
+		 *
+		 * REVISIT the RNDIS gadget code has done this wrong for a
+		 * very long time.  We need another call to the link layer
+		 * code -- gether_updown(...bool) maybe -- to do it right.
+		 */
+		rndis->port.cdc_filter = 0;
+
+		DBG(cdev, "RNDIS RX/TX early activation ... \n");
+		net = gether_connect(&rndis->port);
+		if (IS_ERR(net))
+			return PTR_ERR(net);
+
+		rndis_set_param_dev(rndis->config, net,
+				&rndis->port.cdc_filter);
+	} else
+		goto fail;
+
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+static void rndis_disable(struct usb_function *f)
+{
+	struct f_rndis		*rndis = func_to_rndis(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	if (!rndis->notify->driver_data)
+		return;
+
+	DBG(cdev, "rndis deactivated\n");
+
+	rndis_uninit(rndis->config);
+	gether_disconnect(&rndis->port);
+
+	usb_ep_disable(rndis->notify);
+	rndis->notify->driver_data = NULL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * This isn't quite the same mechanism as CDC Ethernet, since the
+ * notification scheme passes less data, but the same set of link
+ * states must be tested.  A key difference is that altsettings are
+ * not used to tell whether the link should send packets or not.
+ */
+
+static void rndis_open(struct gether *geth)
+{
+	struct f_rndis		*rndis = func_to_rndis(&geth->func);
+	struct usb_composite_dev *cdev = geth->func.config->cdev;
+
+	DBG(cdev, "%s\n", __func__);
+
+	rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3,
+				bitrate(cdev->gadget) / 100);
+	rndis_signal_connect(rndis->config);
+}
+
+static void rndis_close(struct gether *geth)
+{
+	struct f_rndis		*rndis = func_to_rndis(&geth->func);
+
+	DBG(geth->func.config->cdev, "%s\n", __func__);
+
+	rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, 0);
+	rndis_signal_disconnect(rndis->config);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* ethernet function driver setup/binding */
+
+static int __init
+rndis_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_rndis		*rndis = func_to_rndis(f);
+	int			status;
+	struct usb_ep		*ep;
+
+	/* allocate instance-specific interface IDs */
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	rndis->ctrl_id = status;
+
+	rndis_control_intf.bInterfaceNumber = status;
+	rndis_union_desc.bMasterInterface0 = status;
+
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	rndis->data_id = status;
+
+	rndis_data_intf.bInterfaceNumber = status;
+	rndis_union_desc.bSlaveInterface0 = status;
+
+	status = -ENODEV;
+
+	/* allocate instance-specific endpoints */
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+	if (!ep)
+		goto fail;
+	rndis->port.in_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+	if (!ep)
+		goto fail;
+	rndis->port.out_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	/* NOTE:  a status/notification endpoint is, strictly speaking,
+	 * optional.  We don't treat it that way though!  It's simpler,
+	 * and some newer profiles don't treat it as optional.
+	 */
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc);
+	if (!ep)
+		goto fail;
+	rndis->notify = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	status = -ENOMEM;
+
+	/* allocate notification request and buffer */
+	rndis->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
+	if (!rndis->notify_req)
+		goto fail;
+	rndis->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL);
+	if (!rndis->notify_req->buf)
+		goto fail;
+	rndis->notify_req->length = STATUS_BYTECOUNT;
+	rndis->notify_req->context = rndis;
+	rndis->notify_req->complete = rndis_response_complete;
+
+	/* copy descriptors, and track endpoint copies */
+	f->descriptors = usb_copy_descriptors(eth_fs_function);
+	if (!f->descriptors)
+		goto fail;
+
+	rndis->fs.in = usb_find_endpoint(eth_fs_function,
+			f->descriptors, &fs_in_desc);
+	rndis->fs.out = usb_find_endpoint(eth_fs_function,
+			f->descriptors, &fs_out_desc);
+	rndis->fs.notify = usb_find_endpoint(eth_fs_function,
+			f->descriptors, &fs_notify_desc);
+
+	/* support all relevant hardware speeds... we expect that when
+	 * hardware is dual speed, all bulk-capable endpoints work at
+	 * both speeds
+	 */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		hs_in_desc.bEndpointAddress =
+				fs_in_desc.bEndpointAddress;
+		hs_out_desc.bEndpointAddress =
+				fs_out_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
+
+		if (!f->hs_descriptors)
+			goto fail;
+
+		rndis->hs.in = usb_find_endpoint(eth_hs_function,
+				f->hs_descriptors, &hs_in_desc);
+		rndis->hs.out = usb_find_endpoint(eth_hs_function,
+				f->hs_descriptors, &hs_out_desc);
+	}
+
+	rndis->port.open = rndis_open;
+	rndis->port.close = rndis_close;
+
+	status = rndis_register(rndis_response_available, rndis);
+	if (status < 0)
+		goto fail;
+	rndis->config = status;
+
+	rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, 0);
+	rndis_set_host_mac(rndis->config, rndis->ethaddr);
+
+#if 0
+// FIXME
+	if (rndis_set_param_vendor(rndis->config, vendorID,
+				manufacturer))
+		goto fail0;
+#endif
+
+	/* NOTE:  all that is done without knowing or caring about
+	 * the network link ... which is unavailable to this code
+	 * until we're activated via set_alt().
+	 */
+
+	DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			rndis->port.in_ep->name, rndis->port.out_ep->name,
+			rndis->notify->name);
+	return 0;
+
+fail:
+	if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
+		usb_free_descriptors(f->hs_descriptors);
+	if (f->descriptors)
+		usb_free_descriptors(f->descriptors);
+
+	if (rndis->notify_req) {
+		kfree(rndis->notify_req->buf);
+		usb_ep_free_request(rndis->notify, rndis->notify_req);
+	}
+
+	/* we might as well release our claims on endpoints */
+	if (rndis->notify)
+		rndis->notify->driver_data = NULL;
+	if (rndis->port.out)
+		rndis->port.out_ep->driver_data = NULL;
+	if (rndis->port.in)
+		rndis->port.in_ep->driver_data = NULL;
+
+	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+
+	return status;
+}
+
+static void
+rndis_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_rndis		*rndis = func_to_rndis(f);
+
+	rndis_deregister(rndis->config);
+	rndis_exit();
+
+	if (gadget_is_dualspeed(c->cdev->gadget))
+		usb_free_descriptors(f->hs_descriptors);
+	usb_free_descriptors(f->descriptors);
+
+	kfree(rndis->notify_req->buf);
+	usb_ep_free_request(rndis->notify, rndis->notify_req);
+
+	kfree(rndis);
+}
+
+/* Some controllers can't support RNDIS ... */
+static inline bool can_support_rndis(struct usb_configuration *c)
+{
+	/* only two endpoints on sa1100 */
+	if (gadget_is_sa1100(c->cdev->gadget))
+		return false;
+
+	/* everything else is *presumably* fine */
+	return true;
+}
+
+/**
+ * rndis_bind_config - add RNDIS network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ *	side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup().  Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+int __init rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+	struct f_rndis	*rndis;
+	int		status;
+
+	if (!can_support_rndis(c) || !ethaddr)
+		return -EINVAL;
+
+	/* maybe allocate device-global string IDs */
+	if (rndis_string_defs[0].id == 0) {
+
+		/* ... and setup RNDIS itself */
+		status = rndis_init();
+		if (status < 0)
+			return status;
+
+		/* control interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		rndis_string_defs[0].id = status;
+		rndis_control_intf.iInterface = status;
+
+		/* data interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		rndis_string_defs[1].id = status;
+		rndis_data_intf.iInterface = status;
+	}
+
+	/* allocate and initialize one new instance */
+	status = -ENOMEM;
+	rndis = kzalloc(sizeof *rndis, GFP_KERNEL);
+	if (!rndis)
+		goto fail;
+
+	memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);
+
+	/* RNDIS activates when the host changes this filter */
+	rndis->port.cdc_filter = 0;
+
+	/* RNDIS has special (and complex) framing */
+	rndis->port.header_len = sizeof(struct rndis_packet_msg_type);
+	rndis->port.wrap = rndis_add_header;
+	rndis->port.unwrap = rndis_rm_hdr;
+
+	rndis->port.func.name = "rndis";
+	rndis->port.func.strings = rndis_strings;
+	/* descriptors are per-instance copies */
+	rndis->port.func.bind = rndis_bind;
+	rndis->port.func.unbind = rndis_unbind;
+	rndis->port.func.set_alt = rndis_set_alt;
+	rndis->port.func.setup = rndis_setup;
+	rndis->port.func.disable = rndis_disable;
+
+	status = usb_add_function(c, &rndis->port.func);
+	if (status) {
+		kfree(rndis);
+fail:
+		rndis_exit();
+	}
+	return status;
+}
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
new file mode 100644
index 0000000..fe5674d
--- /dev/null
+++ b/drivers/usb/gadget/f_serial.c
@@ -0,0 +1,294 @@
+/*
+ * f_serial.c - generic USB serial function driver
+ *
+ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2008 by David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of that License or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+#include "u_serial.h"
+#include "gadget_chips.h"
+
+
+/*
+ * This function packages a simple "generic serial" port with no real
+ * control mechanisms, just raw data transfer over two bulk endpoints.
+ *
+ * Because it's not standardized, this isn't as interoperable as the
+ * CDC ACM driver.  However, for many purposes it's just as functional
+ * if you can arrange appropriate host side drivers.
+ */
+
+struct gser_descs {
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+};
+
+struct f_gser {
+	struct gserial			port;
+	u8				data_id;
+	u8				port_num;
+
+	struct gser_descs		fs;
+	struct gser_descs		hs;
+};
+
+static inline struct f_gser *func_to_gser(struct usb_function *f)
+{
+	return container_of(f, struct f_gser, port.func);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor gser_interface_desc __initdata = {
+	.bLength =		USB_DT_INTERFACE_SIZE,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	/* .bInterfaceNumber = DYNAMIC */
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *gser_fs_function[] __initdata = {
+	(struct usb_descriptor_header *) &gser_interface_desc,
+	(struct usb_descriptor_header *) &gser_fs_in_desc,
+	(struct usb_descriptor_header *) &gser_fs_out_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *gser_hs_function[] __initdata = {
+	(struct usb_descriptor_header *) &gser_interface_desc,
+	(struct usb_descriptor_header *) &gser_hs_in_desc,
+	(struct usb_descriptor_header *) &gser_hs_out_desc,
+	NULL,
+};
+
+/* string descriptors: */
+
+static struct usb_string gser_string_defs[] = {
+	[0].s = "Generic Serial",
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings gser_string_table = {
+	.language =		0x0409,	/* en-us */
+	.strings =		gser_string_defs,
+};
+
+static struct usb_gadget_strings *gser_strings[] = {
+	&gser_string_table,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_gser		*gser = func_to_gser(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	/* we know alt == 0, so this is an activation or a reset */
+
+	if (gser->port.in->driver_data) {
+		DBG(cdev, "reset generic ttyGS%d\n", gser->port_num);
+		gserial_disconnect(&gser->port);
+	} else {
+		DBG(cdev, "activate generic ttyGS%d\n", gser->port_num);
+		gser->port.in_desc = ep_choose(cdev->gadget,
+				gser->hs.in, gser->fs.in);
+		gser->port.out_desc = ep_choose(cdev->gadget,
+				gser->hs.out, gser->fs.out);
+	}
+	gserial_connect(&gser->port, gser->port_num);
+	return 0;
+}
+
+static void gser_disable(struct usb_function *f)
+{
+	struct f_gser	*gser = func_to_gser(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	DBG(cdev, "generic ttyGS%d deactivated\n", gser->port_num);
+	gserial_disconnect(&gser->port);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* serial function driver setup/binding */
+
+static int __init
+gser_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_gser		*gser = func_to_gser(f);
+	int			status;
+	struct usb_ep		*ep;
+
+	/* allocate instance-specific interface IDs */
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	gser->data_id = status;
+	gser_interface_desc.bInterfaceNumber = status;
+
+	status = -ENODEV;
+
+	/* allocate instance-specific endpoints */
+	ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_in_desc);
+	if (!ep)
+		goto fail;
+	gser->port.in = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_out_desc);
+	if (!ep)
+		goto fail;
+	gser->port.out = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	/* copy descriptors, and track endpoint copies */
+	f->descriptors = usb_copy_descriptors(gser_fs_function);
+
+	gser->fs.in = usb_find_endpoint(gser_fs_function,
+			f->descriptors, &gser_fs_in_desc);
+	gser->fs.out = usb_find_endpoint(gser_fs_function,
+			f->descriptors, &gser_fs_out_desc);
+
+
+	/* support all relevant hardware speeds... we expect that when
+	 * hardware is dual speed, all bulk-capable endpoints work at
+	 * both speeds
+	 */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		gser_hs_in_desc.bEndpointAddress =
+				gser_fs_in_desc.bEndpointAddress;
+		gser_hs_out_desc.bEndpointAddress =
+				gser_fs_out_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
+
+		gser->hs.in = usb_find_endpoint(gser_hs_function,
+				f->hs_descriptors, &gser_hs_in_desc);
+		gser->hs.out = usb_find_endpoint(gser_hs_function,
+				f->hs_descriptors, &gser_hs_out_desc);
+	}
+
+	DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
+			gser->port_num,
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			gser->port.in->name, gser->port.out->name);
+	return 0;
+
+fail:
+	/* we might as well release our claims on endpoints */
+	if (gser->port.out)
+		gser->port.out->driver_data = NULL;
+	if (gser->port.in)
+		gser->port.in->driver_data = NULL;
+
+	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+
+	return status;
+}
+
+static void
+gser_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	if (gadget_is_dualspeed(c->cdev->gadget))
+		usb_free_descriptors(f->hs_descriptors);
+	usb_free_descriptors(f->descriptors);
+	kfree(func_to_gser(f));
+}
+
+/**
+ * gser_bind_config - add a generic serial function to a configuration
+ * @c: the configuration to support the serial instance
+ * @port_num: /dev/ttyGS* port this interface will use
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gserial_setup() with enough ports to
+ * handle all the ones it binds.  Caller is also responsible
+ * for calling @gserial_cleanup() before module unload.
+ */
+int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
+{
+	struct f_gser	*gser;
+	int		status;
+
+	/* REVISIT might want instance-specific strings to help
+	 * distinguish instances ...
+	 */
+
+	/* maybe allocate device-global string ID */
+	if (gser_string_defs[0].id == 0) {
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		gser_string_defs[0].id = status;
+	}
+
+	/* allocate and initialize one new instance */
+	gser = kzalloc(sizeof *gser, GFP_KERNEL);
+	if (!gser)
+		return -ENOMEM;
+
+	gser->port_num = port_num;
+
+	gser->port.func.name = "gser";
+	gser->port.func.strings = gser_strings;
+	gser->port.func.bind = gser_bind;
+	gser->port.func.unbind = gser_unbind;
+	gser->port.func.set_alt = gser_set_alt;
+	gser->port.func.disable = gser_disable;
+
+	status = usb_add_function(c, &gser->port.func);
+	if (status)
+		kfree(gser);
+	return status;
+}
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
new file mode 100644
index 0000000..f18c3a1
--- /dev/null
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -0,0 +1,587 @@
+/*
+ * f_sourcesink.c - USB peripheral source/sink configuration driver
+ *
+ * Copyright (C) 2003-2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+
+#include "g_zero.h"
+#include "gadget_chips.h"
+
+
+/*
+ * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral
+ * controller drivers.
+ *
+ * This just sinks bulk packets OUT to the peripheral and sources them IN
+ * to the host, optionally with specific data patterns for integrity tests.
+ * As such it supports basic functionality and load tests.
+ *
+ * In terms of control messaging, this supports all the standard requests
+ * plus two that support control-OUT tests.  If the optional "autoresume"
+ * mode is enabled, it provides good functional coverage for the "USBCV"
+ * test harness from USB-IF.
+ *
+ * Note that because this doesn't queue more than one request at a time,
+ * some other function must be used to test queueing logic.  The network
+ * link (g_ether) is the best overall option for that, since its TX and RX
+ * queues are relatively independent, will receive a range of packet sizes,
+ * and can often be made to run out completely.  Those issues are important
+ * when stress testing peripheral controller drivers.
+ *
+ *
+ * This is currently packaged as a configuration driver, which can't be
+ * combined with other functions to make composite devices.  However, it
+ * can be combined with other independent configurations.
+ */
+struct f_sourcesink {
+	struct usb_function	function;
+
+	struct usb_ep		*in_ep;
+	struct usb_ep		*out_ep;
+	struct timer_list	resume;
+};
+
+static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
+{
+	return container_of(f, struct f_sourcesink, function);
+}
+
+static unsigned autoresume;
+module_param(autoresume, uint, 0);
+MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
+
+static unsigned pattern;
+module_param(pattern, uint, 0);
+MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 ");
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_interface_descriptor source_sink_intf = {
+	.bLength =		sizeof source_sink_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
+	/* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_source_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_sink_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *fs_source_sink_descs[] = {
+	(struct usb_descriptor_header *) &source_sink_intf,
+	(struct usb_descriptor_header *) &fs_sink_desc,
+	(struct usb_descriptor_header *) &fs_source_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_source_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_sink_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *hs_source_sink_descs[] = {
+	(struct usb_descriptor_header *) &source_sink_intf,
+	(struct usb_descriptor_header *) &hs_source_desc,
+	(struct usb_descriptor_header *) &hs_sink_desc,
+	NULL,
+};
+
+/* function-specific strings: */
+
+static struct usb_string strings_sourcesink[] = {
+	[0].s = "source and sink data",
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab_sourcesink = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_sourcesink,
+};
+
+static struct usb_gadget_strings *sourcesink_strings[] = {
+	&stringtab_sourcesink,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static void sourcesink_autoresume(unsigned long _c)
+{
+	struct usb_composite_dev *cdev = (void *)_c;
+	struct usb_gadget	*g = cdev->gadget;
+
+	/* Normally the host would be woken up for something
+	 * more significant than just a timer firing; likely
+	 * because of some direct user request.
+	 */
+	if (g->speed != USB_SPEED_UNKNOWN) {
+		int status = usb_gadget_wakeup(g);
+		DBG(cdev, "%s --> %d\n", __func__, status);
+	}
+}
+
+static int __init
+sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_sourcesink	*ss = func_to_ss(f);
+	int	id;
+
+	/* allocate interface ID(s) */
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	source_sink_intf.bInterfaceNumber = id;
+
+	/* allocate endpoints */
+	ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
+	if (!ss->in_ep) {
+autoconf_fail:
+		ERROR(cdev, "%s: can't autoconfigure on %s\n",
+			f->name, cdev->gadget->name);
+		return -ENODEV;
+	}
+	ss->in_ep->driver_data = cdev;	/* claim */
+
+	ss->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
+	if (!ss->out_ep)
+		goto autoconf_fail;
+	ss->out_ep->driver_data = cdev;	/* claim */
+
+	setup_timer(&ss->resume, sourcesink_autoresume,
+			(unsigned long) c->cdev);
+
+	/* support high speed hardware */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		hs_source_desc.bEndpointAddress =
+				fs_source_desc.bEndpointAddress;
+		hs_sink_desc.bEndpointAddress =
+				fs_sink_desc.bEndpointAddress;
+		f->hs_descriptors = hs_source_sink_descs;
+	}
+
+	DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			f->name, ss->in_ep->name, ss->out_ep->name);
+	return 0;
+}
+
+static void
+sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	kfree(func_to_ss(f));
+}
+
+/* optionally require specific source/sink data patterns  */
+static int check_read_data(struct f_sourcesink *ss, struct usb_request *req)
+{
+	unsigned		i;
+	u8			*buf = req->buf;
+	struct usb_composite_dev *cdev = ss->function.config->cdev;
+
+	for (i = 0; i < req->actual; i++, buf++) {
+		switch (pattern) {
+
+		/* all-zeroes has no synchronization issues */
+		case 0:
+			if (*buf == 0)
+				continue;
+			break;
+
+		/* "mod63" stays in sync with short-terminated transfers,
+		 * OR otherwise when host and gadget agree on how large
+		 * each usb transfer request should be.  Resync is done
+		 * with set_interface or set_config.  (We *WANT* it to
+		 * get quickly out of sync if controllers or their drivers
+		 * stutter for any reason, including buffer duplcation...)
+		 */
+		case 1:
+			if (*buf == (u8)(i % 63))
+				continue;
+			break;
+		}
+		ERROR(cdev, "bad OUT byte, buf[%d] = %d\n", i, *buf);
+		usb_ep_set_halt(ss->out_ep);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
+{
+	unsigned	i;
+	u8		*buf = req->buf;
+
+	switch (pattern) {
+	case 0:
+		memset(req->buf, 0, req->length);
+		break;
+	case 1:
+		for  (i = 0; i < req->length; i++)
+			*buf++ = (u8) (i % 63);
+		break;
+	}
+}
+
+static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_sourcesink	*ss = ep->driver_data;
+	struct usb_composite_dev *cdev = ss->function.config->cdev;
+	int			status = req->status;
+
+	switch (status) {
+
+	case 0:				/* normal completion? */
+		if (ep == ss->out_ep) {
+			check_read_data(ss, req);
+			memset(req->buf, 0x55, req->length);
+		} else
+			reinit_write_data(ep, req);
+		break;
+
+	/* this endpoint is normally active while we're configured */
+	case -ECONNABORTED:		/* hardware forced ep reset */
+	case -ECONNRESET:		/* request dequeued */
+	case -ESHUTDOWN:		/* disconnect from host */
+		VDBG(cdev, "%s gone (%d), %d/%d\n", ep->name, status,
+				req->actual, req->length);
+		if (ep == ss->out_ep)
+			check_read_data(ss, req);
+		free_ep_req(ep, req);
+		return;
+
+	case -EOVERFLOW:		/* buffer overrun on read means that
+					 * we didn't provide a big enough
+					 * buffer.
+					 */
+	default:
+#if 1
+		DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name,
+				status, req->actual, req->length);
+#endif
+	case -EREMOTEIO:		/* short read */
+		break;
+	}
+
+	status = usb_ep_queue(ep, req, GFP_ATOMIC);
+	if (status) {
+		ERROR(cdev, "kill %s:  resubmit %d bytes --> %d\n",
+				ep->name, req->length, status);
+		usb_ep_set_halt(ep);
+		/* FIXME recover later ... somehow */
+	}
+}
+
+static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in)
+{
+	struct usb_ep		*ep;
+	struct usb_request	*req;
+	int			status;
+
+	ep = is_in ? ss->in_ep : ss->out_ep;
+	req = alloc_ep_req(ep);
+	if (!req)
+		return -ENOMEM;
+
+	req->complete = source_sink_complete;
+	if (is_in)
+		reinit_write_data(ep, req);
+	else
+		memset(req->buf, 0x55, req->length);
+
+	status = usb_ep_queue(ep, req, GFP_ATOMIC);
+	if (status) {
+		struct usb_composite_dev	*cdev;
+
+		cdev = ss->function.config->cdev;
+		ERROR(cdev, "start %s %s --> %d\n",
+				is_in ? "IN" : "OUT",
+				ep->name, status);
+		free_ep_req(ep, req);
+	}
+
+	return status;
+}
+
+static void disable_source_sink(struct f_sourcesink *ss)
+{
+	struct usb_composite_dev	*cdev;
+
+	cdev = ss->function.config->cdev;
+	disable_endpoints(cdev, ss->in_ep, ss->out_ep);
+	del_timer(&ss->resume);
+	VDBG(cdev, "%s disabled\n", ss->function.name);
+}
+
+static int
+enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss)
+{
+	int					result = 0;
+	const struct usb_endpoint_descriptor	*src, *sink;
+	struct usb_ep				*ep;
+
+	src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc);
+	sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc);
+
+	/* one endpoint writes (sources) zeroes IN (to the host) */
+	ep = ss->in_ep;
+	result = usb_ep_enable(ep, src);
+	if (result < 0)
+		return result;
+	ep->driver_data = ss;
+
+	result = source_sink_start_ep(ss, true);
+	if (result < 0) {
+fail:
+		ep = ss->in_ep;
+		usb_ep_disable(ep);
+		ep->driver_data = NULL;
+		return result;
+	}
+
+	/* one endpoint reads (sinks) anything OUT (from the host) */
+	ep = ss->out_ep;
+	result = usb_ep_enable(ep, sink);
+	if (result < 0)
+		goto fail;
+	ep->driver_data = ss;
+
+	result = source_sink_start_ep(ss, false);
+	if (result < 0) {
+		usb_ep_disable(ep);
+		ep->driver_data = NULL;
+		goto fail;
+	}
+
+	DBG(cdev, "%s enabled\n", ss->function.name);
+	return result;
+}
+
+static int sourcesink_set_alt(struct usb_function *f,
+		unsigned intf, unsigned alt)
+{
+	struct f_sourcesink	*ss = func_to_ss(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	/* we know alt is zero */
+	if (ss->in_ep->driver_data)
+		disable_source_sink(ss);
+	return enable_source_sink(cdev, ss);
+}
+
+static void sourcesink_disable(struct usb_function *f)
+{
+	struct f_sourcesink	*ss = func_to_ss(f);
+
+	disable_source_sink(ss);
+}
+
+static void sourcesink_suspend(struct usb_function *f)
+{
+	struct f_sourcesink	*ss = func_to_ss(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
+		return;
+
+	if (autoresume) {
+		mod_timer(&ss->resume, jiffies + (HZ * autoresume));
+		DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume);
+	} else
+		DBG(cdev, "%s\n", __func__);
+}
+
+static void sourcesink_resume(struct usb_function *f)
+{
+	struct f_sourcesink	*ss = func_to_ss(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	DBG(cdev, "%s\n", __func__);
+	del_timer(&ss->resume);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __init sourcesink_bind_config(struct usb_configuration *c)
+{
+	struct f_sourcesink	*ss;
+	int			status;
+
+	ss = kzalloc(sizeof *ss, GFP_KERNEL);
+	if (!ss)
+		return -ENOMEM;
+
+	ss->function.name = "source/sink";
+	ss->function.descriptors = fs_source_sink_descs;
+	ss->function.bind = sourcesink_bind;
+	ss->function.unbind = sourcesink_unbind;
+	ss->function.set_alt = sourcesink_set_alt;
+	ss->function.disable = sourcesink_disable;
+	ss->function.suspend = sourcesink_suspend;
+	ss->function.resume = sourcesink_resume;
+
+	status = usb_add_function(c, &ss->function);
+	if (status)
+		kfree(ss);
+	return status;
+}
+
+static int sourcesink_setup(struct usb_configuration *c,
+		const struct usb_ctrlrequest *ctrl)
+{
+	struct usb_request	*req = c->cdev->req;
+	int			value = -EOPNOTSUPP;
+	u16			w_index = le16_to_cpu(ctrl->wIndex);
+	u16			w_value = le16_to_cpu(ctrl->wValue);
+	u16			w_length = le16_to_cpu(ctrl->wLength);
+
+	/* composite driver infrastructure handles everything except
+	 * the two control test requests.
+	 */
+	switch (ctrl->bRequest) {
+
+	/*
+	 * These are the same vendor-specific requests supported by
+	 * Intel's USB 2.0 compliance test devices.  We exceed that
+	 * device spec by allowing multiple-packet requests.
+	 *
+	 * NOTE:  the Control-OUT data stays in req->buf ... better
+	 * would be copying it into a scratch buffer, so that other
+	 * requests may safely intervene.
+	 */
+	case 0x5b:	/* control WRITE test -- fill the buffer */
+		if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
+			goto unknown;
+		if (w_value || w_index)
+			break;
+		/* just read that many bytes into the buffer */
+		if (w_length > req->length)
+			break;
+		value = w_length;
+		break;
+	case 0x5c:	/* control READ test -- return the buffer */
+		if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
+			goto unknown;
+		if (w_value || w_index)
+			break;
+		/* expect those bytes are still in the buffer; send back */
+		if (w_length > req->length)
+			break;
+		value = w_length;
+		break;
+
+	default:
+unknown:
+		VDBG(c->cdev,
+			"unknown control req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+	}
+
+	/* respond with data transfer or status phase? */
+	if (value >= 0) {
+		VDBG(c->cdev, "source/sink req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+		req->zero = 0;
+		req->length = value;
+		value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0)
+			ERROR(c->cdev, "source/sinkc response, err %d\n",
+					value);
+	}
+
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+static struct usb_configuration sourcesink_driver = {
+	.label		= "source/sink",
+	.strings	= sourcesink_strings,
+	.bind		= sourcesink_bind_config,
+	.setup		= sourcesink_setup,
+	.bConfigurationValue = 3,
+	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower	= 1,	/* 2 mA, minimal */
+	/* .iConfiguration = DYNAMIC */
+};
+
+/**
+ * sourcesink_add - add a source/sink testing configuration to a device
+ * @cdev: the device to support the configuration
+ */
+int __init sourcesink_add(struct usb_composite_dev *cdev)
+{
+	int id;
+
+	/* allocate string ID(s) */
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+	strings_sourcesink[0].id = id;
+
+	source_sink_intf.iInterface = id;
+	sourcesink_driver.iConfiguration = id;
+
+	/* support autoresume for remote wakeup testing */
+	if (autoresume)
+		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+
+	/* support OTG systems */
+	if (gadget_is_otg(cdev->gadget)) {
+		sourcesink_driver.descriptors = otg_desc;
+		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
+	return usb_add_config(cdev, &sourcesink_driver);
+}
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
new file mode 100644
index 0000000..acb8d23
--- /dev/null
+++ b/drivers/usb/gadget/f_subset.c
@@ -0,0 +1,421 @@
+/*
+ * f_subset.c -- "CDC Subset" Ethernet link function driver
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+
+#include "u_ether.h"
+
+
+/*
+ * This function packages a simple "CDC Subset" Ethernet port with no real
+ * control mechanisms; just raw data transfer over two bulk endpoints.
+ * The data transfer model is exactly that of CDC Ethernet, which is
+ * why we call it the "CDC Subset".
+ *
+ * Because it's not standardized, this has some interoperability issues.
+ * They mostly relate to driver binding, since the data transfer model is
+ * so simple (CDC Ethernet).  The original versions of this protocol used
+ * specific product/vendor IDs:  byteswapped IDs for Digital Equipment's
+ * SA-1100 "Itsy" board, which could run Linux 2.4 kernels and supported
+ * daughtercards with USB peripheral connectors.  (It was used more often
+ * with other boards, using the Itsy identifiers.)  Linux hosts recognized
+ * this with CONFIG_USB_ARMLINUX; these devices have only one configuration
+ * and one interface.
+ *
+ * At some point, MCCI defined a (nonconformant) CDC MDLM variant called
+ * "SAFE", which happens to have a mode which is identical to the "CDC
+ * Subset" in terms of data transfer and lack of control model.  This was
+ * adopted by later Sharp Zaurus models, and by some other software which
+ * Linux hosts recognize with CONFIG_USB_NET_ZAURUS.
+ *
+ * Because Microsoft's RNDIS drivers are far from robust, we added a few
+ * descriptors to the CDC Subset code, making this code look like a SAFE
+ * implementation.  This lets you use MCCI's host side MS-Windows drivers
+ * if you get fed up with RNDIS.  It also makes it easier for composite
+ * drivers to work, since they can use class based binding instead of
+ * caring about specific product and vendor IDs.
+ */
+
+struct geth_descs {
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+};
+
+struct f_gether {
+	struct gether			port;
+
+	char				ethaddr[14];
+
+	struct geth_descs		fs;
+	struct geth_descs		hs;
+};
+
+static inline struct f_gether *func_to_geth(struct usb_function *f)
+{
+	return container_of(f, struct f_gether, port.func);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * "Simple" CDC-subset option is a simple vendor-neutral model that most
+ * full speed controllers can handle:  one interface, two bulk endpoints.
+ * To assist host side drivers, we fancy it up a bit, and add descriptors so
+ * some host side drivers will understand it as a "SAFE" variant.
+ *
+ * "SAFE" loosely follows CDC WMC MDLM, violating the spec in various ways.
+ * Data endpoints live in the control interface, there's no data interface.
+ * And it's not used to talk to a cell phone radio.
+ */
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor subset_data_intf __initdata = {
+	.bLength =		sizeof subset_data_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	/* .bInterfaceNumber = DYNAMIC */
+	.bAlternateSetting =	0,
+	.bNumEndpoints =	2,
+	.bInterfaceClass =      USB_CLASS_COMM,
+	.bInterfaceSubClass =	USB_CDC_SUBCLASS_MDLM,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc header_desc __initdata = {
+	.bLength =		sizeof header_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
+
+	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_mdlm_desc mdlm_desc __initdata = {
+	.bLength =		sizeof mdlm_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_MDLM_TYPE,
+
+	.bcdVersion =		__constant_cpu_to_le16(0x0100),
+	.bGUID = {
+		0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
+		0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
+	},
+};
+
+/* since "usb_cdc_mdlm_detail_desc" is a variable length structure, we
+ * can't really use its struct.  All we do here is say that we're using
+ * the submode of "SAFE" which directly matches the CDC Subset.
+ */
+static u8 mdlm_detail_desc[] __initdata = {
+	6,
+	USB_DT_CS_INTERFACE,
+	USB_CDC_MDLM_DETAIL_TYPE,
+
+	0,	/* "SAFE" */
+	0,	/* network control capabilities (none) */
+	0,	/* network data capabilities ("raw" encapsulation) */
+};
+
+static struct usb_cdc_ether_desc ether_desc __initdata = {
+	.bLength =		sizeof ether_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_ETHERNET_TYPE,
+
+	/* this descriptor actually adds value, surprise! */
+	/* .iMACAddress = DYNAMIC */
+	.bmEthernetStatistics =	__constant_cpu_to_le32(0), /* no statistics */
+	.wMaxSegmentSize =	__constant_cpu_to_le16(ETH_FRAME_LEN),
+	.wNumberMCFilters =	__constant_cpu_to_le16(0),
+	.bNumberPowerFilters =	0,
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *fs_eth_function[] __initdata = {
+	(struct usb_descriptor_header *) &subset_data_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &mdlm_desc,
+	(struct usb_descriptor_header *) &mdlm_detail_desc,
+	(struct usb_descriptor_header *) &ether_desc,
+	(struct usb_descriptor_header *) &fs_in_desc,
+	(struct usb_descriptor_header *) &fs_out_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *hs_eth_function[] __initdata = {
+	(struct usb_descriptor_header *) &subset_data_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &mdlm_desc,
+	(struct usb_descriptor_header *) &mdlm_detail_desc,
+	(struct usb_descriptor_header *) &ether_desc,
+	(struct usb_descriptor_header *) &hs_in_desc,
+	(struct usb_descriptor_header *) &hs_out_desc,
+	NULL,
+};
+
+/* string descriptors: */
+
+static struct usb_string geth_string_defs[] = {
+	[0].s = "CDC Ethernet Subset/SAFE",
+	[1].s = NULL /* DYNAMIC */,
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings geth_string_table = {
+	.language =		0x0409,	/* en-us */
+	.strings =		geth_string_defs,
+};
+
+static struct usb_gadget_strings *geth_strings[] = {
+	&geth_string_table,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_gether		*geth = func_to_geth(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct net_device	*net;
+
+	/* we know alt == 0, so this is an activation or a reset */
+
+	if (geth->port.in_ep->driver_data) {
+		DBG(cdev, "reset cdc subset\n");
+		gether_disconnect(&geth->port);
+	}
+
+	DBG(cdev, "init + activate cdc subset\n");
+	geth->port.in = ep_choose(cdev->gadget,
+			geth->hs.in, geth->fs.in);
+	geth->port.out = ep_choose(cdev->gadget,
+			geth->hs.out, geth->fs.out);
+
+	net = gether_connect(&geth->port);
+	return IS_ERR(net) ? PTR_ERR(net) : 0;
+}
+
+static void geth_disable(struct usb_function *f)
+{
+	struct f_gether	*geth = func_to_geth(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	DBG(cdev, "net deactivated\n");
+	gether_disconnect(&geth->port);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* serial function driver setup/binding */
+
+static int __init
+geth_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_gether		*geth = func_to_geth(f);
+	int			status;
+	struct usb_ep		*ep;
+
+	/* allocate instance-specific interface IDs */
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	subset_data_intf.bInterfaceNumber = status;
+
+	status = -ENODEV;
+
+	/* allocate instance-specific endpoints */
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+	if (!ep)
+		goto fail;
+	geth->port.in_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+	if (!ep)
+		goto fail;
+	geth->port.out_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	/* copy descriptors, and track endpoint copies */
+	f->descriptors = usb_copy_descriptors(fs_eth_function);
+
+	geth->fs.in = usb_find_endpoint(fs_eth_function,
+			f->descriptors, &fs_in_desc);
+	geth->fs.out = usb_find_endpoint(fs_eth_function,
+			f->descriptors, &fs_out_desc);
+
+
+	/* support all relevant hardware speeds... we expect that when
+	 * hardware is dual speed, all bulk-capable endpoints work at
+	 * both speeds
+	 */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		hs_in_desc.bEndpointAddress =
+				fs_in_desc.bEndpointAddress;
+		hs_out_desc.bEndpointAddress =
+				fs_out_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
+
+		geth->hs.in = usb_find_endpoint(hs_eth_function,
+				f->hs_descriptors, &hs_in_desc);
+		geth->hs.out = usb_find_endpoint(hs_eth_function,
+				f->hs_descriptors, &hs_out_desc);
+	}
+
+	/* NOTE:  all that is done without knowing or caring about
+	 * the network link ... which is unavailable to this code
+	 * until we're activated via set_alt().
+	 */
+
+	DBG(cdev, "CDC Subset: %s speed IN/%s OUT/%s\n",
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			geth->port.in_ep->name, geth->port.out_ep->name);
+	return 0;
+
+fail:
+	/* we might as well release our claims on endpoints */
+	if (geth->port.out)
+		geth->port.out_ep->driver_data = NULL;
+	if (geth->port.in)
+		geth->port.in_ep->driver_data = NULL;
+
+	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+
+	return status;
+}
+
+static void
+geth_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	if (gadget_is_dualspeed(c->cdev->gadget))
+		usb_free_descriptors(f->hs_descriptors);
+	usb_free_descriptors(f->descriptors);
+	geth_string_defs[1].s = NULL;
+	kfree(func_to_geth(f));
+}
+
+/**
+ * geth_bind_config - add CDC Subset network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ *	side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup().  Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+int __init geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+	struct f_gether	*geth;
+	int		status;
+
+	if (!ethaddr)
+		return -EINVAL;
+
+	/* maybe allocate device-global string IDs */
+	if (geth_string_defs[0].id == 0) {
+
+		/* interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		geth_string_defs[0].id = status;
+		subset_data_intf.iInterface = status;
+
+		/* MAC address */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		geth_string_defs[1].id = status;
+		ether_desc.iMACAddress = status;
+	}
+
+	/* allocate and initialize one new instance */
+	geth = kzalloc(sizeof *geth, GFP_KERNEL);
+	if (!geth)
+		return -ENOMEM;
+
+	/* export host's Ethernet address in CDC format */
+	snprintf(geth->ethaddr, sizeof geth->ethaddr,
+		"%02X%02X%02X%02X%02X%02X",
+		ethaddr[0], ethaddr[1], ethaddr[2],
+		ethaddr[3], ethaddr[4], ethaddr[5]);
+	geth_string_defs[1].s = geth->ethaddr;
+
+	geth->port.cdc_filter = DEFAULT_FILTER;
+
+	geth->port.func.name = "cdc_subset";
+	geth->port.func.strings = geth_strings;
+	geth->port.func.bind = geth_bind;
+	geth->port.func.unbind = geth_unbind;
+	geth->port.func.set_alt = geth_set_alt;
+	geth->port.func.disable = geth_disable;
+
+	status = usb_add_function(c, &geth->port.func);
+	if (status) {
+		geth_string_defs[1].s = NULL;
+		kfree(geth);
+	}
+	return status;
+}
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 47bb9f0..ea2c31d 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -308,7 +308,7 @@ MODULE_LICENSE("Dual BSD/GPL");
 	dev_vdbg(&(d)->gadget->dev , fmt , ## args)
 #define ERROR(d, fmt, args...) \
 	dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARN(d, fmt, args...) \
+#define WARNING(d, fmt, args...) \
 	dev_warn(&(d)->gadget->dev , fmt , ## args)
 #define INFO(d, fmt, args...) \
 	dev_info(&(d)->gadget->dev , fmt , ## args)
@@ -1091,7 +1091,7 @@ static int ep0_queue(struct fsg_dev *fsg)
 	if (rc != 0 && rc != -ESHUTDOWN) {
 
 		/* We can't do much more than wait for a reset */
-		WARN(fsg, "error in submission: %s --> %d\n",
+		WARNING(fsg, "error in submission: %s --> %d\n",
 				fsg->ep0->name, rc);
 	}
 	return rc;
@@ -1227,7 +1227,7 @@ static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
 
 	/* Save the command for later */
 	if (fsg->cbbuf_cmnd_size)
-		WARN(fsg, "CB[I] overwriting previous command\n");
+		WARNING(fsg, "CB[I] overwriting previous command\n");
 	fsg->cbbuf_cmnd_size = req->actual;
 	memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
 
@@ -1506,7 +1506,7 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
 		 * submissions if DMA is enabled. */
 		if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
 						req->length == 0))
-			WARN(fsg, "error in submission: %s --> %d\n",
+			WARNING(fsg, "error in submission: %s --> %d\n",
 					ep->name, rc);
 	}
 }
@@ -2294,7 +2294,7 @@ static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
 		VDBG(fsg, "delayed bulk-in endpoint halt\n");
 	while (rc != 0) {
 		if (rc != -EAGAIN) {
-			WARN(fsg, "usb_ep_set_halt -> %d\n", rc);
+			WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
 			rc = 0;
 			break;
 		}
@@ -2317,7 +2317,7 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
 		VDBG(fsg, "delayed bulk-in endpoint wedge\n");
 	while (rc != 0) {
 		if (rc != -EAGAIN) {
-			WARN(fsg, "usb_ep_set_wedge -> %d\n", rc);
+			WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
 			rc = 0;
 			break;
 		}
@@ -3755,7 +3755,7 @@ static int __init check_parameters(struct fsg_dev *fsg)
 		if (gcnum >= 0)
 			mod_data.release = 0x0300 + gcnum;
 		else {
-			WARN(fsg, "controller '%s' not recognized\n",
+			WARNING(fsg, "controller '%s' not recognized\n",
 				fsg->gadget->name);
 			mod_data.release = 0x0399;
 		}
@@ -3867,8 +3867,8 @@ static int __init fsg_bind(struct usb_gadget *gadget)
 		curlun->dev.parent = &gadget->dev;
 		curlun->dev.driver = &fsg_driver.driver;
 		dev_set_drvdata(&curlun->dev, fsg);
-		snprintf(curlun->dev.bus_id, BUS_ID_SIZE,
-				"%s-lun%d", gadget->dev.bus_id, i);
+		dev_set_name(&curlun->dev,"%s-lun%d",
+			     dev_name(&gadget->dev), i);
 
 		if ((rc = device_register(&curlun->dev)) != 0) {
 			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index 1868754..45ad556 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -223,7 +223,7 @@ static int dr_controller_setup(struct fsl_udc *udc)
 	fsl_writel(tmp, &dr_regs->endpointlistaddr);
 
 	VDBG("vir[qh_base] is %p phy[qh_base] is 0x%8x reg is 0x%8x",
-		(int)udc->ep_qh, (int)tmp,
+		udc->ep_qh, (int)tmp,
 		fsl_readl(&dr_regs->endpointlistaddr));
 
 	/* Config PHY interface */
@@ -1538,7 +1538,7 @@ static void dtd_complete_irq(struct fsl_udc *udc)
 
 		/* If the ep is configured */
 		if (curr_ep->name == NULL) {
-			WARN("Invalid EP?");
+			WARNING("Invalid EP?");
 			continue;
 		}
 
@@ -2331,7 +2331,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 	udc_controller->gadget.name = driver_name;
 
 	/* Setup gadget.dev and register with kernel */
-	strcpy(udc_controller->gadget.dev.bus_id, "gadget");
+	dev_set_name(&udc_controller->gadget.dev, "gadget");
 	udc_controller->gadget.dev.release = fsl_udc_release;
 	udc_controller->gadget.dev.parent = &pdev->dev;
 	ret = device_register(&udc_controller->gadget.dev);
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index 98b1483..6131752 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -552,7 +552,7 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length)
 #endif
 
 #define ERR(stuff...)		pr_err("udc: " stuff)
-#define WARN(stuff...)		pr_warning("udc: " stuff)
+#define WARNING(stuff...)		pr_warning("udc: " stuff)
 #define INFO(stuff...)		pr_info("udc: " stuff)
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h
new file mode 100644
index 0000000..dd2f16a
--- /dev/null
+++ b/drivers/usb/gadget/g_zero.h
@@ -0,0 +1,25 @@
+/*
+ * This header declares the utility functions used by "Gadget Zero", plus
+ * interfaces to its two single-configuration function drivers.
+ */
+
+#ifndef __G_ZERO_H
+#define __G_ZERO_H
+
+#include <linux/usb/composite.h>
+
+/* global state */
+extern unsigned buflen;
+extern const struct usb_descriptor_header *otg_desc[];
+
+/* common utilities */
+struct usb_request *alloc_ep_req(struct usb_ep *ep);
+void free_ep_req(struct usb_ep *ep, struct usb_request *req);
+void disable_endpoints(struct usb_composite_dev *cdev,
+		struct usb_ep *in, struct usb_ep *out);
+
+/* configuration-specific linkup */
+int sourcesink_add(struct usb_composite_dev *cdev);
+int loopback_add(struct usb_composite_dev *cdev);
+
+#endif /* __G_ZERO_H */
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index f7f159c..17d9905 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -11,6 +11,10 @@
  * Some are available on 2.4 kernels; several are available, but not
  * yet pushed in the 2.6 mainline tree.
  */
+
+#ifndef __GADGET_CHIPS_H
+#define __GADGET_CHIPS_H
+
 #ifdef CONFIG_USB_GADGET_NET2280
 #define	gadget_is_net2280(g)	!strcmp("net2280", (g)->name)
 #else
@@ -29,8 +33,8 @@
 #define	gadget_is_dummy(g)	0
 #endif
 
-#ifdef CONFIG_USB_GADGET_PXA2XX
-#define	gadget_is_pxa(g)	!strcmp("pxa2xx_udc", (g)->name)
+#ifdef CONFIG_USB_GADGET_PXA25X
+#define	gadget_is_pxa(g)	!strcmp("pxa25x_udc", (g)->name)
 #else
 #define	gadget_is_pxa(g)	0
 #endif
@@ -214,3 +218,28 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
 		return 0x21;
 	return -ENOENT;
 }
+
+
+/**
+ * gadget_supports_altsettings - return true if altsettings work
+ * @gadget: the gadget in question
+ */
+static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
+{
+	/* PXA 21x/25x/26x has no altsettings at all */
+	if (gadget_is_pxa(gadget))
+		return false;
+
+	/* PXA 27x and 3xx have *broken* altsetting support */
+	if (gadget_is_pxa27x(gadget))
+		return false;
+
+	/* SH3 hardware just doesn't do altsettings */
+	if (gadget_is_sh(gadget))
+		return false;
+
+	/* Everything else is *presumably* fine ... */
+	return true;
+}
+
+#endif /* __GADGET_CHIPS_H */
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index 7f4d482..ea8651e 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -138,8 +138,6 @@ static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req);
 	dev_vdbg(&(d)->gadget->dev , fmt , ## args)
 #define ERROR(d, fmt, args...) \
 	dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARN(d, fmt, args...) \
-	dev_warn(&(d)->gadget->dev , fmt , ## args)
 #define INFO(d, fmt, args...) \
 	dev_info(&(d)->gadget->dev , fmt , ## args)
 
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index be6613a..60aa048 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1768,7 +1768,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	 * usb_gadget_driver_{register,unregister}() must change.
 	 */
 	if (the_controller) {
-		WARN(dev, "ignoring %s\n", pci_name(pdev));
+		WARNING(dev, "ignoring %s\n", pci_name(pdev));
 		return -EBUSY;
 	}
 	if (!pdev->irq) {
@@ -1790,7 +1790,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	dev->gadget.ops = &goku_ops;
 
 	/* the "gadget" abstracts/virtualizes the controller */
-	strcpy(dev->gadget.dev.bus_id, "gadget");
+	dev_set_name(&dev->gadget.dev, "gadget");
 	dev->gadget.dev.parent = &pdev->dev;
 	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 	dev->gadget.dev.release = gadget_release;
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h
index bc4eb1e..566cb23 100644
--- a/drivers/usb/gadget/goku_udc.h
+++ b/drivers/usb/gadget/goku_udc.h
@@ -285,7 +285,7 @@ struct goku_udc {
 
 #define ERROR(dev,fmt,args...) \
 	xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
+#define WARNING(dev,fmt,args...) \
 	xprintk(dev , KERN_WARNING , fmt , ## args)
 #define INFO(dev,fmt,args...) \
 	xprintk(dev , KERN_INFO , fmt , ## args)
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 69b0a27..f4585d3 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -32,6 +32,7 @@
 #include <asm/uaccess.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
+#include <linux/smp_lock.h>
 
 #include <linux/device.h>
 #include <linux/moduleparam.h>
@@ -261,8 +262,6 @@ static const char *CHIP;
 
 #define ERROR(dev,fmt,args...) \
 	xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
-	xprintk(dev , KERN_WARNING , fmt , ## args)
 #define INFO(dev,fmt,args...) \
 	xprintk(dev , KERN_INFO , fmt , ## args)
 
@@ -483,8 +482,7 @@ ep_release (struct inode *inode, struct file *fd)
 	return 0;
 }
 
-static int ep_ioctl (struct inode *inode, struct file *fd,
-		unsigned code, unsigned long value)
+static long ep_ioctl(struct file *fd, unsigned code, unsigned long value)
 {
 	struct ep_data		*data = fd->private_data;
 	int			status;
@@ -740,7 +738,7 @@ static const struct file_operations ep_io_operations = {
 
 	.read =		ep_read,
 	.write =	ep_write,
-	.ioctl =	ep_ioctl,
+	.unlocked_ioctl = ep_ioctl,
 	.release =	ep_release,
 
 	.aio_read =	ep_aio_read,
@@ -1294,15 +1292,18 @@ out:
        return mask;
 }
 
-static int dev_ioctl (struct inode *inode, struct file *fd,
-		unsigned code, unsigned long value)
+static long dev_ioctl (struct file *fd, unsigned code, unsigned long value)
 {
 	struct dev_data		*dev = fd->private_data;
 	struct usb_gadget	*gadget = dev->gadget;
+	long ret = -ENOTTY;
 
-	if (gadget->ops->ioctl)
-		return gadget->ops->ioctl (gadget, code, value);
-	return -ENOTTY;
+	if (gadget->ops->ioctl) {
+		lock_kernel();
+		ret = gadget->ops->ioctl (gadget, code, value);
+		unlock_kernel();
+	}
+	return ret;
 }
 
 /* used after device configuration */
@@ -1314,7 +1315,7 @@ static const struct file_operations ep0_io_operations = {
 	.write =	ep0_write,
 	.fasync =	ep0_fasync,
 	.poll =		ep0_poll,
-	.ioctl =	dev_ioctl,
+	.unlocked_ioctl =	dev_ioctl,
 	.release =	dev_release,
 };
 
@@ -1501,7 +1502,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 		}
 		break;
 
-#ifndef	CONFIG_USB_GADGET_PXA2XX
+#ifndef	CONFIG_USB_GADGET_PXA25X
 	/* PXA automagically handles this request too */
 	case USB_REQ_GET_CONFIGURATION:
 		if (ctrl->bRequestType != 0x80)
@@ -1964,7 +1965,7 @@ static const struct file_operations dev_init_operations = {
 	.open =		dev_open,
 	.write =	dev_config,
 	.fasync =	ep0_fasync,
-	.ioctl =	dev_ioctl,
+	.unlocked_ioctl = dev_ioctl,
 	.release =	dev_release,
 };
 
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 825abd2..c6e7df0 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -1970,7 +1970,7 @@ static const struct usb_gadget_ops lh7a40x_udc_ops = {
 
 static void nop_release(struct device *dev)
 {
-	DEBUG("%s %s\n", __func__, dev->bus_id);
+	DEBUG("%s %s\n", __func__, dev_name(dev));
 }
 
 static struct lh7a40x_udc memory = {
diff --git a/drivers/usb/gadget/lh7a40x_udc.h b/drivers/usb/gadget/lh7a40x_udc.h
index 1ecfd63..ca86120 100644
--- a/drivers/usb/gadget/lh7a40x_udc.h
+++ b/drivers/usb/gadget/lh7a40x_udc.h
@@ -47,7 +47,7 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
-#include <asm/hardware.h>
+#include <mach/hardware.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index ee6b35f..77b44fb 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -1593,7 +1593,7 @@ static int __init m66592_probe(struct platform_device *pdev)
 
 	m66592->gadget.ops = &m66592_gadget_ops;
 	device_initialize(&m66592->gadget.dev);
-	strcpy(m66592->gadget.dev.bus_id, "gadget");
+	dev_set_name(&m66592->gadget.dev, "gadget");
 	m66592->gadget.is_dualspeed = 1;
 	m66592->gadget.dev.parent = &pdev->dev;
 	m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
diff --git a/drivers/usb/gadget/ndis.h b/drivers/usb/gadget/ndis.h
index 09e3ee4..df886ce 100644
--- a/drivers/usb/gadget/ndis.h
+++ b/drivers/usb/gadget/ndis.h
@@ -1,11 +1,11 @@
 /*
- * ndis.h 
- * 
+ * ndis.h
+ *
  * ntddndis.h modified by Benedikt Spranger <b.spranger@pengutronix.de>
- * 
- * Thanks to the cygwin development team, 
+ *
+ * Thanks to the cygwin development team,
  * espacially to Casper S. Hornstrup <chorns@users.sourceforge.net>
- * 
+ *
  * THIS SOFTWARE IS NOT COPYRIGHTED
  *
  * This source code is offered for use in the public domain. You may
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index e018623..5cfb5eb 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1007,7 +1007,7 @@ static void scan_dma_completions (struct net2280_ep *ep)
 			 * 0122, and 0124; not all cases trigger the warning.
 			 */
 			if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
-				WARN (ep->dev, "%s lost packet sync!\n",
+				WARNING (ep->dev, "%s lost packet sync!\n",
 						ep->ep.name);
 				req->req.status = -EOVERFLOW;
 			} else if ((tmp = readl (&ep->regs->ep_avail)) != 0) {
@@ -2768,7 +2768,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 	dev->gadget.is_dualspeed = 1;
 
 	/* the "gadget" abstracts/virtualizes the controller */
-	strcpy (dev->gadget.dev.bus_id, "gadget");
+	dev_set_name(&dev->gadget.dev, "gadget");
 	dev->gadget.dev.parent = &pdev->dev;
 	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 	dev->gadget.dev.release = gadget_release;
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
index 1f2af39..81a71db 100644
--- a/drivers/usb/gadget/net2280.h
+++ b/drivers/usb/gadget/net2280.h
@@ -272,7 +272,7 @@ static inline void net2280_led_shutdown (struct net2280 *dev)
 
 #define ERROR(dev,fmt,args...) \
 	xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
+#define WARNING(dev,fmt,args...) \
 	xprintk(dev , KERN_WARNING , fmt , ## args)
 #define INFO(dev,fmt,args...) \
 	xprintk(dev , KERN_INFO , fmt , ## args)
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 881d74c..bb54cca 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -52,8 +52,9 @@
 #include <asm/unaligned.h>
 #include <asm/mach-types.h>
 
-#include <asm/arch/dma.h>
-#include <asm/arch/usb.h>
+#include <mach/dma.h>
+#include <mach/usb.h>
+#include <mach/control.h>
 
 #include "omap_udc.h"
 
@@ -135,13 +136,17 @@ static void use_ep(struct omap_ep *ep, u16 select)
 
 	if (ep->bEndpointAddress & USB_DIR_IN)
 		num |= UDC_EP_DIR;
-	UDC_EP_NUM_REG = num | select;
+	omap_writew(num | select, UDC_EP_NUM);
 	/* when select, MUST deselect later !! */
 }
 
 static inline void deselect_ep(void)
 {
-	UDC_EP_NUM_REG &= ~UDC_EP_SEL;
+	u16 w;
+
+	w = omap_readw(UDC_EP_NUM);
+	w &= ~UDC_EP_SEL;
+	omap_writew(w, UDC_EP_NUM);
 	/* 6 wait states before TX will happen */
 }
 
@@ -216,7 +221,7 @@ static int omap_ep_enable(struct usb_ep *_ep,
 	ep->has_dma = 0;
 	ep->lch = -1;
 	use_ep(ep, UDC_EP_SEL);
-	UDC_CTRL_REG = udc->clr_halt;
+	omap_writew(udc->clr_halt, UDC_CTRL);
 	ep->ackwait = 0;
 	deselect_ep();
 
@@ -232,7 +237,7 @@ static int omap_ep_enable(struct usb_ep *_ep,
 	if (desc->bmAttributes != USB_ENDPOINT_XFER_ISOC
 			&& !ep->has_dma
 			&& !(ep->bEndpointAddress & USB_DIR_IN)) {
-		UDC_CTRL_REG = UDC_SET_FIFO_EN;
+		omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
 		ep->ackwait = 1 + ep->double_buf;
 	}
 
@@ -259,7 +264,7 @@ static int omap_ep_disable(struct usb_ep *_ep)
 	nuke (ep, -ESHUTDOWN);
 	ep->ep.maxpacket = ep->maxpacket;
 	ep->has_dma = 0;
-	UDC_CTRL_REG = UDC_SET_HALT;
+	omap_writew(UDC_SET_HALT, UDC_CTRL);
 	list_del_init(&ep->iso);
 	del_timer(&ep->timer);
 
@@ -360,13 +365,13 @@ write_packet(u8 *buf, struct omap_req *req, unsigned max)
 	if (likely((((int)buf) & 1) == 0)) {
 		wp = (u16 *)buf;
 		while (max >= 2) {
-			UDC_DATA_REG = *wp++;
+			omap_writew(*wp++, UDC_DATA);
 			max -= 2;
 		}
 		buf = (u8 *)wp;
 	}
 	while (max--)
-		*(volatile u8 *)&UDC_DATA_REG = *buf++;
+		omap_writeb(*buf++, UDC_DATA);
 	return len;
 }
 
@@ -385,13 +390,13 @@ static int write_fifo(struct omap_ep *ep, struct omap_req *req)
 	prefetch(buf);
 
 	/* PIO-IN isn't double buffered except for iso */
-	ep_stat = UDC_STAT_FLG_REG;
+	ep_stat = omap_readw(UDC_STAT_FLG);
 	if (ep_stat & UDC_FIFO_UNWRITABLE)
 		return 0;
 
 	count = ep->ep.maxpacket;
 	count = write_packet(buf, req, count);
-	UDC_CTRL_REG = UDC_SET_FIFO_EN;
+	omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
 	ep->ackwait = 1;
 
 	/* last packet is often short (sometimes a zlp) */
@@ -425,13 +430,13 @@ read_packet(u8 *buf, struct omap_req *req, unsigned avail)
 	if (likely((((int)buf) & 1) == 0)) {
 		wp = (u16 *)buf;
 		while (avail >= 2) {
-			*wp++ = UDC_DATA_REG;
+			*wp++ = omap_readw(UDC_DATA);
 			avail -= 2;
 		}
 		buf = (u8 *)wp;
 	}
 	while (avail--)
-		*buf++ = *(volatile u8 *)&UDC_DATA_REG;
+		*buf++ = omap_readb(UDC_DATA);
 	return len;
 }
 
@@ -446,7 +451,7 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req)
 	prefetchw(buf);
 
 	for (;;) {
-		u16	ep_stat = UDC_STAT_FLG_REG;
+		u16	ep_stat = omap_readw(UDC_STAT_FLG);
 
 		is_last = 0;
 		if (ep_stat & FIFO_EMPTY) {
@@ -460,7 +465,7 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req)
 		if (ep_stat & UDC_FIFO_FULL)
 			avail = ep->ep.maxpacket;
 		else  {
-			avail = UDC_RXFSTAT_REG;
+			avail = omap_readw(UDC_RXFSTAT);
 			ep->fnf = ep->double_buf;
 		}
 		count = read_packet(buf, req, avail);
@@ -473,7 +478,7 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req)
 				req->req.status = -EOVERFLOW;
 				avail -= count;
 				while (avail--)
-					(void) *(volatile u8 *)&UDC_DATA_REG;
+					omap_readw(UDC_DATA);
 			}
 		} else if (req->req.length == req->req.actual)
 			is_last = 1;
@@ -491,32 +496,6 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req)
 
 /*-------------------------------------------------------------------------*/
 
-static inline dma_addr_t dma_csac(unsigned lch)
-{
-	dma_addr_t	csac;
-
-	/* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
-	 * read before the DMA controller finished disabling the channel.
-	 */
-	csac = OMAP_DMA_CSAC_REG(lch);
-	if (csac == 0)
-		csac = OMAP_DMA_CSAC_REG(lch);
-	return csac;
-}
-
-static inline dma_addr_t dma_cdac(unsigned lch)
-{
-	dma_addr_t	cdac;
-
-	/* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
-	 * read before the DMA controller finished disabling the channel.
-	 */
-	cdac = OMAP_DMA_CDAC_REG(lch);
-	if (cdac == 0)
-		cdac = OMAP_DMA_CDAC_REG(lch);
-	return cdac;
-}
-
 static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start)
 {
 	dma_addr_t	end;
@@ -527,7 +506,7 @@ static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start)
 	if (cpu_is_omap15xx())
 		return 0;
 
-	end = dma_csac(ep->lch);
+	end = omap_get_dma_src_pos(ep->lch);
 	if (end == ep->dma_counter)
 		return 0;
 
@@ -537,15 +516,11 @@ static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start)
 	return end - start;
 }
 
-#define DMA_DEST_LAST(x) (cpu_is_omap15xx() \
-		? OMAP_DMA_CSAC_REG(x) /* really: CPC */ \
-		: dma_cdac(x))
-
 static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start)
 {
 	dma_addr_t	end;
 
-	end = DMA_DEST_LAST(ep->lch);
+	end = omap_get_dma_dst_pos(ep->lch);
 	if (end == ep->dma_counter)
 		return 0;
 
@@ -565,7 +540,7 @@ static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start)
 
 static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
 {
-	u16		txdma_ctrl;
+	u16		txdma_ctrl, w;
 	unsigned	length = req->req.length - req->req.actual;
 	const int	sync_mode = cpu_is_omap15xx()
 				? OMAP_DMA_SYNC_FRAME
@@ -596,14 +571,18 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
 		0, 0);
 
 	omap_start_dma(ep->lch);
-	ep->dma_counter = dma_csac(ep->lch);
-	UDC_DMA_IRQ_EN_REG |= UDC_TX_DONE_IE(ep->dma_channel);
-	UDC_TXDMA_REG(ep->dma_channel) = UDC_TXN_START | txdma_ctrl;
+	ep->dma_counter = omap_get_dma_src_pos(ep->lch);
+	w = omap_readw(UDC_DMA_IRQ_EN);
+	w |= UDC_TX_DONE_IE(ep->dma_channel);
+	omap_writew(w, UDC_DMA_IRQ_EN);
+	omap_writew(UDC_TXN_START | txdma_ctrl, UDC_TXDMA(ep->dma_channel));
 	req->dma_bytes = length;
 }
 
 static void finish_in_dma(struct omap_ep *ep, struct omap_req *req, int status)
 {
+	u16 w;
+
 	if (status == 0) {
 		req->req.actual += req->dma_bytes;
 
@@ -620,7 +599,9 @@ static void finish_in_dma(struct omap_ep *ep, struct omap_req *req, int status)
 
 	/* tx completion */
 	omap_stop_dma(ep->lch);
-	UDC_DMA_IRQ_EN_REG &= ~UDC_TX_DONE_IE(ep->dma_channel);
+	w = omap_readw(UDC_DMA_IRQ_EN);
+	w &= ~UDC_TX_DONE_IE(ep->dma_channel);
+	omap_writew(w, UDC_DMA_IRQ_EN);
 	done(ep, req, status);
 }
 
@@ -628,6 +609,7 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
 {
 	unsigned packets = req->req.length - req->req.actual;
 	int dma_trigger = 0;
+	u16 w;
 
 	if (cpu_is_omap24xx())
 		dma_trigger = OMAP24XX_DMA(USB_W2FC_RX0, ep->dma_channel);
@@ -654,12 +636,14 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
 	omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
 		OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
 		0, 0);
-	ep->dma_counter = DMA_DEST_LAST(ep->lch);
+	ep->dma_counter = omap_get_dma_dst_pos(ep->lch);
 
-	UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1);
-	UDC_DMA_IRQ_EN_REG |= UDC_RX_EOT_IE(ep->dma_channel);
-	UDC_EP_NUM_REG = (ep->bEndpointAddress & 0xf);
-	UDC_CTRL_REG = UDC_SET_FIFO_EN;
+	omap_writew(UDC_RXN_STOP | (packets - 1), UDC_RXDMA(ep->dma_channel));
+	w = omap_readw(UDC_DMA_IRQ_EN);
+	w |= UDC_RX_EOT_IE(ep->dma_channel);
+	omap_writew(w, UDC_DMA_IRQ_EN);
+	omap_writew(ep->bEndpointAddress & 0xf, UDC_EP_NUM);
+	omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
 
 	omap_start_dma(ep->lch);
 }
@@ -667,7 +651,7 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
 static void
 finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status, int one)
 {
-	u16	count;
+	u16	count, w;
 
 	if (status == 0)
 		ep->dma_counter = (u16) (req->req.dma + req->req.actual);
@@ -686,13 +670,15 @@ finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status, int one)
 		return;
 
 	/* rx completion */
-	UDC_DMA_IRQ_EN_REG &= ~UDC_RX_EOT_IE(ep->dma_channel);
+	w = omap_readw(UDC_DMA_IRQ_EN);
+	w &= ~UDC_RX_EOT_IE(ep->dma_channel);
+	omap_writew(w, UDC_DMA_IRQ_EN);
 	done(ep, req, status);
 }
 
 static void dma_irq(struct omap_udc *udc, u16 irq_src)
 {
-	u16		dman_stat = UDC_DMAN_STAT_REG;
+	u16		dman_stat = omap_readw(UDC_DMAN_STAT);
 	struct omap_ep	*ep;
 	struct omap_req	*req;
 
@@ -706,7 +692,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src)
 						struct omap_req, queue);
 			finish_in_dma(ep, req, 0);
 		}
-		UDC_IRQ_SRC_REG = UDC_TXN_DONE;
+		omap_writew(UDC_TXN_DONE, UDC_IRQ_SRC);
 
 		if (!list_empty (&ep->queue)) {
 			req = container_of(ep->queue.next,
@@ -725,7 +711,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src)
 					struct omap_req, queue);
 			finish_out_dma(ep, req, 0, dman_stat & UDC_DMA_RX_SB);
 		}
-		UDC_IRQ_SRC_REG = UDC_RXN_EOT;
+		omap_writew(UDC_RXN_EOT, UDC_IRQ_SRC);
 
 		if (!list_empty (&ep->queue)) {
 			req = container_of(ep->queue.next,
@@ -739,7 +725,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src)
 		ep->irqs++;
 		/* omap15xx does this unasked... */
 		VDBG("%s, RX_CNT irq?\n", ep->ep.name);
-		UDC_IRQ_SRC_REG = UDC_RXN_CNT;
+		omap_writew(UDC_RXN_CNT, UDC_IRQ_SRC);
 	}
 }
 
@@ -762,9 +748,9 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 
 	is_in = ep->bEndpointAddress & USB_DIR_IN;
 	if (is_in)
-		reg = UDC_TXDMA_CFG_REG;
+		reg = omap_readw(UDC_TXDMA_CFG);
 	else
-		reg = UDC_RXDMA_CFG_REG;
+		reg = omap_readw(UDC_RXDMA_CFG);
 	reg |= UDC_DMA_REQ;		/* "pulse" activated */
 
 	ep->dma_channel = 0;
@@ -792,7 +778,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 		status = omap_request_dma(dma_channel,
 			ep->ep.name, dma_error, ep, &ep->lch);
 		if (status == 0) {
-			UDC_TXDMA_CFG_REG = reg;
+			omap_writew(reg, UDC_TXDMA_CFG);
 			/* EMIFF or SDRC */
 			omap_set_dma_src_burst_mode(ep->lch,
 						OMAP_DMA_DATA_BURST_4);
@@ -801,7 +787,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 			omap_set_dma_dest_params(ep->lch,
 				OMAP_DMA_PORT_TIPB,
 				OMAP_DMA_AMODE_CONSTANT,
-				(unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
+				UDC_DATA_DMA,
 				0, 0);
 		}
 	} else {
@@ -813,12 +799,12 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 		status = omap_request_dma(dma_channel,
 			ep->ep.name, dma_error, ep, &ep->lch);
 		if (status == 0) {
-			UDC_RXDMA_CFG_REG = reg;
+			omap_writew(reg, UDC_RXDMA_CFG);
 			/* TIPB */
 			omap_set_dma_src_params(ep->lch,
 				OMAP_DMA_PORT_TIPB,
 				OMAP_DMA_AMODE_CONSTANT,
-				(unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
+				UDC_DATA_DMA,
 				0, 0);
 			/* EMIFF or SDRC */
 			omap_set_dma_dest_burst_mode(ep->lch,
@@ -834,7 +820,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 
 		/* channel type P: hw synch (fifo) */
 		if (cpu_class_is_omap1() && !cpu_is_omap15xx())
-			OMAP1_DMA_LCH_CTRL_REG(ep->lch) = 2;
+			omap_set_dma_channel_mode(ep->lch, OMAP_DMA_LCH_P);
 	}
 
 just_restart:
@@ -860,7 +846,7 @@ just_restart:
 			(is_in ? write_fifo : read_fifo)(ep, req);
 			deselect_ep();
 			if (!is_in) {
-				UDC_CTRL_REG = UDC_SET_FIFO_EN;
+				omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
 				ep->ackwait = 1 + ep->double_buf;
 			}
 			/* IN: 6 wait states before it'll tx */
@@ -881,7 +867,7 @@ static void dma_channel_release(struct omap_ep *ep)
 	else
 		req = NULL;
 
-	active = ((1 << 7) & OMAP_DMA_CCR_REG(ep->lch)) != 0;
+	active = omap_get_dma_active_status(ep->lch);
 
 	DBG("%s release %s %cxdma%d %p\n", ep->ep.name,
 			active ? "active" : "idle",
@@ -894,23 +880,25 @@ static void dma_channel_release(struct omap_ep *ep)
 
 	/* wait till current packet DMA finishes, and fifo empties */
 	if (ep->bEndpointAddress & USB_DIR_IN) {
-		UDC_TXDMA_CFG_REG = (UDC_TXDMA_CFG_REG & ~mask) | UDC_DMA_REQ;
+		omap_writew((omap_readw(UDC_TXDMA_CFG) & ~mask) | UDC_DMA_REQ,
+					UDC_TXDMA_CFG);
 
 		if (req) {
 			finish_in_dma(ep, req, -ECONNRESET);
 
 			/* clear FIFO; hosts probably won't empty it */
 			use_ep(ep, UDC_EP_SEL);
-			UDC_CTRL_REG = UDC_CLR_EP;
+			omap_writew(UDC_CLR_EP, UDC_CTRL);
 			deselect_ep();
 		}
-		while (UDC_TXDMA_CFG_REG & mask)
+		while (omap_readw(UDC_TXDMA_CFG) & mask)
 			udelay(10);
 	} else {
-		UDC_RXDMA_CFG_REG = (UDC_RXDMA_CFG_REG & ~mask) | UDC_DMA_REQ;
+		omap_writew((omap_readw(UDC_RXDMA_CFG) & ~mask) | UDC_DMA_REQ,
+					UDC_RXDMA_CFG);
 
 		/* dma empties the fifo */
-		while (UDC_RXDMA_CFG_REG & mask)
+		while (omap_readw(UDC_RXDMA_CFG) & mask)
 			udelay(10);
 		if (req)
 			finish_out_dma(ep, req, -ECONNRESET, 0);
@@ -997,9 +985,13 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	req->req.actual = 0;
 
 	/* maybe kickstart non-iso i/o queues */
-	if (is_iso)
-		UDC_IRQ_EN_REG |= UDC_SOF_IE;
-	else if (list_empty(&ep->queue) && !ep->stopped && !ep->ackwait) {
+	if (is_iso) {
+		u16 w;
+
+		w = omap_readw(UDC_IRQ_EN);
+		w |= UDC_SOF_IE;
+		omap_writew(w, UDC_IRQ_EN);
+	} else if (list_empty(&ep->queue) && !ep->stopped && !ep->ackwait) {
 		int	is_in;
 
 		if (ep->bEndpointAddress == 0) {
@@ -1017,23 +1009,23 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 				 * requests to non-control endpoints
 				 */
 				if (udc->ep0_set_config) {
-					u16	irq_en = UDC_IRQ_EN_REG;
+					u16	irq_en = omap_readw(UDC_IRQ_EN);
 
 					irq_en |= UDC_DS_CHG_IE | UDC_EP0_IE;
 					if (!udc->ep0_reset_config)
 						irq_en |= UDC_EPN_RX_IE
 							| UDC_EPN_TX_IE;
-					UDC_IRQ_EN_REG = irq_en;
+					omap_writew(irq_en, UDC_IRQ_EN);
 				}
 
 				/* STATUS for zero length DATA stages is
 				 * always an IN ... even for IN transfers,
 				 * a weird case which seem to stall OMAP.
 				 */
-				UDC_EP_NUM_REG = (UDC_EP_SEL|UDC_EP_DIR);
-				UDC_CTRL_REG = UDC_CLR_EP;
-				UDC_CTRL_REG = UDC_SET_FIFO_EN;
-				UDC_EP_NUM_REG = UDC_EP_DIR;
+				omap_writew(UDC_EP_SEL | UDC_EP_DIR, UDC_EP_NUM);
+				omap_writew(UDC_CLR_EP, UDC_CTRL);
+				omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+				omap_writew(UDC_EP_DIR, UDC_EP_NUM);
 
 				/* cleanup */
 				udc->ep0_pending = 0;
@@ -1042,11 +1034,11 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
 			/* non-empty DATA stage */
 			} else if (is_in) {
-				UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
+				omap_writew(UDC_EP_SEL | UDC_EP_DIR, UDC_EP_NUM);
 			} else {
 				if (udc->ep0_setup)
 					goto irq_wait;
-				UDC_EP_NUM_REG = UDC_EP_SEL;
+				omap_writew(UDC_EP_SEL, UDC_EP_NUM);
 			}
 		} else {
 			is_in = ep->bEndpointAddress & USB_DIR_IN;
@@ -1062,7 +1054,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 				req = NULL;
 			deselect_ep();
 			if (!is_in) {
-				UDC_CTRL_REG = UDC_SET_FIFO_EN;
+				omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
 				ep->ackwait = 1 + ep->double_buf;
 			}
 			/* IN: 6 wait states before it'll tx */
@@ -1129,10 +1121,10 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value)
 			status = -EINVAL;
 		else if (value) {
 			if (ep->udc->ep0_set_config) {
-				WARN("error changing config?\n");
-				UDC_SYSCON2_REG = UDC_CLR_CFG;
+				WARNING("error changing config?\n");
+				omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
 			}
-			UDC_SYSCON2_REG = UDC_STALL_CMD;
+			omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
 			ep->udc->ep0_pending = 0;
 			status = 0;
 		} else /* NOP */
@@ -1159,8 +1151,8 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value)
 				channel = 0;
 
 			use_ep(ep, UDC_EP_SEL);
-			if (UDC_STAT_FLG_REG & UDC_NON_ISO_FIFO_EMPTY) {
-				UDC_CTRL_REG = UDC_SET_HALT;
+			if (omap_readw(UDC_STAT_FLG) & UDC_NON_ISO_FIFO_EMPTY) {
+				omap_writew(UDC_SET_HALT, UDC_CTRL);
 				status = 0;
 			} else
 				status = -EAGAIN;
@@ -1170,10 +1162,10 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value)
 				dma_channel_claim(ep, channel);
 		} else {
 			use_ep(ep, 0);
-			UDC_CTRL_REG = ep->udc->clr_halt;
+			omap_writew(ep->udc->clr_halt, UDC_CTRL);
 			ep->ackwait = 0;
 			if (!(ep->bEndpointAddress & USB_DIR_IN)) {
-				UDC_CTRL_REG = UDC_SET_FIFO_EN;
+				omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
 				ep->ackwait = 1 + ep->double_buf;
 			}
 		}
@@ -1205,7 +1197,7 @@ static struct usb_ep_ops omap_ep_ops = {
 
 static int omap_get_frame(struct usb_gadget *gadget)
 {
-	u16	sof = UDC_SOF_REG;
+	u16	sof = omap_readw(UDC_SOF);
 	return (sof & UDC_TS_OK) ? (sof & UDC_TS) : -EL2NSYNC;
 }
 
@@ -1224,7 +1216,7 @@ static int omap_wakeup(struct usb_gadget *gadget)
 		 */
 		if (udc->devstat & (UDC_B_HNP_ENABLE|UDC_R_WK_OK)) {
 			DBG("remote wakeup...\n");
-			UDC_SYSCON2_REG = UDC_RMT_WKP;
+			omap_writew(UDC_RMT_WKP, UDC_SYSCON2);
 			retval = 0;
 		}
 
@@ -1247,12 +1239,12 @@ omap_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
 
 	udc = container_of(gadget, struct omap_udc, gadget);
 	spin_lock_irqsave(&udc->lock, flags);
-	syscon1 = UDC_SYSCON1_REG;
+	syscon1 = omap_readw(UDC_SYSCON1);
 	if (is_selfpowered)
 		syscon1 |= UDC_SELF_PWR;
 	else
 		syscon1 &= ~UDC_SELF_PWR;
-	UDC_SYSCON1_REG = syscon1;
+	omap_writew(syscon1, UDC_SYSCON1);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 	return 0;
@@ -1265,18 +1257,36 @@ static int can_pullup(struct omap_udc *udc)
 
 static void pullup_enable(struct omap_udc *udc)
 {
-	UDC_SYSCON1_REG |= UDC_PULLUP_EN;
-	if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx())
-		OTG_CTRL_REG |= OTG_BSESSVLD;
-	UDC_IRQ_EN_REG = UDC_DS_CHG_IE;
+	u16 w;
+
+	w = omap_readw(UDC_SYSCON1);
+	w |= UDC_PULLUP_EN;
+	omap_writew(w, UDC_SYSCON1);
+	if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) {
+		u32 l;
+
+		l = omap_readl(OTG_CTRL);
+		l |= OTG_BSESSVLD;
+		omap_writel(l, OTG_CTRL);
+	}
+	omap_writew(UDC_DS_CHG_IE, UDC_IRQ_EN);
 }
 
 static void pullup_disable(struct omap_udc *udc)
 {
-	if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx())
-		OTG_CTRL_REG &= ~OTG_BSESSVLD;
-	UDC_IRQ_EN_REG = UDC_DS_CHG_IE;
-	UDC_SYSCON1_REG &= ~UDC_PULLUP_EN;
+	u16 w;
+
+	if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) {
+		u32 l;
+
+		l = omap_readl(OTG_CTRL);
+		l &= ~OTG_BSESSVLD;
+		omap_writel(l, OTG_CTRL);
+	}
+	omap_writew(UDC_DS_CHG_IE, UDC_IRQ_EN);
+	w = omap_readw(UDC_SYSCON1);
+	w &= ~UDC_PULLUP_EN;
+	omap_writew(w, UDC_SYSCON1);
 }
 
 static struct omap_udc *udc;
@@ -1304,6 +1314,7 @@ static int omap_vbus_session(struct usb_gadget *gadget, int is_active)
 {
 	struct omap_udc	*udc;
 	unsigned long	flags;
+	u32 l;
 
 	udc = container_of(gadget, struct omap_udc, gadget);
 	spin_lock_irqsave(&udc->lock, flags);
@@ -1311,10 +1322,12 @@ static int omap_vbus_session(struct usb_gadget *gadget, int is_active)
 	udc->vbus_active = (is_active != 0);
 	if (cpu_is_omap15xx()) {
 		/* "software" detect, ignored if !VBUS_MODE_1510 */
+		l = omap_readl(FUNC_MUX_CTRL_0);
 		if (is_active)
-			FUNC_MUX_CTRL_0_REG |= VBUS_CTRL_1510;
+			l |= VBUS_CTRL_1510;
 		else
-			FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510;
+			l &= ~VBUS_CTRL_1510;
+		omap_writel(l, FUNC_MUX_CTRL_0);
 	}
 	if (udc->dc_clk != NULL && is_active) {
 		if (!udc->clk_requested) {
@@ -1384,9 +1397,9 @@ static void nuke(struct omap_ep *ep, int status)
 		dma_channel_release(ep);
 
 	use_ep(ep, 0);
-	UDC_CTRL_REG = UDC_CLR_EP;
+	omap_writew(UDC_CLR_EP, UDC_CTRL);
 	if (ep->bEndpointAddress && ep->bmAttributes != USB_ENDPOINT_XFER_ISOC)
-		UDC_CTRL_REG = UDC_SET_HALT;
+		omap_writew(UDC_SET_HALT, UDC_CTRL);
 
 	while (!list_empty(&ep->queue)) {
 		req = list_entry(ep->queue.next, struct omap_req, queue);
@@ -1414,8 +1427,8 @@ static void update_otg(struct omap_udc *udc)
 	if (!gadget_is_otg(&udc->gadget))
 		return;
 
-	if (OTG_CTRL_REG & OTG_ID)
-		devstat = UDC_DEVSTAT_REG;
+	if (omap_readl(OTG_CTRL) & OTG_ID)
+		devstat = omap_readw(UDC_DEVSTAT);
 	else
 		devstat = 0;
 
@@ -1426,9 +1439,14 @@ static void update_otg(struct omap_udc *udc)
 	/* Enable HNP early, avoiding races on suspend irq path.
 	 * ASSUMES OTG state machine B_BUS_REQ input is true.
 	 */
-	if (udc->gadget.b_hnp_enable)
-		OTG_CTRL_REG = (OTG_CTRL_REG | OTG_B_HNPEN | OTG_B_BUSREQ)
-				& ~OTG_PULLUP;
+	if (udc->gadget.b_hnp_enable) {
+		u32 l;
+
+		l = omap_readl(OTG_CTRL);
+		l |= OTG_B_HNPEN | OTG_B_BUSREQ;
+		l &= ~OTG_PULLUP;
+		omap_writel(l, OTG_CTRL);
+	}
 }
 
 static void ep0_irq(struct omap_udc *udc, u16 irq_src)
@@ -1446,7 +1464,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
 
 		nuke(ep0, 0);
 		if (ack) {
-			UDC_IRQ_SRC_REG = ack;
+			omap_writew(ack, UDC_IRQ_SRC);
 			irq_src = UDC_SETUP;
 		}
 	}
@@ -1466,9 +1484,9 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
 	if (irq_src & UDC_EP0_TX) {
 		int	stat;
 
-		UDC_IRQ_SRC_REG = UDC_EP0_TX;
-		UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
-		stat = UDC_STAT_FLG_REG;
+		omap_writew(UDC_EP0_TX, UDC_IRQ_SRC);
+		omap_writew(UDC_EP_SEL|UDC_EP_DIR, UDC_EP_NUM);
+		stat = omap_readw(UDC_STAT_FLG);
 		if (stat & UDC_ACK) {
 			if (udc->ep0_in) {
 				/* write next IN packet from response,
@@ -1476,26 +1494,26 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
 				 */
 				if (req)
 					stat = write_fifo(ep0, req);
-				UDC_EP_NUM_REG = UDC_EP_DIR;
+				omap_writew(UDC_EP_DIR, UDC_EP_NUM);
 				if (!req && udc->ep0_pending) {
-					UDC_EP_NUM_REG = UDC_EP_SEL;
-					UDC_CTRL_REG = UDC_CLR_EP;
-					UDC_CTRL_REG = UDC_SET_FIFO_EN;
-					UDC_EP_NUM_REG = 0;
+					omap_writew(UDC_EP_SEL, UDC_EP_NUM);
+					omap_writew(UDC_CLR_EP, UDC_CTRL);
+					omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+					omap_writew(0, UDC_EP_NUM);
 					udc->ep0_pending = 0;
 				} /* else:  6 wait states before it'll tx */
 			} else {
 				/* ack status stage of OUT transfer */
-				UDC_EP_NUM_REG = UDC_EP_DIR;
+				omap_writew(UDC_EP_DIR, UDC_EP_NUM);
 				if (req)
 					done(ep0, req, 0);
 			}
 			req = NULL;
 		} else if (stat & UDC_STALL) {
-			UDC_CTRL_REG = UDC_CLR_HALT;
-			UDC_EP_NUM_REG = UDC_EP_DIR;
+			omap_writew(UDC_CLR_HALT, UDC_CTRL);
+			omap_writew(UDC_EP_DIR, UDC_EP_NUM);
 		} else {
-			UDC_EP_NUM_REG = UDC_EP_DIR;
+			omap_writew(UDC_EP_DIR, UDC_EP_NUM);
 		}
 	}
 
@@ -1503,9 +1521,9 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
 	if (irq_src & UDC_EP0_RX) {
 		int	stat;
 
-		UDC_IRQ_SRC_REG = UDC_EP0_RX;
-		UDC_EP_NUM_REG = UDC_EP_SEL;
-		stat = UDC_STAT_FLG_REG;
+		omap_writew(UDC_EP0_RX, UDC_IRQ_SRC);
+		omap_writew(UDC_EP_SEL, UDC_EP_NUM);
+		stat = omap_readw(UDC_STAT_FLG);
 		if (stat & UDC_ACK) {
 			if (!udc->ep0_in) {
 				stat = 0;
@@ -1513,34 +1531,35 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
 				 * reactiviting the fifo; stall on errors.
 				 */
 				if (!req || (stat = read_fifo(ep0, req)) < 0) {
-					UDC_SYSCON2_REG = UDC_STALL_CMD;
+					omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
 					udc->ep0_pending = 0;
 					stat = 0;
 				} else if (stat == 0)
-					UDC_CTRL_REG = UDC_SET_FIFO_EN;
-				UDC_EP_NUM_REG = 0;
+					omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+				omap_writew(0, UDC_EP_NUM);
 
 				/* activate status stage */
 				if (stat == 1) {
 					done(ep0, req, 0);
 					/* that may have STALLed ep0... */
-					UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
-					UDC_CTRL_REG = UDC_CLR_EP;
-					UDC_CTRL_REG = UDC_SET_FIFO_EN;
-					UDC_EP_NUM_REG = UDC_EP_DIR;
+					omap_writew(UDC_EP_SEL | UDC_EP_DIR,
+							UDC_EP_NUM);
+					omap_writew(UDC_CLR_EP, UDC_CTRL);
+					omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+					omap_writew(UDC_EP_DIR, UDC_EP_NUM);
 					udc->ep0_pending = 0;
 				}
 			} else {
 				/* ack status stage of IN transfer */
-				UDC_EP_NUM_REG = 0;
+				omap_writew(0, UDC_EP_NUM);
 				if (req)
 					done(ep0, req, 0);
 			}
 		} else if (stat & UDC_STALL) {
-			UDC_CTRL_REG = UDC_CLR_HALT;
-			UDC_EP_NUM_REG = 0;
+			omap_writew(UDC_CLR_HALT, UDC_CTRL);
+			omap_writew(0, UDC_EP_NUM);
 		} else {
-			UDC_EP_NUM_REG = 0;
+			omap_writew(0, UDC_EP_NUM);
 		}
 	}
 
@@ -1555,14 +1574,14 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
 
 		/* read the (latest) SETUP message */
 		do {
-			UDC_EP_NUM_REG = UDC_SETUP_SEL;
+			omap_writew(UDC_SETUP_SEL, UDC_EP_NUM);
 			/* two bytes at a time */
-			u.word[0] = UDC_DATA_REG;
-			u.word[1] = UDC_DATA_REG;
-			u.word[2] = UDC_DATA_REG;
-			u.word[3] = UDC_DATA_REG;
-			UDC_EP_NUM_REG = 0;
-		} while (UDC_IRQ_SRC_REG & UDC_SETUP);
+			u.word[0] = omap_readw(UDC_DATA);
+			u.word[1] = omap_readw(UDC_DATA);
+			u.word[2] = omap_readw(UDC_DATA);
+			u.word[3] = omap_readw(UDC_DATA);
+			omap_writew(0, UDC_EP_NUM);
+		} while (omap_readw(UDC_IRQ_SRC) & UDC_SETUP);
 
 #define	w_value		le16_to_cpu(u.r.wValue)
 #define	w_index		le16_to_cpu(u.r.wIndex)
@@ -1593,9 +1612,9 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
 			 * later if it fails the request.
 			 */
 			if (udc->ep0_reset_config)
-				UDC_SYSCON2_REG = UDC_CLR_CFG;
+				omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
 			else
-				UDC_SYSCON2_REG = UDC_DEV_CFG;
+				omap_writew(UDC_DEV_CFG, UDC_SYSCON2);
 			update_otg(udc);
 			goto delegate;
 		case USB_REQ_CLEAR_FEATURE:
@@ -1613,10 +1632,10 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
 						|| !ep->desc)
 					goto do_stall;
 				use_ep(ep, 0);
-				UDC_CTRL_REG = udc->clr_halt;
+				omap_writew(udc->clr_halt, UDC_CTRL);
 				ep->ackwait = 0;
 				if (!(ep->bEndpointAddress & USB_DIR_IN)) {
-					UDC_CTRL_REG = UDC_SET_FIFO_EN;
+					omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
 					ep->ackwait = 1 + ep->double_buf;
 				}
 				/* NOTE:  assumes the host behaves sanely,
@@ -1649,15 +1668,15 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
 			}
 			use_ep(ep, 0);
 			/* can't halt if fifo isn't empty... */
-			UDC_CTRL_REG = UDC_CLR_EP;
-			UDC_CTRL_REG = UDC_SET_HALT;
+			omap_writew(UDC_CLR_EP, UDC_CTRL);
+			omap_writew(UDC_SET_HALT, UDC_CTRL);
 			VDBG("%s halted by host\n", ep->name);
 ep0out_status_stage:
 			status = 0;
-			UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
-			UDC_CTRL_REG = UDC_CLR_EP;
-			UDC_CTRL_REG = UDC_SET_FIFO_EN;
-			UDC_EP_NUM_REG = UDC_EP_DIR;
+			omap_writew(UDC_EP_SEL|UDC_EP_DIR, UDC_EP_NUM);
+			omap_writew(UDC_CLR_EP, UDC_CTRL);
+			omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+			omap_writew(UDC_EP_DIR, UDC_EP_NUM);
 			udc->ep0_pending = 0;
 			break;
 		case USB_REQ_GET_STATUS:
@@ -1694,10 +1713,10 @@ intf_status:
 
 zero_status:
 			/* return two zero bytes */
-			UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
-			UDC_DATA_REG = 0;
-			UDC_CTRL_REG = UDC_SET_FIFO_EN;
-			UDC_EP_NUM_REG = UDC_EP_DIR;
+			omap_writew(UDC_EP_SEL|UDC_EP_DIR, UDC_EP_NUM);
+			omap_writew(0, UDC_DATA);
+			omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
+			omap_writew(UDC_EP_DIR, UDC_EP_NUM);
 			status = 0;
 			VDBG("GET_STATUS, interface %d\n", w_index);
 			/* next, status stage */
@@ -1706,8 +1725,8 @@ zero_status:
 delegate:
 			/* activate the ep0out fifo right away */
 			if (!udc->ep0_in && w_length) {
-				UDC_EP_NUM_REG = 0;
-				UDC_CTRL_REG = UDC_SET_FIFO_EN;
+				omap_writew(0, UDC_EP_NUM);
+				omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
 			}
 
 			/* gadget drivers see class/vendor specific requests,
@@ -1746,11 +1765,11 @@ do_stall:
 					u.r.bRequestType, u.r.bRequest, status);
 			if (udc->ep0_set_config) {
 				if (udc->ep0_reset_config)
-					WARN("error resetting config?\n");
+					WARNING("error resetting config?\n");
 				else
-					UDC_SYSCON2_REG = UDC_CLR_CFG;
+					omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
 			}
-			UDC_SYSCON2_REG = UDC_STALL_CMD;
+			omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
 			udc->ep0_pending = 0;
 		}
 	}
@@ -1764,7 +1783,7 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
 {
 	u16	devstat, change;
 
-	devstat = UDC_DEVSTAT_REG;
+	devstat = omap_readw(UDC_DEVSTAT);
 	change = devstat ^ udc->devstat;
 	udc->devstat = devstat;
 
@@ -1804,7 +1823,8 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
 				INFO("USB reset done, gadget %s\n",
 					udc->driver->driver.name);
 				/* ep0 traffic is legal from now on */
-				UDC_IRQ_EN_REG = UDC_DS_CHG_IE | UDC_EP0_IE;
+				omap_writew(UDC_DS_CHG_IE | UDC_EP0_IE,
+						UDC_IRQ_EN);
 			}
 			change &= ~UDC_USB_RESET;
 		}
@@ -1848,7 +1868,7 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
 		VDBG("devstat %03x, ignore change %03x\n",
 			devstat,  change);
 
-	UDC_IRQ_SRC_REG = UDC_DS_CHG;
+	omap_writew(UDC_DS_CHG, UDC_IRQ_SRC);
 }
 
 static irqreturn_t omap_udc_irq(int irq, void *_udc)
@@ -1859,7 +1879,7 @@ static irqreturn_t omap_udc_irq(int irq, void *_udc)
 	unsigned long	flags;
 
 	spin_lock_irqsave(&udc->lock, flags);
-	irq_src = UDC_IRQ_SRC_REG;
+	irq_src = omap_readw(UDC_IRQ_SRC);
 
 	/* Device state change (usb ch9 stuff) */
 	if (irq_src & UDC_DS_CHG) {
@@ -1882,7 +1902,7 @@ static irqreturn_t omap_udc_irq(int irq, void *_udc)
 		irq_src &= ~(UDC_TXN_DONE|UDC_RXN_CNT|UDC_RXN_EOT);
 	}
 
-	irq_src &= ~(UDC_SOF|UDC_EPN_TX|UDC_EPN_RX);
+	irq_src &= ~(UDC_IRQ_SOF | UDC_EPN_TX|UDC_EPN_RX);
 	if (irq_src)
 		DBG("udc_irq, unhandled %03x\n", irq_src);
 	spin_unlock_irqrestore(&udc->lock, flags);
@@ -1903,7 +1923,7 @@ static void pio_out_timer(unsigned long _ep)
 	spin_lock_irqsave(&ep->udc->lock, flags);
 	if (!list_empty(&ep->queue) && ep->ackwait) {
 		use_ep(ep, UDC_EP_SEL);
-		stat_flg = UDC_STAT_FLG_REG;
+		stat_flg = omap_readw(UDC_STAT_FLG);
 
 		if ((stat_flg & UDC_ACK) && (!(stat_flg & UDC_FIFO_EN)
 				|| (ep->double_buf && HALF_FULL(stat_flg)))) {
@@ -1913,8 +1933,8 @@ static void pio_out_timer(unsigned long _ep)
 			req = container_of(ep->queue.next,
 					struct omap_req, queue);
 			(void) read_fifo(ep, req);
-			UDC_EP_NUM_REG = ep->bEndpointAddress;
-			UDC_CTRL_REG = UDC_SET_FIFO_EN;
+			omap_writew(ep->bEndpointAddress, UDC_EP_NUM);
+			omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
 			ep->ackwait = 1 + ep->double_buf;
 		} else
 			deselect_ep();
@@ -1934,20 +1954,20 @@ static irqreturn_t omap_udc_pio_irq(int irq, void *_dev)
 	unsigned long	flags;
 
 	spin_lock_irqsave(&udc->lock, flags);
-	epn_stat = UDC_EPN_STAT_REG;
-	irq_src = UDC_IRQ_SRC_REG;
+	epn_stat = omap_readw(UDC_EPN_STAT);
+	irq_src = omap_readw(UDC_IRQ_SRC);
 
 	/* handle OUT first, to avoid some wasteful NAKs */
 	if (irq_src & UDC_EPN_RX) {
 		epnum = (epn_stat >> 8) & 0x0f;
-		UDC_IRQ_SRC_REG = UDC_EPN_RX;
+		omap_writew(UDC_EPN_RX, UDC_IRQ_SRC);
 		status = IRQ_HANDLED;
 		ep = &udc->ep[epnum];
 		ep->irqs++;
 
-		UDC_EP_NUM_REG = epnum | UDC_EP_SEL;
+		omap_writew(epnum | UDC_EP_SEL, UDC_EP_NUM);
 		ep->fnf = 0;
-		if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+		if (omap_readw(UDC_STAT_FLG) & UDC_ACK) {
 			ep->ackwait--;
 			if (!list_empty(&ep->queue)) {
 				int stat;
@@ -1959,15 +1979,15 @@ static irqreturn_t omap_udc_pio_irq(int irq, void *_dev)
 			}
 		}
 		/* min 6 clock delay before clearing EP_SEL ... */
-		epn_stat = UDC_EPN_STAT_REG;
-		epn_stat = UDC_EPN_STAT_REG;
-		UDC_EP_NUM_REG = epnum;
+		epn_stat = omap_readw(UDC_EPN_STAT);
+		epn_stat = omap_readw(UDC_EPN_STAT);
+		omap_writew(epnum, UDC_EP_NUM);
 
 		/* enabling fifo _after_ clearing ACK, contrary to docs,
 		 * reduces lossage; timer still needed though (sigh).
 		 */
 		if (ep->fnf) {
-			UDC_CTRL_REG = UDC_SET_FIFO_EN;
+			omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);
 			ep->ackwait = 1 + ep->double_buf;
 		}
 		mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
@@ -1976,13 +1996,13 @@ static irqreturn_t omap_udc_pio_irq(int irq, void *_dev)
 	/* then IN transfers */
 	else if (irq_src & UDC_EPN_TX) {
 		epnum = epn_stat & 0x0f;
-		UDC_IRQ_SRC_REG = UDC_EPN_TX;
+		omap_writew(UDC_EPN_TX, UDC_IRQ_SRC);
 		status = IRQ_HANDLED;
 		ep = &udc->ep[16 + epnum];
 		ep->irqs++;
 
-		UDC_EP_NUM_REG = epnum | UDC_EP_DIR | UDC_EP_SEL;
-		if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+		omap_writew(epnum | UDC_EP_DIR | UDC_EP_SEL, UDC_EP_NUM);
+		if (omap_readw(UDC_STAT_FLG) & UDC_ACK) {
 			ep->ackwait = 0;
 			if (!list_empty(&ep->queue)) {
 				req = container_of(ep->queue.next,
@@ -1991,9 +2011,9 @@ static irqreturn_t omap_udc_pio_irq(int irq, void *_dev)
 			}
 		}
 		/* min 6 clock delay before clearing EP_SEL ... */
-		epn_stat = UDC_EPN_STAT_REG;
-		epn_stat = UDC_EPN_STAT_REG;
-		UDC_EP_NUM_REG = epnum | UDC_EP_DIR;
+		epn_stat = omap_readw(UDC_EPN_STAT);
+		epn_stat = omap_readw(UDC_EPN_STAT);
+		omap_writew(epnum | UDC_EP_DIR, UDC_EP_NUM);
 		/* then 6 clocks before it'd tx */
 	}
 
@@ -2021,7 +2041,7 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev)
 		req = list_entry(ep->queue.next, struct omap_req, queue);
 
 		use_ep(ep, UDC_EP_SEL);
-		stat = UDC_STAT_FLG_REG;
+		stat = omap_readw(UDC_STAT_FLG);
 
 		/* NOTE: like the other controller drivers, this isn't
 		 * currently reporting lost or damaged frames.
@@ -2053,9 +2073,14 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev)
 		if (!list_empty(&ep->queue))
 			pending = 1;
 	}
-	if (!pending)
-		UDC_IRQ_EN_REG &= ~UDC_SOF_IE;
-	UDC_IRQ_SRC_REG = UDC_SOF;
+	if (!pending) {
+		u16 w;
+
+		w = omap_readw(UDC_IRQ_EN);
+		w &= ~UDC_SOF_IE;
+		omap_writew(w, UDC_IRQ_EN);
+	}
+	omap_writew(UDC_IRQ_SOF, UDC_IRQ_SRC);
 
 	spin_unlock_irqrestore(&udc->lock, flags);
 	return IRQ_HANDLED;
@@ -2104,7 +2129,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
 		if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
 			continue;
 		use_ep(ep, 0);
-		UDC_CTRL_REG = UDC_SET_HALT;
+		omap_writew(UDC_SET_HALT, UDC_CTRL);
 	}
 	udc->ep0_pending = 0;
 	udc->ep[0].irqs = 0;
@@ -2128,7 +2153,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
 	}
 	DBG("bound to driver %s\n", driver->driver.name);
 
-	UDC_IRQ_SRC_REG = UDC_IRQ_SRC_MASK;
+	omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
 
 	/* connect to bus through transceiver */
 	if (udc->transceiver) {
@@ -2225,7 +2250,7 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep)
 	else
 		buf[0] = 0;
 
-	stat_flg = UDC_STAT_FLG_REG;
+	stat_flg = omap_readw(UDC_STAT_FLG);
 	seq_printf(s,
 		"\n%s %s%s%sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n",
 		ep->name, buf,
@@ -2286,17 +2311,17 @@ static int proc_otg_show(struct seq_file *s)
 	u32		trans;
 	char		*ctrl_name;
 
-	tmp = OTG_REV_REG;
+	tmp = omap_readl(OTG_REV);
 	if (cpu_is_omap24xx()) {
 		ctrl_name = "control_devconf";
-		trans = CONTROL_DEVCONF_REG;
+		trans = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
 	} else {
 		ctrl_name = "tranceiver_ctrl";
-		trans = USB_TRANSCEIVER_CTRL_REG;
+		trans = omap_readw(USB_TRANSCEIVER_CTRL);
 	}
 	seq_printf(s, "\nOTG rev %d.%d, %s %05x\n",
 		tmp >> 4, tmp & 0xf, ctrl_name, trans);
-	tmp = OTG_SYSCON_1_REG;
+	tmp = omap_readw(OTG_SYSCON_1);
 	seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s,"
 			FOURBITS "\n", tmp,
 		trx_mode(USB2_TRX_MODE(tmp), trans & CONF_USB2_UNI_R),
@@ -2308,7 +2333,7 @@ static int proc_otg_show(struct seq_file *s)
 		(tmp & HST_IDLE_EN) ? " !host" : "",
 		(tmp & DEV_IDLE_EN) ? " !dev" : "",
 		(tmp & OTG_RESET_DONE) ? " reset_done" : " reset_active");
-	tmp = OTG_SYSCON_2_REG;
+	tmp = omap_readl(OTG_SYSCON_2);
 	seq_printf(s, "otg_syscon2 %08x%s" EIGHTBITS
 			" b_ase_brst=%d hmc=%d\n", tmp,
 		(tmp & OTG_EN) ? " otg_en" : "",
@@ -2323,7 +2348,7 @@ static int proc_otg_show(struct seq_file *s)
 		(tmp & HMC_TLLATTACH) ? " tllattach" : "",
 		B_ASE_BRST(tmp),
 		OTG_HMC(tmp));
-	tmp = OTG_CTRL_REG;
+	tmp = omap_readl(OTG_CTRL);
 	seq_printf(s, "otg_ctrl    %06x" EIGHTBITS EIGHTBITS "%s\n", tmp,
 		(tmp & OTG_ASESSVLD) ? " asess" : "",
 		(tmp & OTG_BSESSEND) ? " bsess_end" : "",
@@ -2343,13 +2368,13 @@ static int proc_otg_show(struct seq_file *s)
 		(tmp & OTG_PU_VBUS) ? " pu_vb" : "",
 		(tmp & OTG_PU_ID) ? " pu_id" : ""
 		);
-	tmp = OTG_IRQ_EN_REG;
+	tmp = omap_readw(OTG_IRQ_EN);
 	seq_printf(s, "otg_irq_en  %04x" "\n", tmp);
-	tmp = OTG_IRQ_SRC_REG;
+	tmp = omap_readw(OTG_IRQ_SRC);
 	seq_printf(s, "otg_irq_src %04x" "\n", tmp);
-	tmp = OTG_OUTCTRL_REG;
+	tmp = omap_readw(OTG_OUTCTRL);
 	seq_printf(s, "otg_outctrl %04x" "\n", tmp);
-	tmp = OTG_TEST_REG;
+	tmp = omap_readw(OTG_TEST);
 	seq_printf(s, "otg_test    %04x" "\n", tmp);
 	return 0;
 }
@@ -2370,7 +2395,7 @@ static int proc_udc_show(struct seq_file *s, void *_)
 		driver_desc,
 		use_dma ?  " (dma)" : "");
 
-	tmp = UDC_REV_REG & 0xff;
+	tmp = omap_readw(UDC_REV) & 0xff;
 	seq_printf(s,
 		"UDC rev %d.%d, fifo mode %d, gadget %s\n"
 		"hmc %d, transceiver %s\n",
@@ -2384,16 +2409,16 @@ static int proc_udc_show(struct seq_file *s, void *_)
 				? "external" : "(none)"));
 	if (cpu_class_is_omap1()) {
 		seq_printf(s, "ULPD control %04x req %04x status %04x\n",
-			__REG16(ULPD_CLOCK_CTRL),
-			__REG16(ULPD_SOFT_REQ),
-			__REG16(ULPD_STATUS_REQ));
+			omap_readw(ULPD_CLOCK_CTRL),
+			omap_readw(ULPD_SOFT_REQ),
+			omap_readw(ULPD_STATUS_REQ));
 	}
 
 	/* OTG controller registers */
 	if (!cpu_is_omap15xx())
 		proc_otg_show(s);
 
-	tmp = UDC_SYSCON1_REG;
+	tmp = omap_readw(UDC_SYSCON1);
 	seq_printf(s, "\nsyscon1     %04x" EIGHTBITS "\n", tmp,
 		(tmp & UDC_CFG_LOCK) ? " cfg_lock" : "",
 		(tmp & UDC_DATA_ENDIAN) ? " data_endian" : "",
@@ -2412,7 +2437,7 @@ static int proc_udc_show(struct seq_file *s, void *_)
 		return 0;
 	}
 
-	tmp = UDC_DEVSTAT_REG;
+	tmp = omap_readw(UDC_DEVSTAT);
 	seq_printf(s, "devstat     %04x" EIGHTBITS "%s%s\n", tmp,
 		(tmp & UDC_B_HNP_ENABLE) ? " b_hnp" : "",
 		(tmp & UDC_A_HNP_SUPPORT) ? " a_hnp" : "",
@@ -2424,20 +2449,20 @@ static int proc_udc_show(struct seq_file *s, void *_)
 		(tmp & UDC_ADD) ? " ADD" : "",
 		(tmp & UDC_DEF) ? " DEF" : "",
 		(tmp & UDC_ATT) ? " ATT" : "");
-	seq_printf(s, "sof         %04x\n", UDC_SOF_REG);
-	tmp = UDC_IRQ_EN_REG;
+	seq_printf(s, "sof         %04x\n", omap_readw(UDC_SOF));
+	tmp = omap_readw(UDC_IRQ_EN);
 	seq_printf(s, "irq_en      %04x" FOURBITS "%s\n", tmp,
 		(tmp & UDC_SOF_IE) ? " sof" : "",
 		(tmp & UDC_EPN_RX_IE) ? " epn_rx" : "",
 		(tmp & UDC_EPN_TX_IE) ? " epn_tx" : "",
 		(tmp & UDC_DS_CHG_IE) ? " ds_chg" : "",
 		(tmp & UDC_EP0_IE) ? " ep0" : "");
-	tmp = UDC_IRQ_SRC_REG;
+	tmp = omap_readw(UDC_IRQ_SRC);
 	seq_printf(s, "irq_src     %04x" EIGHTBITS "%s%s\n", tmp,
 		(tmp & UDC_TXN_DONE) ? " txn_done" : "",
 		(tmp & UDC_RXN_CNT) ? " rxn_cnt" : "",
 		(tmp & UDC_RXN_EOT) ? " rxn_eot" : "",
-		(tmp & UDC_SOF) ? " sof" : "",
+		(tmp & UDC_IRQ_SOF) ? " sof" : "",
 		(tmp & UDC_EPN_RX) ? " epn_rx" : "",
 		(tmp & UDC_EPN_TX) ? " epn_tx" : "",
 		(tmp & UDC_DS_CHG) ? " ds_chg" : "",
@@ -2447,7 +2472,7 @@ static int proc_udc_show(struct seq_file *s, void *_)
 	if (use_dma) {
 		unsigned i;
 
-		tmp = UDC_DMA_IRQ_EN_REG;
+		tmp = omap_readw(UDC_DMA_IRQ_EN);
 		seq_printf(s, "dma_irq_en  %04x%s" EIGHTBITS "\n", tmp,
 			(tmp & UDC_TX_DONE_IE(3)) ? " tx2_done" : "",
 			(tmp & UDC_RX_CNT_IE(3)) ? " rx2_cnt" : "",
@@ -2461,29 +2486,29 @@ static int proc_udc_show(struct seq_file *s, void *_)
 			(tmp & UDC_RX_CNT_IE(1)) ? " rx0_cnt" : "",
 			(tmp & UDC_RX_EOT_IE(1)) ? " rx0_eot" : "");
 
-		tmp = UDC_RXDMA_CFG_REG;
+		tmp = omap_readw(UDC_RXDMA_CFG);
 		seq_printf(s, "rxdma_cfg   %04x\n", tmp);
 		if (tmp) {
 			for (i = 0; i < 3; i++) {
 				if ((tmp & (0x0f << (i * 4))) == 0)
 					continue;
 				seq_printf(s, "rxdma[%d]    %04x\n", i,
-						UDC_RXDMA_REG(i + 1));
+						omap_readw(UDC_RXDMA(i + 1)));
 			}
 		}
-		tmp = UDC_TXDMA_CFG_REG;
+		tmp = omap_readw(UDC_TXDMA_CFG);
 		seq_printf(s, "txdma_cfg   %04x\n", tmp);
 		if (tmp) {
 			for (i = 0; i < 3; i++) {
 				if (!(tmp & (0x0f << (i * 4))))
 					continue;
 				seq_printf(s, "txdma[%d]    %04x\n", i,
-						UDC_TXDMA_REG(i + 1));
+						omap_readw(UDC_TXDMA(i + 1)));
 			}
 		}
 	}
 
-	tmp = UDC_DEVSTAT_REG;
+	tmp = omap_readw(UDC_DEVSTAT);
 	if (tmp & UDC_ATT) {
 		proc_ep_show(s, &udc->ep[0]);
 		if (tmp & UDC_ADD) {
@@ -2535,7 +2560,7 @@ static inline void remove_proc_file(void) {}
  * buffer space among the endpoints we'll be operating.
  *
  * NOTE: as of OMAP 1710 ES2.0, writing a new endpoint config when
- * UDC_SYSCON_1_REG.CFG_LOCK is set can now work.  We won't use that
+ * UDC_SYSCON_1.CFG_LOCK is set can now work.  We won't use that
  * capability yet though.
  */
 static unsigned __init
@@ -2597,9 +2622,9 @@ omap_ep_setup(char *name, u8 addr, u8 type,
 		name, addr, epn_rxtx, maxp, dbuf ? "x2" : "", buf);
 
 	if (addr & USB_DIR_IN)
-		UDC_EP_TX_REG(addr & 0xf) = epn_rxtx;
+		omap_writew(epn_rxtx, UDC_EP_TX(addr & 0xf));
 	else
-		UDC_EP_RX_REG(addr) = epn_rxtx;
+		omap_writew(epn_rxtx, UDC_EP_RX(addr));
 
 	/* next endpoint's buffer starts after this one's */
 	buf += maxp;
@@ -2638,15 +2663,15 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv)
 	unsigned	tmp, buf;
 
 	/* abolish any previous hardware state */
-	UDC_SYSCON1_REG = 0;
-	UDC_IRQ_EN_REG = 0;
-	UDC_IRQ_SRC_REG = UDC_IRQ_SRC_MASK;
-	UDC_DMA_IRQ_EN_REG = 0;
-	UDC_RXDMA_CFG_REG = 0;
-	UDC_TXDMA_CFG_REG = 0;
+	omap_writew(0, UDC_SYSCON1);
+	omap_writew(0, UDC_IRQ_EN);
+	omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
+	omap_writew(0, UDC_DMA_IRQ_EN);
+	omap_writew(0, UDC_RXDMA_CFG);
+	omap_writew(0, UDC_TXDMA_CFG);
 
 	/* UDC_PULLUP_EN gates the chip clock */
-	// OTG_SYSCON_1_REG |= DEV_IDLE_EN;
+	// OTG_SYSCON_1 |= DEV_IDLE_EN;
 
 	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
 	if (!udc)
@@ -2662,7 +2687,7 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv)
 	udc->gadget.name = driver_name;
 
 	device_initialize(&udc->gadget.dev);
-	strcpy (udc->gadget.dev.bus_id, "gadget");
+	dev_set_name(&udc->gadget.dev, "gadget");
 	udc->gadget.dev.release = omap_udc_release;
 	udc->gadget.dev.parent = &odev->dev;
 	if (use_dma)
@@ -2677,8 +2702,8 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv)
 
 	/* initially disable all non-ep0 endpoints */
 	for (tmp = 1; tmp < 15; tmp++) {
-		UDC_EP_RX_REG(tmp) = 0;
-		UDC_EP_TX_REG(tmp) = 0;
+		omap_writew(0, UDC_EP_RX(tmp));
+		omap_writew(0, UDC_EP_TX(tmp));
 	}
 
 #define OMAP_BULK_EP(name,addr) \
@@ -2763,7 +2788,7 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv)
 		ERR("unsupported fifo_mode #%d\n", fifo_mode);
 		return -ENODEV;
 	}
-	UDC_SYSCON1_REG = UDC_CFG_LOCK|UDC_SELF_PWR;
+	omap_writew(UDC_CFG_LOCK|UDC_SELF_PWR, UDC_SYSCON1);
 	INFO("fifo mode %d, %d bytes not used\n", fifo_mode, 2048 - buf);
 	return 0;
 }
@@ -2807,7 +2832,7 @@ static int __init omap_udc_probe(struct platform_device *pdev)
 	}
 
 	INFO("OMAP UDC rev %d.%d%s\n",
-		UDC_REV_REG >> 4, UDC_REV_REG & 0xf,
+		omap_readw(UDC_REV) >> 4, omap_readw(UDC_REV) & 0xf,
 		config->otg ? ", Mini-AB" : "");
 
 	/* use the mode given to us by board init code */
@@ -2822,12 +2847,12 @@ static int __init omap_udc_probe(struct platform_device *pdev)
 			 * know when to turn PULLUP_EN on/off; and that
 			 * means we always "need" the 48MHz clock.
 			 */
-			u32 tmp = FUNC_MUX_CTRL_0_REG;
-
-			FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510;
+			u32 tmp = omap_readl(FUNC_MUX_CTRL_0);
+			tmp &= ~VBUS_CTRL_1510;
+			omap_writel(tmp, FUNC_MUX_CTRL_0);
 			tmp |= VBUS_MODE_1510;
 			tmp &= ~VBUS_CTRL_1510;
-			FUNC_MUX_CTRL_0_REG = tmp;
+			omap_writel(tmp, FUNC_MUX_CTRL_0);
 		}
 	} else {
 		/* The transceiver may package some GPIO logic or handle
@@ -2907,7 +2932,7 @@ known:
 #endif
 
 	/* starting with omap1710 es2.0, clear toggle is a separate bit */
-	if (UDC_REV_REG >= 0x61)
+	if (omap_readw(UDC_REV) >= 0x61)
 		udc->clr_halt = UDC_RESET_EP | UDC_CLRDATA_TOGGLE;
 	else
 		udc->clr_halt = UDC_RESET_EP;
@@ -3005,7 +3030,7 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
 		put_device(udc->transceiver->dev);
 		udc->transceiver = NULL;
 	}
-	UDC_SYSCON1_REG = 0;
+	omap_writew(0, UDC_SYSCON1);
 
 	remove_proc_file();
 
@@ -3036,7 +3061,7 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
  *
  * REVISIT we should probably reject suspend requests when there's a host
  * session active, rather than disconnecting, at least on boards that can
- * report VBUS irqs (UDC_DEVSTAT_REG.UDC_ATT).  And in any case, we need to
+ * report VBUS irqs (UDC_DEVSTAT.UDC_ATT).  And in any case, we need to
  * make host resumes and VBUS detection trigger OMAP wakeup events; that
  * may involve talking to an external transceiver (e.g. isp1301).
  */
@@ -3045,14 +3070,14 @@ static int omap_udc_suspend(struct platform_device *dev, pm_message_t message)
 {
 	u32	devstat;
 
-	devstat = UDC_DEVSTAT_REG;
+	devstat = omap_readw(UDC_DEVSTAT);
 
 	/* we're requesting 48 MHz clock if the pullup is enabled
 	 * (== we're attached to the host) and we're not suspended,
 	 * which would prevent entry to deep sleep...
 	 */
 	if ((devstat & UDC_ATT) != 0 && (devstat & UDC_SUS) == 0) {
-		WARN("session active; suspend requires disconnect\n");
+		WARNING("session active; suspend requires disconnect\n");
 		omap_pullup(&udc->gadget, 0);
 	}
 
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
index c6b9cbc..29edc51 100644
--- a/drivers/usb/gadget/omap_udc.h
+++ b/drivers/usb/gadget/omap_udc.h
@@ -8,23 +8,22 @@
 /*
  * USB device/endpoint management registers
  */
-#define UDC_REG(offset)              __REG16(UDC_BASE + (offset))
 
-#define	UDC_REV_REG			UDC_REG(0x0)	/* Revision */
-#define	UDC_EP_NUM_REG			UDC_REG(0x4)	/* Which endpoint */
+#define	UDC_REV				(UDC_BASE + 0x0)	/* Revision */
+#define	UDC_EP_NUM			(UDC_BASE + 0x4)	/* Which endpoint */
 #	define	UDC_SETUP_SEL		(1 << 6)
 #	define	UDC_EP_SEL		(1 << 5)
 #	define	UDC_EP_DIR		(1 << 4)
 	/* low 4 bits for endpoint number */
-#define	UDC_DATA_REG			UDC_REG(0x08)	/* Endpoint FIFO */
-#define	UDC_CTRL_REG			UDC_REG(0x0C)	/* Endpoint control */
+#define	UDC_DATA			(UDC_BASE + 0x08)	/* Endpoint FIFO */
+#define	UDC_CTRL			(UDC_BASE + 0x0C)	/* Endpoint control */
 #	define	UDC_CLR_HALT		(1 << 7)
 #	define	UDC_SET_HALT		(1 << 6)
 #	define	UDC_CLRDATA_TOGGLE	(1 << 3)
 #	define	UDC_SET_FIFO_EN		(1 << 2)
 #	define	UDC_CLR_EP		(1 << 1)
 #	define	UDC_RESET_EP		(1 << 0)
-#define	UDC_STAT_FLG_REG		UDC_REG(0x10)	/* Endpoint status */
+#define	UDC_STAT_FLG			(UDC_BASE + 0x10)	/* Endpoint status */
 #	define	UDC_NO_RXPACKET		(1 << 15)
 #	define	UDC_MISS_IN		(1 << 14)
 #	define	UDC_DATA_FLUSH		(1 << 13)
@@ -38,8 +37,8 @@
 #	define	UDC_FIFO_EN		(1 << 2)
 #	define	UDC_NON_ISO_FIFO_EMPTY	(1 << 1)
 #	define	UDC_NON_ISO_FIFO_FULL	(1 << 0)
-#define	UDC_RXFSTAT_REG			UDC_REG(0x14)	/* OUT bytecount */
-#define	UDC_SYSCON1_REG			UDC_REG(0x18)	/* System config 1 */
+#define	UDC_RXFSTAT			(UDC_BASE + 0x14)	/* OUT bytecount */
+#define	UDC_SYSCON1			(UDC_BASE + 0x18)	/* System config 1 */
 #	define	UDC_CFG_LOCK		(1 << 8)
 #	define	UDC_DATA_ENDIAN		(1 << 7)
 #	define	UDC_DMA_ENDIAN		(1 << 6)
@@ -48,12 +47,12 @@
 #	define	UDC_SELF_PWR		(1 << 2)
 #	define	UDC_SOFF_DIS		(1 << 1)
 #	define	UDC_PULLUP_EN		(1 << 0)
-#define	UDC_SYSCON2_REG			UDC_REG(0x1C)	/* System config 2 */
+#define	UDC_SYSCON2			(UDC_BASE + 0x1C)	/* System config 2 */
 #	define	UDC_RMT_WKP		(1 << 6)
 #	define	UDC_STALL_CMD		(1 << 5)
 #	define	UDC_DEV_CFG		(1 << 3)
 #	define	UDC_CLR_CFG		(1 << 2)
-#define	UDC_DEVSTAT_REG			UDC_REG(0x20)	/* Device status */
+#define	UDC_DEVSTAT			(UDC_BASE + 0x20)	/* Device status */
 #	define	UDC_B_HNP_ENABLE	(1 << 9)
 #	define	UDC_A_HNP_SUPPORT	(1 << 8)
 #	define	UDC_A_ALT_HNP_SUPPORT	(1 << 7)
@@ -64,26 +63,26 @@
 #	define	UDC_ADD			(1 << 2)
 #	define	UDC_DEF			(1 << 1)
 #	define	UDC_ATT			(1 << 0)
-#define	UDC_SOF_REG			UDC_REG(0x24)	/* Start of frame */
+#define	UDC_SOF				(UDC_BASE + 0x24)	/* Start of frame */
 #	define	UDC_FT_LOCK		(1 << 12)
 #	define	UDC_TS_OK		(1 << 11)
 #	define	UDC_TS			0x03ff
-#define	UDC_IRQ_EN_REG			UDC_REG(0x28)	/* Interrupt enable */
+#define	UDC_IRQ_EN			(UDC_BASE + 0x28)	/* Interrupt enable */
 #	define	UDC_SOF_IE		(1 << 7)
 #	define	UDC_EPN_RX_IE		(1 << 5)
 #	define	UDC_EPN_TX_IE		(1 << 4)
 #	define	UDC_DS_CHG_IE		(1 << 3)
 #	define	UDC_EP0_IE		(1 << 0)
-#define	UDC_DMA_IRQ_EN_REG		UDC_REG(0x2C)	/* DMA irq enable */
+#define	UDC_DMA_IRQ_EN			(UDC_BASE + 0x2C)	/* DMA irq enable */
 	/* rx/tx dma channels numbered 1-3 not 0-2 */
 #	define	UDC_TX_DONE_IE(n)	(1 << (4 * (n) - 2))
 #	define	UDC_RX_CNT_IE(n)	(1 << (4 * (n) - 3))
 #	define	UDC_RX_EOT_IE(n)	(1 << (4 * (n) - 4))
-#define	UDC_IRQ_SRC_REG			UDC_REG(0x30)	/* Interrupt source */
+#define	UDC_IRQ_SRC			(UDC_BASE + 0x30)	/* Interrupt source */
 #	define	UDC_TXN_DONE		(1 << 10)
 #	define	UDC_RXN_CNT		(1 << 9)
 #	define	UDC_RXN_EOT		(1 << 8)
-#	define	UDC_SOF			(1 << 7)
+#	define	UDC_IRQ_SOF		(1 << 7)
 #	define	UDC_EPN_RX		(1 << 5)
 #	define	UDC_EPN_TX		(1 << 4)
 #	define	UDC_DS_CHG		(1 << 3)
@@ -91,41 +90,41 @@
 #	define	UDC_EP0_RX		(1 << 1)
 #	define	UDC_EP0_TX		(1 << 0)
 #	define	UDC_IRQ_SRC_MASK	0x7bf
-#define	UDC_EPN_STAT_REG		UDC_REG(0x34)	/* EP irq status */
-#define	UDC_DMAN_STAT_REG		UDC_REG(0x38)	/* DMA irq status */
+#define	UDC_EPN_STAT			(UDC_BASE + 0x34)	/* EP irq status */
+#define	UDC_DMAN_STAT			(UDC_BASE + 0x38)	/* DMA irq status */
 #	define	UDC_DMA_RX_SB		(1 << 12)
 #	define	UDC_DMA_RX_SRC(x)	(((x)>>8) & 0xf)
 #	define	UDC_DMA_TX_SRC(x)	(((x)>>0) & 0xf)
 
 
 /* DMA configuration registers:  up to three channels in each direction.  */
-#define	UDC_RXDMA_CFG_REG		UDC_REG(0x40)	/* 3 eps for RX DMA */
+#define	UDC_RXDMA_CFG			(UDC_BASE + 0x40)	/* 3 eps for RX DMA */
 #	define	UDC_DMA_REQ		(1 << 12)
-#define	UDC_TXDMA_CFG_REG		UDC_REG(0x44)	/* 3 eps for TX DMA */
-#define	UDC_DATA_DMA_REG		UDC_REG(0x48)	/* rx/tx fifo addr */
+#define	UDC_TXDMA_CFG			(UDC_BASE + 0x44)	/* 3 eps for TX DMA */
+#define	UDC_DATA_DMA			(UDC_BASE + 0x48)	/* rx/tx fifo addr */
 
 /* rx/tx dma control, numbering channels 1-3 not 0-2 */
-#define	UDC_TXDMA_REG(chan)		UDC_REG(0x50 - 4 + 4 * (chan))
+#define	UDC_TXDMA(chan)			(UDC_BASE + 0x50 - 4 + 4 * (chan))
 #	define UDC_TXN_EOT		(1 << 15)	/* bytes vs packets */
 #	define UDC_TXN_START		(1 << 14)	/* start transfer */
 #	define UDC_TXN_TSC		0x03ff		/* units in xfer */
-#define	UDC_RXDMA_REG(chan)		UDC_REG(0x60 - 4 + 4 * (chan))
+#define	UDC_RXDMA(chan)			(UDC_BASE + 0x60 - 4 + 4 * (chan))
 #	define UDC_RXN_STOP		(1 << 15)	/* enable EOT irq */
 #	define UDC_RXN_TC		0x00ff		/* packets in xfer */
 
 
 /*
  * Endpoint configuration registers (used before CFG_LOCK is set)
- * UDC_EP_TX_REG(0) is unused
+ * UDC_EP_TX(0) is unused
  */
-#define	UDC_EP_RX_REG(endpoint)		UDC_REG(0x80 + (endpoint)*4)
+#define	UDC_EP_RX(endpoint)		(UDC_BASE + 0x80 + (endpoint)*4)
 #	define	UDC_EPN_RX_VALID	(1 << 15)
 #	define	UDC_EPN_RX_DB		(1 << 14)
 	/* buffer size in bits 13, 12 */
 #	define	UDC_EPN_RX_ISO		(1 << 11)
 	/* buffer pointer in low 11 bits */
-#define	UDC_EP_TX_REG(endpoint)		UDC_REG(0xc0 + (endpoint)*4)
-	/* same bitfields as in RX_REG */
+#define	UDC_EP_TX(endpoint)		(UDC_BASE + 0xc0 + (endpoint)*4)
+	/* same bitfields as in RX */
 
 /*-------------------------------------------------------------------------*/
 
@@ -189,20 +188,20 @@ struct omap_udc {
 #endif
 
 #define ERR(stuff...)		pr_err("udc: " stuff)
-#define WARN(stuff...)		pr_warning("udc: " stuff)
+#define WARNING(stuff...)	pr_warning("udc: " stuff)
 #define INFO(stuff...)		pr_info("udc: " stuff)
 #define DBG(stuff...)		pr_debug("udc: " stuff)
 
 /*-------------------------------------------------------------------------*/
 
-#define	MOD_CONF_CTRL_0_REG	__REG32(MOD_CONF_CTRL_0)
-#define	VBUS_W2FC_1510		(1 << 17)	/* 0 gpio0, 1 dvdd2 pin */
+/* MOD_CONF_CTRL_0 */
+#define VBUS_W2FC_1510		(1 << 17)	/* 0 gpio0, 1 dvdd2 pin */
 
-#define	FUNC_MUX_CTRL_0_REG	__REG32(FUNC_MUX_CTRL_0)
+/* FUNC_MUX_CTRL_0 */
 #define	VBUS_CTRL_1510		(1 << 19)	/* 1 connected (software) */
 #define	VBUS_MODE_1510		(1 << 18)	/* 0 hardware, 1 software */
 
-#define	HMC_1510	((MOD_CONF_CTRL_0_REG >> 1) & 0x3f)
-#define	HMC_1610	(OTG_SYSCON_2_REG & 0x3f)
+#define	HMC_1510	((omap_readl(MOD_CONF_CTRL_0) >> 1) & 0x3f)
+#define	HMC_1610	(omap_readl(OTG_SYSCON_2) & 0x3f)
 #define	HMC		(cpu_is_omap15xx() ? HMC_1510 : HMC_1610)
 
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 76be75e..e009008 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -179,7 +179,7 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR);
 
 #define ERROR(dev, fmt, args...) \
 	xprintk(dev, KERN_ERR, fmt, ## args)
-#define WARN(dev, fmt, args...) \
+#define WARNING(dev, fmt, args...) \
 	xprintk(dev, KERN_WARNING, fmt, ## args)
 #define INFO(dev, fmt, args...) \
 	xprintk(dev, KERN_INFO, fmt, ## args)
@@ -462,6 +462,7 @@ printer_open(struct inode *inode, struct file *fd)
 	unsigned long		flags;
 	int			ret = -EBUSY;
 
+	lock_kernel();
 	dev = container_of(inode->i_cdev, struct printer_dev, printer_cdev);
 
 	spin_lock_irqsave(&dev->lock, flags);
@@ -477,7 +478,7 @@ printer_open(struct inode *inode, struct file *fd)
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 	DBG(dev, "printer_open returned %x\n", ret);
-
+	unlock_kernel();
 	return ret;
 }
 
@@ -827,9 +828,8 @@ printer_poll(struct file *fd, poll_table *wait)
 	return status;
 }
 
-static int
-printer_ioctl(struct inode *inode, struct file *fd, unsigned int code,
-		unsigned long arg)
+static long
+printer_ioctl(struct file *fd, unsigned int code, unsigned long arg)
 {
 	struct printer_dev	*dev = fd->private_data;
 	unsigned long		flags;
@@ -868,7 +868,7 @@ static struct file_operations printer_io_operations = {
 	.write =	printer_write,
 	.fsync =	printer_fsync,
 	.poll =		printer_poll,
-	.ioctl =	printer_ioctl,
+	.unlocked_ioctl = printer_ioctl,
 	.release =	printer_close
 };
 
@@ -1360,8 +1360,8 @@ printer_bind(struct usb_gadget *gadget)
 
 
 	/* Setup the sysfs files for the printer gadget. */
-	dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
-			"g_printer");
+	dev->pdev = device_create_drvdata(usb_gadget_class, NULL,
+					  g_printer_devno, NULL, "g_printer");
 	if (IS_ERR(dev->pdev)) {
 		ERROR(dev, "Failed to create device: g_printer\n");
 		goto fail;
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
new file mode 100644
index 0000000..da6e93c
--- /dev/null
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -0,0 +1,2390 @@
+/*
+ * Intel PXA25x and IXP4xx on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker)
+ * Copyright (C) 2003 Robert Schwebel, Pengutronix
+ * Copyright (C) 2003 Benedikt Spranger, Pengutronix
+ * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2003 Joshua Wise
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/io.h>
+
+#include <asm/byteorder.h>
+#include <asm/dma.h>
+#include <asm/gpio.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <asm/unaligned.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+/*
+ * This driver is PXA25x only.  Grab the right register definitions.
+ */
+#ifdef CONFIG_ARCH_PXA
+#include <mach/pxa25x-udc.h>
+#endif
+
+#include <asm/mach/udc_pxa2xx.h>
+
+
+/*
+ * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x
+ * series processors.  The UDC for the IXP 4xx series is very similar.
+ * There are fifteen endpoints, in addition to ep0.
+ *
+ * Such controller drivers work with a gadget driver.  The gadget driver
+ * returns descriptors, implements configuration and data protocols used
+ * by the host to interact with this device, and allocates endpoints to
+ * the different protocol interfaces.  The controller driver virtualizes
+ * usb hardware so that the gadget drivers will be more portable.
+ *
+ * This UDC hardware wants to implement a bit too much USB protocol, so
+ * it constrains the sorts of USB configuration change events that work.
+ * The errata for these chips are misleading; some "fixed" bugs from
+ * pxa250 a0/a1 b0/b1/b2 sure act like they're still there.
+ *
+ * Note that the UDC hardware supports DMA (except on IXP) but that's
+ * not used here.  IN-DMA (to host) is simple enough, when the data is
+ * suitably aligned (16 bytes) ... the network stack doesn't do that,
+ * other software can.  OUT-DMA is buggy in most chip versions, as well
+ * as poorly designed (data toggle not automatic).  So this driver won't
+ * bother using DMA.  (Mostly-working IN-DMA support was available in
+ * kernels before 2.6.23, but was never enabled or well tested.)
+ */
+
+#define	DRIVER_VERSION	"30-June-2007"
+#define	DRIVER_DESC	"PXA 25x USB Device Controller driver"
+
+
+static const char driver_name [] = "pxa25x_udc";
+
+static const char ep0name [] = "ep0";
+
+
+#ifdef CONFIG_ARCH_IXP4XX
+
+/* cpu-specific register addresses are compiled in to this code */
+#ifdef CONFIG_ARCH_PXA
+#error "Can't configure both IXP and PXA"
+#endif
+
+/* IXP doesn't yet support <linux/clk.h> */
+#define clk_get(dev,name)	NULL
+#define clk_enable(clk)		do { } while (0)
+#define clk_disable(clk)	do { } while (0)
+#define clk_put(clk)		do { } while (0)
+
+#endif
+
+#include "pxa25x_udc.h"
+
+
+#ifdef	CONFIG_USB_PXA25X_SMALL
+#define SIZE_STR	" (small)"
+#else
+#define SIZE_STR	""
+#endif
+
+/* ---------------------------------------------------------------------------
+ *	endpoint related parts of the api to the usb controller hardware,
+ *	used by gadget driver; and the inner talker-to-hardware core.
+ * ---------------------------------------------------------------------------
+ */
+
+static void pxa25x_ep_fifo_flush (struct usb_ep *ep);
+static void nuke (struct pxa25x_ep *, int status);
+
+/* one GPIO should be used to detect VBUS from the host */
+static int is_vbus_present(void)
+{
+	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
+
+	if (mach->gpio_vbus) {
+		int value = gpio_get_value(mach->gpio_vbus);
+		return mach->gpio_vbus_inverted ? !value : value;
+	}
+	if (mach->udc_is_connected)
+		return mach->udc_is_connected();
+	return 1;
+}
+
+/* one GPIO should control a D+ pullup, so host sees this device (or not) */
+static void pullup_off(void)
+{
+	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
+	int off_level = mach->gpio_pullup_inverted;
+
+	if (mach->gpio_pullup)
+		gpio_set_value(mach->gpio_pullup, off_level);
+	else if (mach->udc_command)
+		mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+}
+
+static void pullup_on(void)
+{
+	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
+	int on_level = !mach->gpio_pullup_inverted;
+
+	if (mach->gpio_pullup)
+		gpio_set_value(mach->gpio_pullup, on_level);
+	else if (mach->udc_command)
+		mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+}
+
+static void pio_irq_enable(int bEndpointAddress)
+{
+        bEndpointAddress &= 0xf;
+        if (bEndpointAddress < 8)
+                UICR0 &= ~(1 << bEndpointAddress);
+        else {
+                bEndpointAddress -= 8;
+                UICR1 &= ~(1 << bEndpointAddress);
+	}
+}
+
+static void pio_irq_disable(int bEndpointAddress)
+{
+        bEndpointAddress &= 0xf;
+        if (bEndpointAddress < 8)
+                UICR0 |= 1 << bEndpointAddress;
+        else {
+                bEndpointAddress -= 8;
+                UICR1 |= 1 << bEndpointAddress;
+        }
+}
+
+/* The UDCCR reg contains mask and interrupt status bits,
+ * so using '|=' isn't safe as it may ack an interrupt.
+ */
+#define UDCCR_MASK_BITS         (UDCCR_REM | UDCCR_SRM | UDCCR_UDE)
+
+static inline void udc_set_mask_UDCCR(int mask)
+{
+	UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS);
+}
+
+static inline void udc_clear_mask_UDCCR(int mask)
+{
+	UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS);
+}
+
+static inline void udc_ack_int_UDCCR(int mask)
+{
+	/* udccr contains the bits we dont want to change */
+	__u32 udccr = UDCCR & UDCCR_MASK_BITS;
+
+	UDCCR = udccr | (mask & ~UDCCR_MASK_BITS);
+}
+
+/*
+ * endpoint enable/disable
+ *
+ * we need to verify the descriptors used to enable endpoints.  since pxa25x
+ * endpoint configurations are fixed, and are pretty much always enabled,
+ * there's not a lot to manage here.
+ *
+ * because pxa25x can't selectively initialize bulk (or interrupt) endpoints,
+ * (resetting endpoint halt and toggle), SET_INTERFACE is unusable except
+ * for a single interface (with only the default altsetting) and for gadget
+ * drivers that don't halt endpoints (not reset by set_interface).  that also
+ * means that if you use ISO, you must violate the USB spec rule that all
+ * iso endpoints must be in non-default altsettings.
+ */
+static int pxa25x_ep_enable (struct usb_ep *_ep,
+		const struct usb_endpoint_descriptor *desc)
+{
+	struct pxa25x_ep        *ep;
+	struct pxa25x_udc       *dev;
+
+	ep = container_of (_ep, struct pxa25x_ep, ep);
+	if (!_ep || !desc || ep->desc || _ep->name == ep0name
+			|| desc->bDescriptorType != USB_DT_ENDPOINT
+			|| ep->bEndpointAddress != desc->bEndpointAddress
+			|| ep->fifo_size < le16_to_cpu
+						(desc->wMaxPacketSize)) {
+		DMSG("%s, bad ep or descriptor\n", __func__);
+		return -EINVAL;
+	}
+
+	/* xfer types must match, except that interrupt ~= bulk */
+	if (ep->bmAttributes != desc->bmAttributes
+			&& ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+			&& desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+		DMSG("%s, %s type mismatch\n", __func__, _ep->name);
+		return -EINVAL;
+	}
+
+	/* hardware _could_ do smaller, but driver doesn't */
+	if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+				&& le16_to_cpu (desc->wMaxPacketSize)
+						!= BULK_FIFO_SIZE)
+			|| !desc->wMaxPacketSize) {
+		DMSG("%s, bad %s maxpacket\n", __func__, _ep->name);
+		return -ERANGE;
+	}
+
+	dev = ep->dev;
+	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+		DMSG("%s, bogus device state\n", __func__);
+		return -ESHUTDOWN;
+	}
+
+	ep->desc = desc;
+	ep->stopped = 0;
+	ep->pio_irqs = 0;
+	ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize);
+
+	/* flush fifo (mostly for OUT buffers) */
+	pxa25x_ep_fifo_flush (_ep);
+
+	/* ... reset halt state too, if we could ... */
+
+	DBG(DBG_VERBOSE, "enabled %s\n", _ep->name);
+	return 0;
+}
+
+static int pxa25x_ep_disable (struct usb_ep *_ep)
+{
+	struct pxa25x_ep	*ep;
+	unsigned long		flags;
+
+	ep = container_of (_ep, struct pxa25x_ep, ep);
+	if (!_ep || !ep->desc) {
+		DMSG("%s, %s not enabled\n", __func__,
+			_ep ? ep->ep.name : NULL);
+		return -EINVAL;
+	}
+	local_irq_save(flags);
+
+	nuke (ep, -ESHUTDOWN);
+
+	/* flush fifo (mostly for IN buffers) */
+	pxa25x_ep_fifo_flush (_ep);
+
+	ep->desc = NULL;
+	ep->stopped = 1;
+
+	local_irq_restore(flags);
+	DBG(DBG_VERBOSE, "%s disabled\n", _ep->name);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* for the pxa25x, these can just wrap kmalloc/kfree.  gadget drivers
+ * must still pass correctly initialized endpoints, since other controller
+ * drivers may care about how it's currently set up (dma issues etc).
+ */
+
+/*
+ *	pxa25x_ep_alloc_request - allocate a request data structure
+ */
+static struct usb_request *
+pxa25x_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
+{
+	struct pxa25x_request *req;
+
+	req = kzalloc(sizeof(*req), gfp_flags);
+	if (!req)
+		return NULL;
+
+	INIT_LIST_HEAD (&req->queue);
+	return &req->req;
+}
+
+
+/*
+ *	pxa25x_ep_free_request - deallocate a request data structure
+ */
+static void
+pxa25x_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct pxa25x_request	*req;
+
+	req = container_of (_req, struct pxa25x_request, req);
+	WARN_ON(!list_empty (&req->queue));
+	kfree(req);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ *	done - retire a request; caller blocked irqs
+ */
+static void done(struct pxa25x_ep *ep, struct pxa25x_request *req, int status)
+{
+	unsigned		stopped = ep->stopped;
+
+	list_del_init(&req->queue);
+
+	if (likely (req->req.status == -EINPROGRESS))
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	if (status && status != -ESHUTDOWN)
+		DBG(DBG_VERBOSE, "complete %s req %p stat %d len %u/%u\n",
+			ep->ep.name, &req->req, status,
+			req->req.actual, req->req.length);
+
+	/* don't modify queue heads during completion callback */
+	ep->stopped = 1;
+	req->req.complete(&ep->ep, &req->req);
+	ep->stopped = stopped;
+}
+
+
+static inline void ep0_idle (struct pxa25x_udc *dev)
+{
+	dev->ep0state = EP0_IDLE;
+}
+
+static int
+write_packet(volatile u32 *uddr, struct pxa25x_request *req, unsigned max)
+{
+	u8		*buf;
+	unsigned	length, count;
+
+	buf = req->req.buf + req->req.actual;
+	prefetch(buf);
+
+	/* how big will this packet be? */
+	length = min(req->req.length - req->req.actual, max);
+	req->req.actual += length;
+
+	count = length;
+	while (likely(count--))
+		*uddr = *buf++;
+
+	return length;
+}
+
+/*
+ * write to an IN endpoint fifo, as many packets as possible.
+ * irqs will use this to write the rest later.
+ * caller guarantees at least one packet buffer is ready (or a zlp).
+ */
+static int
+write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
+{
+	unsigned		max;
+
+	max = le16_to_cpu(ep->desc->wMaxPacketSize);
+	do {
+		unsigned	count;
+		int		is_last, is_short;
+
+		count = write_packet(ep->reg_uddr, req, max);
+
+		/* last packet is usually short (or a zlp) */
+		if (unlikely (count != max))
+			is_last = is_short = 1;
+		else {
+			if (likely(req->req.length != req->req.actual)
+					|| req->req.zero)
+				is_last = 0;
+			else
+				is_last = 1;
+			/* interrupt/iso maxpacket may not fill the fifo */
+			is_short = unlikely (max < ep->fifo_size);
+		}
+
+		DBG(DBG_VERY_NOISY, "wrote %s %d bytes%s%s %d left %p\n",
+			ep->ep.name, count,
+			is_last ? "/L" : "", is_short ? "/S" : "",
+			req->req.length - req->req.actual, req);
+
+		/* let loose that packet. maybe try writing another one,
+		 * double buffering might work.  TSP, TPC, and TFS
+		 * bit values are the same for all normal IN endpoints.
+		 */
+		*ep->reg_udccs = UDCCS_BI_TPC;
+		if (is_short)
+			*ep->reg_udccs = UDCCS_BI_TSP;
+
+		/* requests complete when all IN data is in the FIFO */
+		if (is_last) {
+			done (ep, req, 0);
+			if (list_empty(&ep->queue))
+				pio_irq_disable (ep->bEndpointAddress);
+			return 1;
+		}
+
+		// TODO experiment: how robust can fifo mode tweaking be?
+		// double buffering is off in the default fifo mode, which
+		// prevents TFS from being set here.
+
+	} while (*ep->reg_udccs & UDCCS_BI_TFS);
+	return 0;
+}
+
+/* caller asserts req->pending (ep0 irq status nyet cleared); starts
+ * ep0 data stage.  these chips want very simple state transitions.
+ */
+static inline
+void ep0start(struct pxa25x_udc *dev, u32 flags, const char *tag)
+{
+	UDCCS0 = flags|UDCCS0_SA|UDCCS0_OPR;
+	USIR0 = USIR0_IR0;
+	dev->req_pending = 0;
+	DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n",
+		__func__, tag, UDCCS0, flags);
+}
+
+static int
+write_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
+{
+	unsigned	count;
+	int		is_short;
+
+	count = write_packet(&UDDR0, req, EP0_FIFO_SIZE);
+	ep->dev->stats.write.bytes += count;
+
+	/* last packet "must be" short (or a zlp) */
+	is_short = (count != EP0_FIFO_SIZE);
+
+	DBG(DBG_VERY_NOISY, "ep0in %d bytes %d left %p\n", count,
+		req->req.length - req->req.actual, req);
+
+	if (unlikely (is_short)) {
+		if (ep->dev->req_pending)
+			ep0start(ep->dev, UDCCS0_IPR, "short IN");
+		else
+			UDCCS0 = UDCCS0_IPR;
+
+		count = req->req.length;
+		done (ep, req, 0);
+		ep0_idle(ep->dev);
+#ifndef CONFIG_ARCH_IXP4XX
+#if 1
+		/* This seems to get rid of lost status irqs in some cases:
+		 * host responds quickly, or next request involves config
+		 * change automagic, or should have been hidden, or ...
+		 *
+		 * FIXME get rid of all udelays possible...
+		 */
+		if (count >= EP0_FIFO_SIZE) {
+			count = 100;
+			do {
+				if ((UDCCS0 & UDCCS0_OPR) != 0) {
+					/* clear OPR, generate ack */
+					UDCCS0 = UDCCS0_OPR;
+					break;
+				}
+				count--;
+				udelay(1);
+			} while (count);
+		}
+#endif
+#endif
+	} else if (ep->dev->req_pending)
+		ep0start(ep->dev, 0, "IN");
+	return is_short;
+}
+
+
+/*
+ * read_fifo -  unload packet(s) from the fifo we use for usb OUT
+ * transfers and put them into the request.  caller should have made
+ * sure there's at least one packet ready.
+ *
+ * returns true if the request completed because of short packet or the
+ * request buffer having filled (and maybe overran till end-of-packet).
+ */
+static int
+read_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
+{
+	for (;;) {
+		u32		udccs;
+		u8		*buf;
+		unsigned	bufferspace, count, is_short;
+
+		/* make sure there's a packet in the FIFO.
+		 * UDCCS_{BO,IO}_RPC are all the same bit value.
+		 * UDCCS_{BO,IO}_RNE are all the same bit value.
+		 */
+		udccs = *ep->reg_udccs;
+		if (unlikely ((udccs & UDCCS_BO_RPC) == 0))
+			break;
+		buf = req->req.buf + req->req.actual;
+		prefetchw(buf);
+		bufferspace = req->req.length - req->req.actual;
+
+		/* read all bytes from this packet */
+		if (likely (udccs & UDCCS_BO_RNE)) {
+			count = 1 + (0x0ff & *ep->reg_ubcr);
+			req->req.actual += min (count, bufferspace);
+		} else /* zlp */
+			count = 0;
+		is_short = (count < ep->ep.maxpacket);
+		DBG(DBG_VERY_NOISY, "read %s %02x, %d bytes%s req %p %d/%d\n",
+			ep->ep.name, udccs, count,
+			is_short ? "/S" : "",
+			req, req->req.actual, req->req.length);
+		while (likely (count-- != 0)) {
+			u8	byte = (u8) *ep->reg_uddr;
+
+			if (unlikely (bufferspace == 0)) {
+				/* this happens when the driver's buffer
+				 * is smaller than what the host sent.
+				 * discard the extra data.
+				 */
+				if (req->req.status != -EOVERFLOW)
+					DMSG("%s overflow %d\n",
+						ep->ep.name, count);
+				req->req.status = -EOVERFLOW;
+			} else {
+				*buf++ = byte;
+				bufferspace--;
+			}
+		}
+		*ep->reg_udccs =  UDCCS_BO_RPC;
+		/* RPC/RSP/RNE could now reflect the other packet buffer */
+
+		/* iso is one request per packet */
+		if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+			if (udccs & UDCCS_IO_ROF)
+				req->req.status = -EHOSTUNREACH;
+			/* more like "is_done" */
+			is_short = 1;
+		}
+
+		/* completion */
+		if (is_short || req->req.actual == req->req.length) {
+			done (ep, req, 0);
+			if (list_empty(&ep->queue))
+				pio_irq_disable (ep->bEndpointAddress);
+			return 1;
+		}
+
+		/* finished that packet.  the next one may be waiting... */
+	}
+	return 0;
+}
+
+/*
+ * special ep0 version of the above.  no UBCR0 or double buffering; status
+ * handshaking is magic.  most device protocols don't need control-OUT.
+ * CDC vendor commands (and RNDIS), mass storage CB/CBI, and some other
+ * protocols do use them.
+ */
+static int
+read_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
+{
+	u8		*buf, byte;
+	unsigned	bufferspace;
+
+	buf = req->req.buf + req->req.actual;
+	bufferspace = req->req.length - req->req.actual;
+
+	while (UDCCS0 & UDCCS0_RNE) {
+		byte = (u8) UDDR0;
+
+		if (unlikely (bufferspace == 0)) {
+			/* this happens when the driver's buffer
+			 * is smaller than what the host sent.
+			 * discard the extra data.
+			 */
+			if (req->req.status != -EOVERFLOW)
+				DMSG("%s overflow\n", ep->ep.name);
+			req->req.status = -EOVERFLOW;
+		} else {
+			*buf++ = byte;
+			req->req.actual++;
+			bufferspace--;
+		}
+	}
+
+	UDCCS0 = UDCCS0_OPR | UDCCS0_IPR;
+
+	/* completion */
+	if (req->req.actual >= req->req.length)
+		return 1;
+
+	/* finished that packet.  the next one may be waiting... */
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+	struct pxa25x_request	*req;
+	struct pxa25x_ep	*ep;
+	struct pxa25x_udc	*dev;
+	unsigned long		flags;
+
+	req = container_of(_req, struct pxa25x_request, req);
+	if (unlikely (!_req || !_req->complete || !_req->buf
+			|| !list_empty(&req->queue))) {
+		DMSG("%s, bad params\n", __func__);
+		return -EINVAL;
+	}
+
+	ep = container_of(_ep, struct pxa25x_ep, ep);
+	if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+		DMSG("%s, bad ep\n", __func__);
+		return -EINVAL;
+	}
+
+	dev = ep->dev;
+	if (unlikely (!dev->driver
+			|| dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+		DMSG("%s, bogus device state\n", __func__);
+		return -ESHUTDOWN;
+	}
+
+	/* iso is always one packet per request, that's the only way
+	 * we can report per-packet status.  that also helps with dma.
+	 */
+	if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
+			&& req->req.length > le16_to_cpu
+						(ep->desc->wMaxPacketSize)))
+		return -EMSGSIZE;
+
+	DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n",
+		_ep->name, _req, _req->length, _req->buf);
+
+	local_irq_save(flags);
+
+	_req->status = -EINPROGRESS;
+	_req->actual = 0;
+
+	/* kickstart this i/o queue? */
+	if (list_empty(&ep->queue) && !ep->stopped) {
+		if (ep->desc == NULL/* ep0 */) {
+			unsigned	length = _req->length;
+
+			switch (dev->ep0state) {
+			case EP0_IN_DATA_PHASE:
+				dev->stats.write.ops++;
+				if (write_ep0_fifo(ep, req))
+					req = NULL;
+				break;
+
+			case EP0_OUT_DATA_PHASE:
+				dev->stats.read.ops++;
+				/* messy ... */
+				if (dev->req_config) {
+					DBG(DBG_VERBOSE, "ep0 config ack%s\n",
+						dev->has_cfr ?  "" : " raced");
+					if (dev->has_cfr)
+						UDCCFR = UDCCFR_AREN|UDCCFR_ACM
+							|UDCCFR_MB1;
+					done(ep, req, 0);
+					dev->ep0state = EP0_END_XFER;
+					local_irq_restore (flags);
+					return 0;
+				}
+				if (dev->req_pending)
+					ep0start(dev, UDCCS0_IPR, "OUT");
+				if (length == 0 || ((UDCCS0 & UDCCS0_RNE) != 0
+						&& read_ep0_fifo(ep, req))) {
+					ep0_idle(dev);
+					done(ep, req, 0);
+					req = NULL;
+				}
+				break;
+
+			default:
+				DMSG("ep0 i/o, odd state %d\n", dev->ep0state);
+				local_irq_restore (flags);
+				return -EL2HLT;
+			}
+		/* can the FIFO can satisfy the request immediately? */
+		} else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
+			if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0
+					&& write_fifo(ep, req))
+				req = NULL;
+		} else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0
+				&& read_fifo(ep, req)) {
+			req = NULL;
+		}
+
+		if (likely (req && ep->desc))
+			pio_irq_enable(ep->bEndpointAddress);
+	}
+
+	/* pio or dma irq handler advances the queue. */
+	if (likely(req != NULL))
+		list_add_tail(&req->queue, &ep->queue);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+
+/*
+ *	nuke - dequeue ALL requests
+ */
+static void nuke(struct pxa25x_ep *ep, int status)
+{
+	struct pxa25x_request *req;
+
+	/* called with irqs blocked */
+	while (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next,
+				struct pxa25x_request,
+				queue);
+		done(ep, req, status);
+	}
+	if (ep->desc)
+		pio_irq_disable (ep->bEndpointAddress);
+}
+
+
+/* dequeue JUST ONE request */
+static int pxa25x_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct pxa25x_ep	*ep;
+	struct pxa25x_request	*req;
+	unsigned long		flags;
+
+	ep = container_of(_ep, struct pxa25x_ep, ep);
+	if (!_ep || ep->ep.name == ep0name)
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	/* make sure it's actually queued on this endpoint */
+	list_for_each_entry (req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+	if (&req->req != _req) {
+		local_irq_restore(flags);
+		return -EINVAL;
+	}
+
+	done(ep, req, -ECONNRESET);
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value)
+{
+	struct pxa25x_ep	*ep;
+	unsigned long		flags;
+
+	ep = container_of(_ep, struct pxa25x_ep, ep);
+	if (unlikely (!_ep
+			|| (!ep->desc && ep->ep.name != ep0name))
+			|| ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+		DMSG("%s, bad ep\n", __func__);
+		return -EINVAL;
+	}
+	if (value == 0) {
+		/* this path (reset toggle+halt) is needed to implement
+		 * SET_INTERFACE on normal hardware.  but it can't be
+		 * done from software on the PXA UDC, and the hardware
+		 * forgets to do it as part of SET_INTERFACE automagic.
+		 */
+		DMSG("only host can clear %s halt\n", _ep->name);
+		return -EROFS;
+	}
+
+	local_irq_save(flags);
+
+	if ((ep->bEndpointAddress & USB_DIR_IN) != 0
+			&& ((*ep->reg_udccs & UDCCS_BI_TFS) == 0
+			   || !list_empty(&ep->queue))) {
+		local_irq_restore(flags);
+		return -EAGAIN;
+	}
+
+	/* FST bit is the same for control, bulk in, bulk out, interrupt in */
+	*ep->reg_udccs = UDCCS_BI_FST|UDCCS_BI_FTF;
+
+	/* ep0 needs special care */
+	if (!ep->desc) {
+		start_watchdog(ep->dev);
+		ep->dev->req_pending = 0;
+		ep->dev->ep0state = EP0_STALL;
+
+	/* and bulk/intr endpoints like dropping stalls too */
+	} else {
+		unsigned i;
+		for (i = 0; i < 1000; i += 20) {
+			if (*ep->reg_udccs & UDCCS_BI_SST)
+				break;
+			udelay(20);
+		}
+	}
+	local_irq_restore(flags);
+
+	DBG(DBG_VERBOSE, "%s halt\n", _ep->name);
+	return 0;
+}
+
+static int pxa25x_ep_fifo_status(struct usb_ep *_ep)
+{
+	struct pxa25x_ep        *ep;
+
+	ep = container_of(_ep, struct pxa25x_ep, ep);
+	if (!_ep) {
+		DMSG("%s, bad ep\n", __func__);
+		return -ENODEV;
+	}
+	/* pxa can't report unclaimed bytes from IN fifos */
+	if ((ep->bEndpointAddress & USB_DIR_IN) != 0)
+		return -EOPNOTSUPP;
+	if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN
+			|| (*ep->reg_udccs & UDCCS_BO_RFS) == 0)
+		return 0;
+	else
+		return (*ep->reg_ubcr & 0xfff) + 1;
+}
+
+static void pxa25x_ep_fifo_flush(struct usb_ep *_ep)
+{
+	struct pxa25x_ep        *ep;
+
+	ep = container_of(_ep, struct pxa25x_ep, ep);
+	if (!_ep || ep->ep.name == ep0name || !list_empty(&ep->queue)) {
+		DMSG("%s, bad ep\n", __func__);
+		return;
+	}
+
+	/* toggle and halt bits stay unchanged */
+
+	/* for OUT, just read and discard the FIFO contents. */
+	if ((ep->bEndpointAddress & USB_DIR_IN) == 0) {
+		while (((*ep->reg_udccs) & UDCCS_BO_RNE) != 0)
+			(void) *ep->reg_uddr;
+		return;
+	}
+
+	/* most IN status is the same, but ISO can't stall */
+	*ep->reg_udccs = UDCCS_BI_TPC|UDCCS_BI_FTF|UDCCS_BI_TUR
+		| (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
+			? 0 : UDCCS_BI_SST;
+}
+
+
+static struct usb_ep_ops pxa25x_ep_ops = {
+	.enable		= pxa25x_ep_enable,
+	.disable	= pxa25x_ep_disable,
+
+	.alloc_request	= pxa25x_ep_alloc_request,
+	.free_request	= pxa25x_ep_free_request,
+
+	.queue		= pxa25x_ep_queue,
+	.dequeue	= pxa25x_ep_dequeue,
+
+	.set_halt	= pxa25x_ep_set_halt,
+	.fifo_status	= pxa25x_ep_fifo_status,
+	.fifo_flush	= pxa25x_ep_fifo_flush,
+};
+
+
+/* ---------------------------------------------------------------------------
+ *	device-scoped parts of the api to the usb controller hardware
+ * ---------------------------------------------------------------------------
+ */
+
+static int pxa25x_udc_get_frame(struct usb_gadget *_gadget)
+{
+	return ((UFNRH & 0x07) << 8) | (UFNRL & 0xff);
+}
+
+static int pxa25x_udc_wakeup(struct usb_gadget *_gadget)
+{
+	/* host may not have enabled remote wakeup */
+	if ((UDCCS0 & UDCCS0_DRWF) == 0)
+		return -EHOSTUNREACH;
+	udc_set_mask_UDCCR(UDCCR_RSM);
+	return 0;
+}
+
+static void stop_activity(struct pxa25x_udc *, struct usb_gadget_driver *);
+static void udc_enable (struct pxa25x_udc *);
+static void udc_disable(struct pxa25x_udc *);
+
+/* We disable the UDC -- and its 48 MHz clock -- whenever it's not
+ * in active use.
+ */
+static int pullup(struct pxa25x_udc *udc)
+{
+	int is_active = udc->vbus && udc->pullup && !udc->suspended;
+	DMSG("%s\n", is_active ? "active" : "inactive");
+	if (is_active) {
+		if (!udc->active) {
+			udc->active = 1;
+			/* Enable clock for USB device */
+			clk_enable(udc->clk);
+			udc_enable(udc);
+		}
+	} else {
+		if (udc->active) {
+			if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+				DMSG("disconnect %s\n", udc->driver
+					? udc->driver->driver.name
+					: "(no driver)");
+				stop_activity(udc, udc->driver);
+			}
+			udc_disable(udc);
+			/* Disable clock for USB device */
+			clk_disable(udc->clk);
+			udc->active = 0;
+		}
+
+	}
+	return 0;
+}
+
+/* VBUS reporting logically comes from a transceiver */
+static int pxa25x_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
+{
+	struct pxa25x_udc	*udc;
+
+	udc = container_of(_gadget, struct pxa25x_udc, gadget);
+	udc->vbus = (is_active != 0);
+	DMSG("vbus %s\n", is_active ? "supplied" : "inactive");
+	pullup(udc);
+	return 0;
+}
+
+/* drivers may have software control over D+ pullup */
+static int pxa25x_udc_pullup(struct usb_gadget *_gadget, int is_active)
+{
+	struct pxa25x_udc	*udc;
+
+	udc = container_of(_gadget, struct pxa25x_udc, gadget);
+
+	/* not all boards support pullup control */
+	if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
+		return -EOPNOTSUPP;
+
+	udc->pullup = (is_active != 0);
+	pullup(udc);
+	return 0;
+}
+
+static const struct usb_gadget_ops pxa25x_udc_ops = {
+	.get_frame	= pxa25x_udc_get_frame,
+	.wakeup		= pxa25x_udc_wakeup,
+	.vbus_session	= pxa25x_udc_vbus_session,
+	.pullup		= pxa25x_udc_pullup,
+
+	// .vbus_draw ... boards may consume current from VBUS, up to
+	// 100-500mA based on config.  the 500uA suspend ceiling means
+	// that exclusively vbus-powered PXA designs violate USB specs.
+};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+
+static int
+udc_seq_show(struct seq_file *m, void *_d)
+{
+	struct pxa25x_udc	*dev = m->private;
+	unsigned long		flags;
+	int			i;
+	u32			tmp;
+
+	local_irq_save(flags);
+
+	/* basic device status */
+	seq_printf(m, DRIVER_DESC "\n"
+		"%s version: %s\nGadget driver: %s\nHost %s\n\n",
+		driver_name, DRIVER_VERSION SIZE_STR "(pio)",
+		dev->driver ? dev->driver->driver.name : "(none)",
+		is_vbus_present() ? "full speed" : "disconnected");
+
+	/* registers for device and ep0 */
+	seq_printf(m,
+		"uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
+		UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
+
+	tmp = UDCCR;
+	seq_printf(m,
+		"udccr %02X =%s%s%s%s%s%s%s%s\n", tmp,
+		(tmp & UDCCR_REM) ? " rem" : "",
+		(tmp & UDCCR_RSTIR) ? " rstir" : "",
+		(tmp & UDCCR_SRM) ? " srm" : "",
+		(tmp & UDCCR_SUSIR) ? " susir" : "",
+		(tmp & UDCCR_RESIR) ? " resir" : "",
+		(tmp & UDCCR_RSM) ? " rsm" : "",
+		(tmp & UDCCR_UDA) ? " uda" : "",
+		(tmp & UDCCR_UDE) ? " ude" : "");
+
+	tmp = UDCCS0;
+	seq_printf(m,
+		"udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp,
+		(tmp & UDCCS0_SA) ? " sa" : "",
+		(tmp & UDCCS0_RNE) ? " rne" : "",
+		(tmp & UDCCS0_FST) ? " fst" : "",
+		(tmp & UDCCS0_SST) ? " sst" : "",
+		(tmp & UDCCS0_DRWF) ? " dwrf" : "",
+		(tmp & UDCCS0_FTF) ? " ftf" : "",
+		(tmp & UDCCS0_IPR) ? " ipr" : "",
+		(tmp & UDCCS0_OPR) ? " opr" : "");
+
+	if (dev->has_cfr) {
+		tmp = UDCCFR;
+		seq_printf(m,
+			"udccfr %02X =%s%s\n", tmp,
+			(tmp & UDCCFR_AREN) ? " aren" : "",
+			(tmp & UDCCFR_ACM) ? " acm" : "");
+	}
+
+	if (!is_vbus_present() || !dev->driver)
+		goto done;
+
+	seq_printf(m, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
+		dev->stats.write.bytes, dev->stats.write.ops,
+		dev->stats.read.bytes, dev->stats.read.ops,
+		dev->stats.irqs);
+
+	/* dump endpoint queues */
+	for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
+		struct pxa25x_ep	*ep = &dev->ep [i];
+		struct pxa25x_request	*req;
+
+		if (i != 0) {
+			const struct usb_endpoint_descriptor	*desc;
+
+			desc = ep->desc;
+			if (!desc)
+				continue;
+			tmp = *dev->ep [i].reg_udccs;
+			seq_printf(m,
+				"%s max %d %s udccs %02x irqs %lu\n",
+				ep->ep.name, le16_to_cpu(desc->wMaxPacketSize),
+				"pio", tmp, ep->pio_irqs);
+			/* TODO translate all five groups of udccs bits! */
+
+		} else /* ep0 should only have one transfer queued */
+			seq_printf(m, "ep0 max 16 pio irqs %lu\n",
+				ep->pio_irqs);
+
+		if (list_empty(&ep->queue)) {
+			seq_printf(m, "\t(nothing queued)\n");
+			continue;
+		}
+		list_for_each_entry(req, &ep->queue, queue) {
+			seq_printf(m,
+					"\treq %p len %d/%d buf %p\n",
+					&req->req, req->req.actual,
+					req->req.length, req->req.buf);
+		}
+	}
+
+done:
+	local_irq_restore(flags);
+	return 0;
+}
+
+static int
+udc_debugfs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, udc_seq_show, inode->i_private);
+}
+
+static const struct file_operations debug_fops = {
+	.open		= udc_debugfs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.owner		= THIS_MODULE,
+};
+
+#define create_debug_files(dev) \
+	do { \
+		dev->debugfs_udc = debugfs_create_file(dev->gadget.name, \
+			S_IRUGO, NULL, dev, &debug_fops); \
+	} while (0)
+#define remove_debug_files(dev) \
+	do { \
+		if (dev->debugfs_udc) \
+			debugfs_remove(dev->debugfs_udc); \
+	} while (0)
+
+#else	/* !CONFIG_USB_GADGET_DEBUG_FILES */
+
+#define create_debug_files(dev) do {} while (0)
+#define remove_debug_files(dev) do {} while (0)
+
+#endif	/* CONFIG_USB_GADGET_DEBUG_FILES */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ *	udc_disable - disable USB device controller
+ */
+static void udc_disable(struct pxa25x_udc *dev)
+{
+	/* block all irqs */
+	udc_set_mask_UDCCR(UDCCR_SRM|UDCCR_REM);
+	UICR0 = UICR1 = 0xff;
+	UFNRH = UFNRH_SIM;
+
+	/* if hardware supports it, disconnect from usb */
+	pullup_off();
+
+	udc_clear_mask_UDCCR(UDCCR_UDE);
+
+	ep0_idle (dev);
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+}
+
+
+/*
+ *	udc_reinit - initialize software state
+ */
+static void udc_reinit(struct pxa25x_udc *dev)
+{
+	u32	i;
+
+	/* device/ep0 records init */
+	INIT_LIST_HEAD (&dev->gadget.ep_list);
+	INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
+	dev->ep0state = EP0_IDLE;
+
+	/* basic endpoint records init */
+	for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
+		struct pxa25x_ep *ep = &dev->ep[i];
+
+		if (i != 0)
+			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
+
+		ep->desc = NULL;
+		ep->stopped = 0;
+		INIT_LIST_HEAD (&ep->queue);
+		ep->pio_irqs = 0;
+	}
+
+	/* the rest was statically initialized, and is read-only */
+}
+
+/* until it's enabled, this UDC should be completely invisible
+ * to any USB host.
+ */
+static void udc_enable (struct pxa25x_udc *dev)
+{
+	udc_clear_mask_UDCCR(UDCCR_UDE);
+
+	/* try to clear these bits before we enable the udc */
+	udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
+
+	ep0_idle(dev);
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+	dev->stats.irqs = 0;
+
+	/*
+	 * sequence taken from chapter 12.5.10, PXA250 AppProcDevManual:
+	 * - enable UDC
+	 * - if RESET is already in progress, ack interrupt
+	 * - unmask reset interrupt
+	 */
+	udc_set_mask_UDCCR(UDCCR_UDE);
+	if (!(UDCCR & UDCCR_UDA))
+		udc_ack_int_UDCCR(UDCCR_RSTIR);
+
+	if (dev->has_cfr /* UDC_RES2 is defined */) {
+		/* pxa255 (a0+) can avoid a set_config race that could
+		 * prevent gadget drivers from configuring correctly
+		 */
+		UDCCFR = UDCCFR_ACM | UDCCFR_MB1;
+	} else {
+		/* "USB test mode" for pxa250 errata 40-42 (stepping a0, a1)
+		 * which could result in missing packets and interrupts.
+		 * supposedly one bit per endpoint, controlling whether it
+		 * double buffers or not; ACM/AREN bits fit into the holes.
+		 * zero bits (like USIR0_IRx) disable double buffering.
+		 */
+		UDC_RES1 = 0x00;
+		UDC_RES2 = 0x00;
+	}
+
+	/* enable suspend/resume and reset irqs */
+	udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
+
+	/* enable ep0 irqs */
+	UICR0 &= ~UICR0_IM0;
+
+	/* if hardware supports it, pullup D+ and wait for reset */
+	pullup_on();
+}
+
+
+/* when a driver is successfully registered, it will receive
+ * control requests including set_configuration(), which enables
+ * non-control requests.  then usb traffic follows until a
+ * disconnect is reported.  then a host may connect again, or
+ * the driver might get unbound.
+ */
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+	struct pxa25x_udc	*dev = the_controller;
+	int			retval;
+
+	if (!driver
+			|| driver->speed < USB_SPEED_FULL
+			|| !driver->bind
+			|| !driver->disconnect
+			|| !driver->setup)
+		return -EINVAL;
+	if (!dev)
+		return -ENODEV;
+	if (dev->driver)
+		return -EBUSY;
+
+	/* first hook up the driver ... */
+	dev->driver = driver;
+	dev->gadget.dev.driver = &driver->driver;
+	dev->pullup = 1;
+
+	retval = device_add (&dev->gadget.dev);
+	if (retval) {
+fail:
+		dev->driver = NULL;
+		dev->gadget.dev.driver = NULL;
+		return retval;
+	}
+	retval = driver->bind(&dev->gadget);
+	if (retval) {
+		DMSG("bind to driver %s --> error %d\n",
+				driver->driver.name, retval);
+		device_del (&dev->gadget.dev);
+		goto fail;
+	}
+
+	/* ... then enable host detection and ep0; and we're ready
+	 * for set_configuration as well as eventual disconnect.
+	 */
+	DMSG("registered gadget driver '%s'\n", driver->driver.name);
+	pullup(dev);
+	dump_state(dev);
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+static void
+stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
+{
+	int i;
+
+	/* don't disconnect drivers more than once */
+	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+		driver = NULL;
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+	/* prevent new request submissions, kill any outstanding requests  */
+	for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
+		struct pxa25x_ep *ep = &dev->ep[i];
+
+		ep->stopped = 1;
+		nuke(ep, -ESHUTDOWN);
+	}
+	del_timer_sync(&dev->timer);
+
+	/* report disconnect; the driver is already quiesced */
+	if (driver)
+		driver->disconnect(&dev->gadget);
+
+	/* re-init driver-visible data structures */
+	udc_reinit(dev);
+}
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct pxa25x_udc	*dev = the_controller;
+
+	if (!dev)
+		return -ENODEV;
+	if (!driver || driver != dev->driver || !driver->unbind)
+		return -EINVAL;
+
+	local_irq_disable();
+	dev->pullup = 0;
+	pullup(dev);
+	stop_activity(dev, driver);
+	local_irq_enable();
+
+	driver->unbind(&dev->gadget);
+	dev->gadget.dev.driver = NULL;
+	dev->driver = NULL;
+
+	device_del (&dev->gadget.dev);
+
+	DMSG("unregistered gadget driver '%s'\n", driver->driver.name);
+	dump_state(dev);
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_LUBBOCK
+
+/* Lubbock has separate connect and disconnect irqs.  More typical designs
+ * use one GPIO as the VBUS IRQ, and another to control the D+ pullup.
+ */
+
+static irqreturn_t
+lubbock_vbus_irq(int irq, void *_dev)
+{
+	struct pxa25x_udc	*dev = _dev;
+	int			vbus;
+
+	dev->stats.irqs++;
+	switch (irq) {
+	case LUBBOCK_USB_IRQ:
+		vbus = 1;
+		disable_irq(LUBBOCK_USB_IRQ);
+		enable_irq(LUBBOCK_USB_DISC_IRQ);
+		break;
+	case LUBBOCK_USB_DISC_IRQ:
+		vbus = 0;
+		disable_irq(LUBBOCK_USB_DISC_IRQ);
+		enable_irq(LUBBOCK_USB_IRQ);
+		break;
+	default:
+		return IRQ_NONE;
+	}
+
+	pxa25x_udc_vbus_session(&dev->gadget, vbus);
+	return IRQ_HANDLED;
+}
+
+#endif
+
+static irqreturn_t udc_vbus_irq(int irq, void *_dev)
+{
+	struct pxa25x_udc	*dev = _dev;
+	int			vbus = gpio_get_value(dev->mach->gpio_vbus);
+
+	if (dev->mach->gpio_vbus_inverted)
+		vbus = !vbus;
+
+	pxa25x_udc_vbus_session(&dev->gadget, vbus);
+	return IRQ_HANDLED;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static inline void clear_ep_state (struct pxa25x_udc *dev)
+{
+	unsigned i;
+
+	/* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
+	 * fifos, and pending transactions mustn't be continued in any case.
+	 */
+	for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++)
+		nuke(&dev->ep[i], -ECONNABORTED);
+}
+
+static void udc_watchdog(unsigned long _dev)
+{
+	struct pxa25x_udc	*dev = (void *)_dev;
+
+	local_irq_disable();
+	if (dev->ep0state == EP0_STALL
+			&& (UDCCS0 & UDCCS0_FST) == 0
+			&& (UDCCS0 & UDCCS0_SST) == 0) {
+		UDCCS0 = UDCCS0_FST|UDCCS0_FTF;
+		DBG(DBG_VERBOSE, "ep0 re-stall\n");
+		start_watchdog(dev);
+	}
+	local_irq_enable();
+}
+
+static void handle_ep0 (struct pxa25x_udc *dev)
+{
+	u32			udccs0 = UDCCS0;
+	struct pxa25x_ep	*ep = &dev->ep [0];
+	struct pxa25x_request	*req;
+	union {
+		struct usb_ctrlrequest	r;
+		u8			raw [8];
+		u32			word [2];
+	} u;
+
+	if (list_empty(&ep->queue))
+		req = NULL;
+	else
+		req = list_entry(ep->queue.next, struct pxa25x_request, queue);
+
+	/* clear stall status */
+	if (udccs0 & UDCCS0_SST) {
+		nuke(ep, -EPIPE);
+		UDCCS0 = UDCCS0_SST;
+		del_timer(&dev->timer);
+		ep0_idle(dev);
+	}
+
+	/* previous request unfinished?  non-error iff back-to-back ... */
+	if ((udccs0 & UDCCS0_SA) != 0 && dev->ep0state != EP0_IDLE) {
+		nuke(ep, 0);
+		del_timer(&dev->timer);
+		ep0_idle(dev);
+	}
+
+	switch (dev->ep0state) {
+	case EP0_IDLE:
+		/* late-breaking status? */
+		udccs0 = UDCCS0;
+
+		/* start control request? */
+		if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))
+				== (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))) {
+			int i;
+
+			nuke (ep, -EPROTO);
+
+			/* read SETUP packet */
+			for (i = 0; i < 8; i++) {
+				if (unlikely(!(UDCCS0 & UDCCS0_RNE))) {
+bad_setup:
+					DMSG("SETUP %d!\n", i);
+					goto stall;
+				}
+				u.raw [i] = (u8) UDDR0;
+			}
+			if (unlikely((UDCCS0 & UDCCS0_RNE) != 0))
+				goto bad_setup;
+
+got_setup:
+			DBG(DBG_VERBOSE, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+				u.r.bRequestType, u.r.bRequest,
+				le16_to_cpu(u.r.wValue),
+				le16_to_cpu(u.r.wIndex),
+				le16_to_cpu(u.r.wLength));
+
+			/* cope with automagic for some standard requests. */
+			dev->req_std = (u.r.bRequestType & USB_TYPE_MASK)
+						== USB_TYPE_STANDARD;
+			dev->req_config = 0;
+			dev->req_pending = 1;
+			switch (u.r.bRequest) {
+			/* hardware restricts gadget drivers here! */
+			case USB_REQ_SET_CONFIGURATION:
+				if (u.r.bRequestType == USB_RECIP_DEVICE) {
+					/* reflect hardware's automagic
+					 * up to the gadget driver.
+					 */
+config_change:
+					dev->req_config = 1;
+					clear_ep_state(dev);
+					/* if !has_cfr, there's no synch
+					 * else use AREN (later) not SA|OPR
+					 * USIR0_IR0 acts edge sensitive
+					 */
+				}
+				break;
+			/* ... and here, even more ... */
+			case USB_REQ_SET_INTERFACE:
+				if (u.r.bRequestType == USB_RECIP_INTERFACE) {
+					/* udc hardware is broken by design:
+					 *  - altsetting may only be zero;
+					 *  - hw resets all interfaces' eps;
+					 *  - ep reset doesn't include halt(?).
+					 */
+					DMSG("broken set_interface (%d/%d)\n",
+						le16_to_cpu(u.r.wIndex),
+						le16_to_cpu(u.r.wValue));
+					goto config_change;
+				}
+				break;
+			/* hardware was supposed to hide this */
+			case USB_REQ_SET_ADDRESS:
+				if (u.r.bRequestType == USB_RECIP_DEVICE) {
+					ep0start(dev, 0, "address");
+					return;
+				}
+				break;
+			}
+
+			if (u.r.bRequestType & USB_DIR_IN)
+				dev->ep0state = EP0_IN_DATA_PHASE;
+			else
+				dev->ep0state = EP0_OUT_DATA_PHASE;
+
+			i = dev->driver->setup(&dev->gadget, &u.r);
+			if (i < 0) {
+				/* hardware automagic preventing STALL... */
+				if (dev->req_config) {
+					/* hardware sometimes neglects to tell
+					 * tell us about config change events,
+					 * so later ones may fail...
+					 */
+					WARNING("config change %02x fail %d?\n",
+						u.r.bRequest, i);
+					return;
+					/* TODO experiment:  if has_cfr,
+					 * hardware didn't ACK; maybe we
+					 * could actually STALL!
+					 */
+				}
+				DBG(DBG_VERBOSE, "protocol STALL, "
+					"%02x err %d\n", UDCCS0, i);
+stall:
+				/* the watchdog timer helps deal with cases
+				 * where udc seems to clear FST wrongly, and
+				 * then NAKs instead of STALLing.
+				 */
+				ep0start(dev, UDCCS0_FST|UDCCS0_FTF, "stall");
+				start_watchdog(dev);
+				dev->ep0state = EP0_STALL;
+
+			/* deferred i/o == no response yet */
+			} else if (dev->req_pending) {
+				if (likely(dev->ep0state == EP0_IN_DATA_PHASE
+						|| dev->req_std || u.r.wLength))
+					ep0start(dev, 0, "defer");
+				else
+					ep0start(dev, UDCCS0_IPR, "defer/IPR");
+			}
+
+			/* expect at least one data or status stage irq */
+			return;
+
+		} else if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA))
+				== (UDCCS0_OPR|UDCCS0_SA))) {
+			unsigned i;
+
+			/* pxa210/250 erratum 131 for B0/B1 says RNE lies.
+			 * still observed on a pxa255 a0.
+			 */
+			DBG(DBG_VERBOSE, "e131\n");
+			nuke(ep, -EPROTO);
+
+			/* read SETUP data, but don't trust it too much */
+			for (i = 0; i < 8; i++)
+				u.raw [i] = (u8) UDDR0;
+			if ((u.r.bRequestType & USB_RECIP_MASK)
+					> USB_RECIP_OTHER)
+				goto stall;
+			if (u.word [0] == 0 && u.word [1] == 0)
+				goto stall;
+			goto got_setup;
+		} else {
+			/* some random early IRQ:
+			 * - we acked FST
+			 * - IPR cleared
+			 * - OPR got set, without SA (likely status stage)
+			 */
+			UDCCS0 = udccs0 & (UDCCS0_SA|UDCCS0_OPR);
+		}
+		break;
+	case EP0_IN_DATA_PHASE:			/* GET_DESCRIPTOR etc */
+		if (udccs0 & UDCCS0_OPR) {
+			UDCCS0 = UDCCS0_OPR|UDCCS0_FTF;
+			DBG(DBG_VERBOSE, "ep0in premature status\n");
+			if (req)
+				done(ep, req, 0);
+			ep0_idle(dev);
+		} else /* irq was IPR clearing */ {
+			if (req) {
+				/* this IN packet might finish the request */
+				(void) write_ep0_fifo(ep, req);
+			} /* else IN token before response was written */
+		}
+		break;
+	case EP0_OUT_DATA_PHASE:		/* SET_DESCRIPTOR etc */
+		if (udccs0 & UDCCS0_OPR) {
+			if (req) {
+				/* this OUT packet might finish the request */
+				if (read_ep0_fifo(ep, req))
+					done(ep, req, 0);
+				/* else more OUT packets expected */
+			} /* else OUT token before read was issued */
+		} else /* irq was IPR clearing */ {
+			DBG(DBG_VERBOSE, "ep0out premature status\n");
+			if (req)
+				done(ep, req, 0);
+			ep0_idle(dev);
+		}
+		break;
+	case EP0_END_XFER:
+		if (req)
+			done(ep, req, 0);
+		/* ack control-IN status (maybe in-zlp was skipped)
+		 * also appears after some config change events.
+		 */
+		if (udccs0 & UDCCS0_OPR)
+			UDCCS0 = UDCCS0_OPR;
+		ep0_idle(dev);
+		break;
+	case EP0_STALL:
+		UDCCS0 = UDCCS0_FST;
+		break;
+	}
+	USIR0 = USIR0_IR0;
+}
+
+static void handle_ep(struct pxa25x_ep *ep)
+{
+	struct pxa25x_request	*req;
+	int			is_in = ep->bEndpointAddress & USB_DIR_IN;
+	int			completed;
+	u32			udccs, tmp;
+
+	do {
+		completed = 0;
+		if (likely (!list_empty(&ep->queue)))
+			req = list_entry(ep->queue.next,
+					struct pxa25x_request, queue);
+		else
+			req = NULL;
+
+		// TODO check FST handling
+
+		udccs = *ep->reg_udccs;
+		if (unlikely(is_in)) {	/* irq from TPC, SST, or (ISO) TUR */
+			tmp = UDCCS_BI_TUR;
+			if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK))
+				tmp |= UDCCS_BI_SST;
+			tmp &= udccs;
+			if (likely (tmp))
+				*ep->reg_udccs = tmp;
+			if (req && likely ((udccs & UDCCS_BI_TFS) != 0))
+				completed = write_fifo(ep, req);
+
+		} else {	/* irq from RPC (or for ISO, ROF) */
+			if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK))
+				tmp = UDCCS_BO_SST | UDCCS_BO_DME;
+			else
+				tmp = UDCCS_IO_ROF | UDCCS_IO_DME;
+			tmp &= udccs;
+			if (likely(tmp))
+				*ep->reg_udccs = tmp;
+
+			/* fifos can hold packets, ready for reading... */
+			if (likely(req)) {
+				completed = read_fifo(ep, req);
+			} else
+				pio_irq_disable (ep->bEndpointAddress);
+		}
+		ep->pio_irqs++;
+	} while (completed);
+}
+
+/*
+ *	pxa25x_udc_irq - interrupt handler
+ *
+ * avoid delays in ep0 processing. the control handshaking isn't always
+ * under software control (pxa250c0 and the pxa255 are better), and delays
+ * could cause usb protocol errors.
+ */
+static irqreturn_t
+pxa25x_udc_irq(int irq, void *_dev)
+{
+	struct pxa25x_udc	*dev = _dev;
+	int			handled;
+
+	dev->stats.irqs++;
+	do {
+		u32		udccr = UDCCR;
+
+		handled = 0;
+
+		/* SUSpend Interrupt Request */
+		if (unlikely(udccr & UDCCR_SUSIR)) {
+			udc_ack_int_UDCCR(UDCCR_SUSIR);
+			handled = 1;
+			DBG(DBG_VERBOSE, "USB suspend%s\n", is_vbus_present()
+				? "" : "+disconnect");
+
+			if (!is_vbus_present())
+				stop_activity(dev, dev->driver);
+			else if (dev->gadget.speed != USB_SPEED_UNKNOWN
+					&& dev->driver
+					&& dev->driver->suspend)
+				dev->driver->suspend(&dev->gadget);
+			ep0_idle (dev);
+		}
+
+		/* RESume Interrupt Request */
+		if (unlikely(udccr & UDCCR_RESIR)) {
+			udc_ack_int_UDCCR(UDCCR_RESIR);
+			handled = 1;
+			DBG(DBG_VERBOSE, "USB resume\n");
+
+			if (dev->gadget.speed != USB_SPEED_UNKNOWN
+					&& dev->driver
+					&& dev->driver->resume
+					&& is_vbus_present())
+				dev->driver->resume(&dev->gadget);
+		}
+
+		/* ReSeT Interrupt Request - USB reset */
+		if (unlikely(udccr & UDCCR_RSTIR)) {
+			udc_ack_int_UDCCR(UDCCR_RSTIR);
+			handled = 1;
+
+			if ((UDCCR & UDCCR_UDA) == 0) {
+				DBG(DBG_VERBOSE, "USB reset start\n");
+
+				/* reset driver and endpoints,
+				 * in case that's not yet done
+				 */
+				stop_activity (dev, dev->driver);
+
+			} else {
+				DBG(DBG_VERBOSE, "USB reset end\n");
+				dev->gadget.speed = USB_SPEED_FULL;
+				memset(&dev->stats, 0, sizeof dev->stats);
+				/* driver and endpoints are still reset */
+			}
+
+		} else {
+			u32	usir0 = USIR0 & ~UICR0;
+			u32	usir1 = USIR1 & ~UICR1;
+			int	i;
+
+			if (unlikely (!usir0 && !usir1))
+				continue;
+
+			DBG(DBG_VERY_NOISY, "irq %02x.%02x\n", usir1, usir0);
+
+			/* control traffic */
+			if (usir0 & USIR0_IR0) {
+				dev->ep[0].pio_irqs++;
+				handle_ep0(dev);
+				handled = 1;
+			}
+
+			/* endpoint data transfers */
+			for (i = 0; i < 8; i++) {
+				u32	tmp = 1 << i;
+
+				if (i && (usir0 & tmp)) {
+					handle_ep(&dev->ep[i]);
+					USIR0 |= tmp;
+					handled = 1;
+				}
+				if (usir1 & tmp) {
+					handle_ep(&dev->ep[i+8]);
+					USIR1 |= tmp;
+					handled = 1;
+				}
+			}
+		}
+
+		/* we could also ask for 1 msec SOF (SIR) interrupts */
+
+	} while (handled);
+	return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void nop_release (struct device *dev)
+{
+	DMSG("%s %s\n", __func__, dev_name(dev));
+}
+
+/* this uses load-time allocation and initialization (instead of
+ * doing it at run-time) to save code, eliminate fault paths, and
+ * be more obviously correct.
+ */
+static struct pxa25x_udc memory = {
+	.gadget = {
+		.ops		= &pxa25x_udc_ops,
+		.ep0		= &memory.ep[0].ep,
+		.name		= driver_name,
+		.dev = {
+			.bus_id		= "gadget",
+			.release	= nop_release,
+		},
+	},
+
+	/* control endpoint */
+	.ep[0] = {
+		.ep = {
+			.name		= ep0name,
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= EP0_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.reg_udccs	= &UDCCS0,
+		.reg_uddr	= &UDDR0,
+	},
+
+	/* first group of endpoints */
+	.ep[1] = {
+		.ep = {
+			.name		= "ep1in-bulk",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= BULK_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= BULK_FIFO_SIZE,
+		.bEndpointAddress = USB_DIR_IN | 1,
+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
+		.reg_udccs	= &UDCCS1,
+		.reg_uddr	= &UDDR1,
+	},
+	.ep[2] = {
+		.ep = {
+			.name		= "ep2out-bulk",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= BULK_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= BULK_FIFO_SIZE,
+		.bEndpointAddress = 2,
+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
+		.reg_udccs	= &UDCCS2,
+		.reg_ubcr	= &UBCR2,
+		.reg_uddr	= &UDDR2,
+	},
+#ifndef CONFIG_USB_PXA25X_SMALL
+	.ep[3] = {
+		.ep = {
+			.name		= "ep3in-iso",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= ISO_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= ISO_FIFO_SIZE,
+		.bEndpointAddress = USB_DIR_IN | 3,
+		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
+		.reg_udccs	= &UDCCS3,
+		.reg_uddr	= &UDDR3,
+	},
+	.ep[4] = {
+		.ep = {
+			.name		= "ep4out-iso",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= ISO_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= ISO_FIFO_SIZE,
+		.bEndpointAddress = 4,
+		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
+		.reg_udccs	= &UDCCS4,
+		.reg_ubcr	= &UBCR4,
+		.reg_uddr	= &UDDR4,
+	},
+	.ep[5] = {
+		.ep = {
+			.name		= "ep5in-int",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= INT_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= INT_FIFO_SIZE,
+		.bEndpointAddress = USB_DIR_IN | 5,
+		.bmAttributes	= USB_ENDPOINT_XFER_INT,
+		.reg_udccs	= &UDCCS5,
+		.reg_uddr	= &UDDR5,
+	},
+
+	/* second group of endpoints */
+	.ep[6] = {
+		.ep = {
+			.name		= "ep6in-bulk",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= BULK_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= BULK_FIFO_SIZE,
+		.bEndpointAddress = USB_DIR_IN | 6,
+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
+		.reg_udccs	= &UDCCS6,
+		.reg_uddr	= &UDDR6,
+	},
+	.ep[7] = {
+		.ep = {
+			.name		= "ep7out-bulk",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= BULK_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= BULK_FIFO_SIZE,
+		.bEndpointAddress = 7,
+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
+		.reg_udccs	= &UDCCS7,
+		.reg_ubcr	= &UBCR7,
+		.reg_uddr	= &UDDR7,
+	},
+	.ep[8] = {
+		.ep = {
+			.name		= "ep8in-iso",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= ISO_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= ISO_FIFO_SIZE,
+		.bEndpointAddress = USB_DIR_IN | 8,
+		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
+		.reg_udccs	= &UDCCS8,
+		.reg_uddr	= &UDDR8,
+	},
+	.ep[9] = {
+		.ep = {
+			.name		= "ep9out-iso",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= ISO_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= ISO_FIFO_SIZE,
+		.bEndpointAddress = 9,
+		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
+		.reg_udccs	= &UDCCS9,
+		.reg_ubcr	= &UBCR9,
+		.reg_uddr	= &UDDR9,
+	},
+	.ep[10] = {
+		.ep = {
+			.name		= "ep10in-int",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= INT_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= INT_FIFO_SIZE,
+		.bEndpointAddress = USB_DIR_IN | 10,
+		.bmAttributes	= USB_ENDPOINT_XFER_INT,
+		.reg_udccs	= &UDCCS10,
+		.reg_uddr	= &UDDR10,
+	},
+
+	/* third group of endpoints */
+	.ep[11] = {
+		.ep = {
+			.name		= "ep11in-bulk",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= BULK_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= BULK_FIFO_SIZE,
+		.bEndpointAddress = USB_DIR_IN | 11,
+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
+		.reg_udccs	= &UDCCS11,
+		.reg_uddr	= &UDDR11,
+	},
+	.ep[12] = {
+		.ep = {
+			.name		= "ep12out-bulk",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= BULK_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= BULK_FIFO_SIZE,
+		.bEndpointAddress = 12,
+		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
+		.reg_udccs	= &UDCCS12,
+		.reg_ubcr	= &UBCR12,
+		.reg_uddr	= &UDDR12,
+	},
+	.ep[13] = {
+		.ep = {
+			.name		= "ep13in-iso",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= ISO_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= ISO_FIFO_SIZE,
+		.bEndpointAddress = USB_DIR_IN | 13,
+		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
+		.reg_udccs	= &UDCCS13,
+		.reg_uddr	= &UDDR13,
+	},
+	.ep[14] = {
+		.ep = {
+			.name		= "ep14out-iso",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= ISO_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= ISO_FIFO_SIZE,
+		.bEndpointAddress = 14,
+		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
+		.reg_udccs	= &UDCCS14,
+		.reg_ubcr	= &UBCR14,
+		.reg_uddr	= &UDDR14,
+	},
+	.ep[15] = {
+		.ep = {
+			.name		= "ep15in-int",
+			.ops		= &pxa25x_ep_ops,
+			.maxpacket	= INT_FIFO_SIZE,
+		},
+		.dev		= &memory,
+		.fifo_size	= INT_FIFO_SIZE,
+		.bEndpointAddress = USB_DIR_IN | 15,
+		.bmAttributes	= USB_ENDPOINT_XFER_INT,
+		.reg_udccs	= &UDCCS15,
+		.reg_uddr	= &UDDR15,
+	},
+#endif /* !CONFIG_USB_PXA25X_SMALL */
+};
+
+#define CP15R0_VENDOR_MASK	0xffffe000
+
+#if	defined(CONFIG_ARCH_PXA)
+#define CP15R0_XSCALE_VALUE	0x69052000	/* intel/arm/xscale */
+
+#elif	defined(CONFIG_ARCH_IXP4XX)
+#define CP15R0_XSCALE_VALUE	0x69054000	/* intel/arm/ixp4xx */
+
+#endif
+
+#define CP15R0_PROD_MASK	0x000003f0
+#define PXA25x			0x00000100	/* and PXA26x */
+#define PXA210			0x00000120
+
+#define CP15R0_REV_MASK		0x0000000f
+
+#define CP15R0_PRODREV_MASK	(CP15R0_PROD_MASK | CP15R0_REV_MASK)
+
+#define PXA255_A0		0x00000106	/* or PXA260_B1 */
+#define PXA250_C0		0x00000105	/* or PXA26x_B0 */
+#define PXA250_B2		0x00000104
+#define PXA250_B1		0x00000103	/* or PXA260_A0 */
+#define PXA250_B0		0x00000102
+#define PXA250_A1		0x00000101
+#define PXA250_A0		0x00000100
+
+#define PXA210_C0		0x00000125
+#define PXA210_B2		0x00000124
+#define PXA210_B1		0x00000123
+#define PXA210_B0		0x00000122
+#define IXP425_A0		0x000001c1
+#define IXP425_B0		0x000001f1
+#define IXP465_AD		0x00000200
+
+/*
+ *	probe - binds to the platform device
+ */
+static int __init pxa25x_udc_probe(struct platform_device *pdev)
+{
+	struct pxa25x_udc *dev = &memory;
+	int retval, vbus_irq, irq;
+	u32 chiprev;
+
+	/* insist on Intel/ARM/XScale */
+	asm("mrc%? p15, 0, %0, c0, c0" : "=r" (chiprev));
+	if ((chiprev & CP15R0_VENDOR_MASK) != CP15R0_XSCALE_VALUE) {
+		pr_err("%s: not XScale!\n", driver_name);
+		return -ENODEV;
+	}
+
+	/* trigger chiprev-specific logic */
+	switch (chiprev & CP15R0_PRODREV_MASK) {
+#if	defined(CONFIG_ARCH_PXA)
+	case PXA255_A0:
+		dev->has_cfr = 1;
+		break;
+	case PXA250_A0:
+	case PXA250_A1:
+		/* A0/A1 "not released"; ep 13, 15 unusable */
+		/* fall through */
+	case PXA250_B2: case PXA210_B2:
+	case PXA250_B1: case PXA210_B1:
+	case PXA250_B0: case PXA210_B0:
+		/* OUT-DMA is broken ... */
+		/* fall through */
+	case PXA250_C0: case PXA210_C0:
+		break;
+#elif	defined(CONFIG_ARCH_IXP4XX)
+	case IXP425_A0:
+	case IXP425_B0:
+	case IXP465_AD:
+		dev->has_cfr = 1;
+		break;
+#endif
+	default:
+		pr_err("%s: unrecognized processor: %08x\n",
+			driver_name, chiprev);
+		/* iop3xx, ixp4xx, ... */
+		return -ENODEV;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return -ENODEV;
+
+	dev->clk = clk_get(&pdev->dev, "UDCCLK");
+	if (IS_ERR(dev->clk)) {
+		retval = PTR_ERR(dev->clk);
+		goto err_clk;
+	}
+
+	pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
+		dev->has_cfr ? "" : " (!cfr)",
+		SIZE_STR "(pio)"
+		);
+
+	/* other non-static parts of init */
+	dev->dev = &pdev->dev;
+	dev->mach = pdev->dev.platform_data;
+
+	if (dev->mach->gpio_vbus) {
+		if ((retval = gpio_request(dev->mach->gpio_vbus,
+				"pxa25x_udc GPIO VBUS"))) {
+			dev_dbg(&pdev->dev,
+				"can't get vbus gpio %d, err: %d\n",
+				dev->mach->gpio_vbus, retval);
+			goto err_gpio_vbus;
+		}
+		gpio_direction_input(dev->mach->gpio_vbus);
+		vbus_irq = gpio_to_irq(dev->mach->gpio_vbus);
+	} else
+		vbus_irq = 0;
+
+	if (dev->mach->gpio_pullup) {
+		if ((retval = gpio_request(dev->mach->gpio_pullup,
+				"pca25x_udc GPIO PULLUP"))) {
+			dev_dbg(&pdev->dev,
+				"can't get pullup gpio %d, err: %d\n",
+				dev->mach->gpio_pullup, retval);
+			goto err_gpio_pullup;
+		}
+		gpio_direction_output(dev->mach->gpio_pullup, 0);
+	}
+
+	init_timer(&dev->timer);
+	dev->timer.function = udc_watchdog;
+	dev->timer.data = (unsigned long) dev;
+
+	device_initialize(&dev->gadget.dev);
+	dev->gadget.dev.parent = &pdev->dev;
+	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
+
+	the_controller = dev;
+	platform_set_drvdata(pdev, dev);
+
+	udc_disable(dev);
+	udc_reinit(dev);
+
+	dev->vbus = is_vbus_present();
+
+	/* irq setup after old hardware state is cleaned up */
+	retval = request_irq(irq, pxa25x_udc_irq,
+			IRQF_DISABLED, driver_name, dev);
+	if (retval != 0) {
+		pr_err("%s: can't get irq %d, err %d\n",
+			driver_name, irq, retval);
+		goto err_irq1;
+	}
+	dev->got_irq = 1;
+
+#ifdef CONFIG_ARCH_LUBBOCK
+	if (machine_is_lubbock()) {
+		retval = request_irq(LUBBOCK_USB_DISC_IRQ,
+				lubbock_vbus_irq,
+				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+				driver_name, dev);
+		if (retval != 0) {
+			pr_err("%s: can't get irq %i, err %d\n",
+				driver_name, LUBBOCK_USB_DISC_IRQ, retval);
+lubbock_fail0:
+			goto err_irq_lub;
+		}
+		retval = request_irq(LUBBOCK_USB_IRQ,
+				lubbock_vbus_irq,
+				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+				driver_name, dev);
+		if (retval != 0) {
+			pr_err("%s: can't get irq %i, err %d\n",
+				driver_name, LUBBOCK_USB_IRQ, retval);
+			free_irq(LUBBOCK_USB_DISC_IRQ, dev);
+			goto lubbock_fail0;
+		}
+	} else
+#endif
+	if (vbus_irq) {
+		retval = request_irq(vbus_irq, udc_vbus_irq,
+				IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				driver_name, dev);
+		if (retval != 0) {
+			pr_err("%s: can't get irq %i, err %d\n",
+				driver_name, vbus_irq, retval);
+			goto err_vbus_irq;
+		}
+	}
+	create_debug_files(dev);
+
+	return 0;
+
+ err_vbus_irq:
+#ifdef	CONFIG_ARCH_LUBBOCK
+	free_irq(LUBBOCK_USB_DISC_IRQ, dev);
+ err_irq_lub:
+#endif
+	free_irq(irq, dev);
+ err_irq1:
+	if (dev->mach->gpio_pullup)
+		gpio_free(dev->mach->gpio_pullup);
+ err_gpio_pullup:
+	if (dev->mach->gpio_vbus)
+		gpio_free(dev->mach->gpio_vbus);
+ err_gpio_vbus:
+	clk_put(dev->clk);
+ err_clk:
+	return retval;
+}
+
+static void pxa25x_udc_shutdown(struct platform_device *_dev)
+{
+	pullup_off();
+}
+
+static int __exit pxa25x_udc_remove(struct platform_device *pdev)
+{
+	struct pxa25x_udc *dev = platform_get_drvdata(pdev);
+
+	if (dev->driver)
+		return -EBUSY;
+
+	dev->pullup = 0;
+	pullup(dev);
+
+	remove_debug_files(dev);
+
+	if (dev->got_irq) {
+		free_irq(platform_get_irq(pdev, 0), dev);
+		dev->got_irq = 0;
+	}
+#ifdef CONFIG_ARCH_LUBBOCK
+	if (machine_is_lubbock()) {
+		free_irq(LUBBOCK_USB_DISC_IRQ, dev);
+		free_irq(LUBBOCK_USB_IRQ, dev);
+	}
+#endif
+	if (dev->mach->gpio_vbus) {
+		free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev);
+		gpio_free(dev->mach->gpio_vbus);
+	}
+	if (dev->mach->gpio_pullup)
+		gpio_free(dev->mach->gpio_pullup);
+
+	clk_put(dev->clk);
+
+	platform_set_drvdata(pdev, NULL);
+	the_controller = NULL;
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_PM
+
+/* USB suspend (controlled by the host) and system suspend (controlled
+ * by the PXA) don't necessarily work well together.  If USB is active,
+ * the 48 MHz clock is required; so the system can't enter 33 MHz idle
+ * mode, or any deeper PM saving state.
+ *
+ * For now, we punt and forcibly disconnect from the USB host when PXA
+ * enters any suspend state.  While we're disconnected, we always disable
+ * the 48MHz USB clock ... allowing PXA sleep and/or 33 MHz idle states.
+ * Boards without software pullup control shouldn't use those states.
+ * VBUS IRQs should probably be ignored so that the PXA device just acts
+ * "dead" to USB hosts until system resume.
+ */
+static int pxa25x_udc_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct pxa25x_udc	*udc = platform_get_drvdata(dev);
+	unsigned long flags;
+
+	if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
+		WARNING("USB host won't detect disconnect!\n");
+	udc->suspended = 1;
+
+	local_irq_save(flags);
+	pullup(udc);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static int pxa25x_udc_resume(struct platform_device *dev)
+{
+	struct pxa25x_udc	*udc = platform_get_drvdata(dev);
+	unsigned long flags;
+
+	udc->suspended = 0;
+	local_irq_save(flags);
+	pullup(udc);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+#else
+#define	pxa25x_udc_suspend	NULL
+#define	pxa25x_udc_resume	NULL
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static struct platform_driver udc_driver = {
+	.shutdown	= pxa25x_udc_shutdown,
+	.remove		= __exit_p(pxa25x_udc_remove),
+	.suspend	= pxa25x_udc_suspend,
+	.resume		= pxa25x_udc_resume,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "pxa25x-udc",
+	},
+};
+
+static int __init udc_init(void)
+{
+	pr_info("%s: version %s\n", driver_name, DRIVER_VERSION);
+	return platform_driver_probe(&udc_driver, pxa25x_udc_probe);
+}
+module_init(udc_init);
+
+static void __exit udc_exit(void)
+{
+	platform_driver_unregister(&udc_driver);
+}
+module_exit(udc_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Frank Becker, Robert Schwebel, David Brownell");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa25x-udc");
diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h
new file mode 100644
index 0000000..1d51aa2
--- /dev/null
+++ b/drivers/usb/gadget/pxa25x_udc.h
@@ -0,0 +1,266 @@
+/*
+ * Intel PXA25x on-chip full speed USB device controller
+ *
+ * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ * Copyright (C) 2003 David Brownell
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __LINUX_USB_GADGET_PXA25X_H
+#define __LINUX_USB_GADGET_PXA25X_H
+
+#include <linux/types.h>
+
+/*-------------------------------------------------------------------------*/
+
+/* pxa25x has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */
+#define UFNRH_SIR	(1 << 7)	/* SOF interrupt request */
+#define UFNRH_SIM	(1 << 6)	/* SOF interrupt mask */
+#define UFNRH_IPE14	(1 << 5)	/* ISO packet error, ep14 */
+#define UFNRH_IPE9	(1 << 4)	/* ISO packet error, ep9 */
+#define UFNRH_IPE4	(1 << 3)	/* ISO packet error, ep4 */
+
+/* pxa255 has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */
+#define	UDCCFR		UDC_RES2	/* UDC Control Function Register */
+#define UDCCFR_AREN	(1 << 7)	/* ACK response enable (now) */
+#define UDCCFR_ACM	(1 << 2)	/* ACK control mode (wait for AREN) */
+
+/* latest pxa255 errata define new "must be one" bits in UDCCFR */
+#define	UDCCFR_MB1	(0xff & ~(UDCCFR_AREN|UDCCFR_ACM))
+
+/*-------------------------------------------------------------------------*/
+
+struct pxa25x_udc;
+
+struct pxa25x_ep {
+	struct usb_ep				ep;
+	struct pxa25x_udc			*dev;
+
+	const struct usb_endpoint_descriptor	*desc;
+	struct list_head			queue;
+	unsigned long				pio_irqs;
+
+	unsigned short				fifo_size;
+	u8					bEndpointAddress;
+	u8					bmAttributes;
+
+	unsigned				stopped : 1;
+	unsigned				dma_fixup : 1;
+
+	/* UDCCS = UDC Control/Status for this EP
+	 * UBCR = UDC Byte Count Remaining (contents of OUT fifo)
+	 * UDDR = UDC Endpoint Data Register (the fifo)
+	 * DRCM = DMA Request Channel Map
+	 */
+	volatile u32				*reg_udccs;
+	volatile u32				*reg_ubcr;
+	volatile u32				*reg_uddr;
+};
+
+struct pxa25x_request {
+	struct usb_request			req;
+	struct list_head			queue;
+};
+
+enum ep0_state {
+	EP0_IDLE,
+	EP0_IN_DATA_PHASE,
+	EP0_OUT_DATA_PHASE,
+	EP0_END_XFER,
+	EP0_STALL,
+};
+
+#define EP0_FIFO_SIZE	((unsigned)16)
+#define BULK_FIFO_SIZE	((unsigned)64)
+#define ISO_FIFO_SIZE	((unsigned)256)
+#define INT_FIFO_SIZE	((unsigned)8)
+
+struct udc_stats {
+	struct ep0stats {
+		unsigned long		ops;
+		unsigned long		bytes;
+	} read, write;
+	unsigned long			irqs;
+};
+
+#ifdef CONFIG_USB_PXA25X_SMALL
+/* when memory's tight, SMALL config saves code+data.  */
+#define	PXA_UDC_NUM_ENDPOINTS	3
+#endif
+
+#ifndef	PXA_UDC_NUM_ENDPOINTS
+#define	PXA_UDC_NUM_ENDPOINTS	16
+#endif
+
+struct pxa25x_udc {
+	struct usb_gadget			gadget;
+	struct usb_gadget_driver		*driver;
+
+	enum ep0_state				ep0state;
+	struct udc_stats			stats;
+	unsigned				got_irq : 1,
+						vbus : 1,
+						pullup : 1,
+						has_cfr : 1,
+						req_pending : 1,
+						req_std : 1,
+						req_config : 1,
+						suspended : 1,
+						active : 1;
+
+#define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200))
+	struct timer_list			timer;
+
+	struct device				*dev;
+	struct clk				*clk;
+	struct pxa2xx_udc_mach_info		*mach;
+	u64					dma_mask;
+	struct pxa25x_ep			ep [PXA_UDC_NUM_ENDPOINTS];
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+	struct dentry				*debugfs_udc;
+#endif
+};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_LUBBOCK
+#include <mach/lubbock.h>
+/* lubbock can also report usb connect/disconnect irqs */
+#endif
+
+static struct pxa25x_udc *the_controller;
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Debugging support vanishes in non-debug builds.  DBG_NORMAL should be
+ * mostly silent during normal use/testing, with no timing side-effects.
+ */
+#define DBG_NORMAL	1	/* error paths, device state transitions */
+#define DBG_VERBOSE	2	/* add some success path trace info */
+#define DBG_NOISY	3	/* ... even more: request level */
+#define DBG_VERY_NOISY	4	/* ... even more: packet level */
+
+#define DMSG(stuff...)	pr_debug("udc: " stuff)
+
+#ifdef DEBUG
+
+static int is_vbus_present(void);
+
+static const char *state_name[] = {
+	"EP0_IDLE",
+	"EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE",
+	"EP0_END_XFER", "EP0_STALL"
+};
+
+#ifdef VERBOSE_DEBUG
+#    define UDC_DEBUG DBG_VERBOSE
+#else
+#    define UDC_DEBUG DBG_NORMAL
+#endif
+
+static void __maybe_unused
+dump_udccr(const char *label)
+{
+	u32	udccr = UDCCR;
+	DMSG("%s %02X =%s%s%s%s%s%s%s%s\n",
+		label, udccr,
+		(udccr & UDCCR_REM) ? " rem" : "",
+		(udccr & UDCCR_RSTIR) ? " rstir" : "",
+		(udccr & UDCCR_SRM) ? " srm" : "",
+		(udccr & UDCCR_SUSIR) ? " susir" : "",
+		(udccr & UDCCR_RESIR) ? " resir" : "",
+		(udccr & UDCCR_RSM) ? " rsm" : "",
+		(udccr & UDCCR_UDA) ? " uda" : "",
+		(udccr & UDCCR_UDE) ? " ude" : "");
+}
+
+static void __maybe_unused
+dump_udccs0(const char *label)
+{
+	u32		udccs0 = UDCCS0;
+
+	DMSG("%s %s %02X =%s%s%s%s%s%s%s%s\n",
+		label, state_name[the_controller->ep0state], udccs0,
+		(udccs0 & UDCCS0_SA) ? " sa" : "",
+		(udccs0 & UDCCS0_RNE) ? " rne" : "",
+		(udccs0 & UDCCS0_FST) ? " fst" : "",
+		(udccs0 & UDCCS0_SST) ? " sst" : "",
+		(udccs0 & UDCCS0_DRWF) ? " dwrf" : "",
+		(udccs0 & UDCCS0_FTF) ? " ftf" : "",
+		(udccs0 & UDCCS0_IPR) ? " ipr" : "",
+		(udccs0 & UDCCS0_OPR) ? " opr" : "");
+}
+
+static void __maybe_unused
+dump_state(struct pxa25x_udc *dev)
+{
+	u32		tmp;
+	unsigned	i;
+
+	DMSG("%s %s, uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
+		is_vbus_present() ? "host " : "disconnected",
+		state_name[dev->ep0state],
+		UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
+	dump_udccr("udccr");
+	if (dev->has_cfr) {
+		tmp = UDCCFR;
+		DMSG("udccfr %02X =%s%s\n", tmp,
+			(tmp & UDCCFR_AREN) ? " aren" : "",
+			(tmp & UDCCFR_ACM) ? " acm" : "");
+	}
+
+	if (!dev->driver) {
+		DMSG("no gadget driver bound\n");
+		return;
+	} else
+		DMSG("ep0 driver '%s'\n", dev->driver->driver.name);
+
+	if (!is_vbus_present())
+		return;
+
+	dump_udccs0 ("udccs0");
+	DMSG("ep0 IN %lu/%lu, OUT %lu/%lu\n",
+		dev->stats.write.bytes, dev->stats.write.ops,
+		dev->stats.read.bytes, dev->stats.read.ops);
+
+	for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) {
+		if (dev->ep [i].desc == NULL)
+			continue;
+		DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccs);
+	}
+}
+
+#else
+
+#define	dump_udccr(x)	do{}while(0)
+#define	dump_udccs0(x)	do{}while(0)
+#define	dump_state(x)	do{}while(0)
+
+#define UDC_DEBUG ((unsigned)0)
+
+#endif
+
+#define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
+
+#define ERR(stuff...)		pr_err("udc: " stuff)
+#define WARNING(stuff...)	pr_warning("udc: " stuff)
+#define INFO(stuff...)		pr_info("udc: " stuff)
+
+
+#endif /* __LINUX_USB_GADGET_PXA25X_H */
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index e02bfd4..7cbc78a 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -33,13 +33,13 @@
 #include <linux/irq.h>
 
 #include <asm/byteorder.h>
-#include <asm/hardware.h>
+#include <mach/hardware.h>
 
 #include <linux/usb.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-
-#include <asm/arch/udc.h>
+#include <mach/pxa2xx-regs.h> /* FIXME: for PSSR */
+#include <mach/udc.h>
 
 #include "pxa27x_udc.h"
 
@@ -1575,7 +1575,6 @@ static void udc_enable(struct pxa_udc *udc)
 {
 	udc_writel(udc, UDCICR0, 0);
 	udc_writel(udc, UDCICR1, 0);
-	udc_writel(udc, UP2OCR, UP2OCR_HXOE);
 	udc_clear_mask_UDCCR(udc, UDCCR_UDE);
 
 	clk_enable(udc->clk);
@@ -1623,7 +1622,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
 	struct pxa_udc *udc = the_controller;
 	int retval;
 
-	if (!driver || driver->speed != USB_SPEED_FULL || !driver->bind
+	if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind
 			|| !driver->disconnect || !driver->setup)
 		return -EINVAL;
 	if (!udc)
@@ -2360,18 +2359,19 @@ static int pxa_udc_resume(struct platform_device *_dev)
 	 * Software must configure the USB OTG pad, UDC, and UHC
 	 * to the state they were in before entering sleep mode.
 	 */
-	PSSR |= PSSR_OTGPH;
+	if (cpu_is_pxa27x())
+		PSSR |= PSSR_OTGPH;
 
 	return 0;
 }
 #endif
 
 /* work with hotplug and coldplug */
-MODULE_ALIAS("platform:pxa2xx-udc");
+MODULE_ALIAS("platform:pxa27x-udc");
 
 static struct platform_driver udc_driver = {
 	.driver		= {
-		.name	= "pxa2xx-udc",
+		.name	= "pxa27x-udc",
 		.owner	= THIS_MODULE,
 	},
 	.remove		= __exit_p(pxa_udc_remove),
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h
index 97453db..1d1b793 100644
--- a/drivers/usb/gadget/pxa27x_udc.h
+++ b/drivers/usb/gadget/pxa27x_udc.h
@@ -484,12 +484,4 @@ static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget)
 #define ep_warn(ep, fmt, arg...) \
 	dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg)
 
-/*
- * Cannot include pxa-regs.h, as register names are similar.
- * So PSSR is redefined here. This should be removed once UDC registers will
- * be gone from pxa-regs.h.
- */
-#define PSSR		__REG(0x40F00004)	/* Power Manager Sleep Status */
-#define PSSR_OTGPH	(1 << 6)		/* OTG Peripheral Hold */
-
 #endif /* __LINUX_USB_GADGET_PXA27X_H */
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
deleted file mode 100644
index 08f699b..0000000
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ /dev/null
@@ -1,2383 +0,0 @@
-/*
- * linux/drivers/usb/gadget/pxa2xx_udc.c
- * Intel PXA25x and IXP4xx on-chip full speed USB device controllers
- *
- * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker)
- * Copyright (C) 2003 Robert Schwebel, Pengutronix
- * Copyright (C) 2003 Benedikt Spranger, Pengutronix
- * Copyright (C) 2003 David Brownell
- * Copyright (C) 2003 Joshua Wise
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-/* #define VERBOSE_DEBUG */
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/mm.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/irq.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/seq_file.h>
-#include <linux/debugfs.h>
-
-#include <asm/byteorder.h>
-#include <asm/dma.h>
-#include <asm/gpio.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <asm/unaligned.h>
-#include <asm/hardware.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include <asm/mach/udc_pxa2xx.h>
-
-
-/*
- * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x
- * series processors.  The UDC for the IXP 4xx series is very similar.
- * There are fifteen endpoints, in addition to ep0.
- *
- * Such controller drivers work with a gadget driver.  The gadget driver
- * returns descriptors, implements configuration and data protocols used
- * by the host to interact with this device, and allocates endpoints to
- * the different protocol interfaces.  The controller driver virtualizes
- * usb hardware so that the gadget drivers will be more portable.
- *
- * This UDC hardware wants to implement a bit too much USB protocol, so
- * it constrains the sorts of USB configuration change events that work.
- * The errata for these chips are misleading; some "fixed" bugs from
- * pxa250 a0/a1 b0/b1/b2 sure act like they're still there.
- *
- * Note that the UDC hardware supports DMA (except on IXP) but that's
- * not used here.  IN-DMA (to host) is simple enough, when the data is
- * suitably aligned (16 bytes) ... the network stack doesn't do that,
- * other software can.  OUT-DMA is buggy in most chip versions, as well
- * as poorly designed (data toggle not automatic).  So this driver won't
- * bother using DMA.  (Mostly-working IN-DMA support was available in
- * kernels before 2.6.23, but was never enabled or well tested.)
- */
-
-#define	DRIVER_VERSION	"30-June-2007"
-#define	DRIVER_DESC	"PXA 25x USB Device Controller driver"
-
-
-static const char driver_name [] = "pxa2xx_udc";
-
-static const char ep0name [] = "ep0";
-
-
-#ifdef CONFIG_ARCH_IXP4XX
-
-/* cpu-specific register addresses are compiled in to this code */
-#ifdef CONFIG_ARCH_PXA
-#error "Can't configure both IXP and PXA"
-#endif
-
-/* IXP doesn't yet support <linux/clk.h> */
-#define clk_get(dev,name)	NULL
-#define clk_enable(clk)		do { } while (0)
-#define clk_disable(clk)	do { } while (0)
-#define clk_put(clk)		do { } while (0)
-
-#endif
-
-#include "pxa2xx_udc.h"
-
-
-#ifdef	CONFIG_USB_PXA2XX_SMALL
-#define SIZE_STR	" (small)"
-#else
-#define SIZE_STR	""
-#endif
-
-/* ---------------------------------------------------------------------------
- *	endpoint related parts of the api to the usb controller hardware,
- *	used by gadget driver; and the inner talker-to-hardware core.
- * ---------------------------------------------------------------------------
- */
-
-static void pxa2xx_ep_fifo_flush (struct usb_ep *ep);
-static void nuke (struct pxa2xx_ep *, int status);
-
-/* one GPIO should be used to detect VBUS from the host */
-static int is_vbus_present(void)
-{
-	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
-
-	if (mach->gpio_vbus) {
-		int value = gpio_get_value(mach->gpio_vbus);
-		return mach->gpio_vbus_inverted ? !value : value;
-	}
-	if (mach->udc_is_connected)
-		return mach->udc_is_connected();
-	return 1;
-}
-
-/* one GPIO should control a D+ pullup, so host sees this device (or not) */
-static void pullup_off(void)
-{
-	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
-
-	if (mach->gpio_pullup)
-		gpio_set_value(mach->gpio_pullup, 0);
-	else if (mach->udc_command)
-		mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
-}
-
-static void pullup_on(void)
-{
-	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
-
-	if (mach->gpio_pullup)
-		gpio_set_value(mach->gpio_pullup, 1);
-	else if (mach->udc_command)
-		mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
-}
-
-static void pio_irq_enable(int bEndpointAddress)
-{
-        bEndpointAddress &= 0xf;
-        if (bEndpointAddress < 8)
-                UICR0 &= ~(1 << bEndpointAddress);
-        else {
-                bEndpointAddress -= 8;
-                UICR1 &= ~(1 << bEndpointAddress);
-	}
-}
-
-static void pio_irq_disable(int bEndpointAddress)
-{
-        bEndpointAddress &= 0xf;
-        if (bEndpointAddress < 8)
-                UICR0 |= 1 << bEndpointAddress;
-        else {
-                bEndpointAddress -= 8;
-                UICR1 |= 1 << bEndpointAddress;
-        }
-}
-
-/* The UDCCR reg contains mask and interrupt status bits,
- * so using '|=' isn't safe as it may ack an interrupt.
- */
-#define UDCCR_MASK_BITS         (UDCCR_REM | UDCCR_SRM | UDCCR_UDE)
-
-static inline void udc_set_mask_UDCCR(int mask)
-{
-	UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS);
-}
-
-static inline void udc_clear_mask_UDCCR(int mask)
-{
-	UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS);
-}
-
-static inline void udc_ack_int_UDCCR(int mask)
-{
-	/* udccr contains the bits we dont want to change */
-	__u32 udccr = UDCCR & UDCCR_MASK_BITS;
-
-	UDCCR = udccr | (mask & ~UDCCR_MASK_BITS);
-}
-
-/*
- * endpoint enable/disable
- *
- * we need to verify the descriptors used to enable endpoints.  since pxa2xx
- * endpoint configurations are fixed, and are pretty much always enabled,
- * there's not a lot to manage here.
- *
- * because pxa2xx can't selectively initialize bulk (or interrupt) endpoints,
- * (resetting endpoint halt and toggle), SET_INTERFACE is unusable except
- * for a single interface (with only the default altsetting) and for gadget
- * drivers that don't halt endpoints (not reset by set_interface).  that also
- * means that if you use ISO, you must violate the USB spec rule that all
- * iso endpoints must be in non-default altsettings.
- */
-static int pxa2xx_ep_enable (struct usb_ep *_ep,
-		const struct usb_endpoint_descriptor *desc)
-{
-	struct pxa2xx_ep        *ep;
-	struct pxa2xx_udc       *dev;
-
-	ep = container_of (_ep, struct pxa2xx_ep, ep);
-	if (!_ep || !desc || ep->desc || _ep->name == ep0name
-			|| desc->bDescriptorType != USB_DT_ENDPOINT
-			|| ep->bEndpointAddress != desc->bEndpointAddress
-			|| ep->fifo_size < le16_to_cpu
-						(desc->wMaxPacketSize)) {
-		DMSG("%s, bad ep or descriptor\n", __func__);
-		return -EINVAL;
-	}
-
-	/* xfer types must match, except that interrupt ~= bulk */
-	if (ep->bmAttributes != desc->bmAttributes
-			&& ep->bmAttributes != USB_ENDPOINT_XFER_BULK
-			&& desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
-		DMSG("%s, %s type mismatch\n", __func__, _ep->name);
-		return -EINVAL;
-	}
-
-	/* hardware _could_ do smaller, but driver doesn't */
-	if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
-				&& le16_to_cpu (desc->wMaxPacketSize)
-						!= BULK_FIFO_SIZE)
-			|| !desc->wMaxPacketSize) {
-		DMSG("%s, bad %s maxpacket\n", __func__, _ep->name);
-		return -ERANGE;
-	}
-
-	dev = ep->dev;
-	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
-		DMSG("%s, bogus device state\n", __func__);
-		return -ESHUTDOWN;
-	}
-
-	ep->desc = desc;
-	ep->stopped = 0;
-	ep->pio_irqs = 0;
-	ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize);
-
-	/* flush fifo (mostly for OUT buffers) */
-	pxa2xx_ep_fifo_flush (_ep);
-
-	/* ... reset halt state too, if we could ... */
-
-	DBG(DBG_VERBOSE, "enabled %s\n", _ep->name);
-	return 0;
-}
-
-static int pxa2xx_ep_disable (struct usb_ep *_ep)
-{
-	struct pxa2xx_ep	*ep;
-	unsigned long		flags;
-
-	ep = container_of (_ep, struct pxa2xx_ep, ep);
-	if (!_ep || !ep->desc) {
-		DMSG("%s, %s not enabled\n", __func__,
-			_ep ? ep->ep.name : NULL);
-		return -EINVAL;
-	}
-	local_irq_save(flags);
-
-	nuke (ep, -ESHUTDOWN);
-
-	/* flush fifo (mostly for IN buffers) */
-	pxa2xx_ep_fifo_flush (_ep);
-
-	ep->desc = NULL;
-	ep->stopped = 1;
-
-	local_irq_restore(flags);
-	DBG(DBG_VERBOSE, "%s disabled\n", _ep->name);
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* for the pxa2xx, these can just wrap kmalloc/kfree.  gadget drivers
- * must still pass correctly initialized endpoints, since other controller
- * drivers may care about how it's currently set up (dma issues etc).
- */
-
-/*
- *	pxa2xx_ep_alloc_request - allocate a request data structure
- */
-static struct usb_request *
-pxa2xx_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
-{
-	struct pxa2xx_request *req;
-
-	req = kzalloc(sizeof(*req), gfp_flags);
-	if (!req)
-		return NULL;
-
-	INIT_LIST_HEAD (&req->queue);
-	return &req->req;
-}
-
-
-/*
- *	pxa2xx_ep_free_request - deallocate a request data structure
- */
-static void
-pxa2xx_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
-{
-	struct pxa2xx_request	*req;
-
-	req = container_of (_req, struct pxa2xx_request, req);
-	WARN_ON (!list_empty (&req->queue));
-	kfree(req);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- *	done - retire a request; caller blocked irqs
- */
-static void done(struct pxa2xx_ep *ep, struct pxa2xx_request *req, int status)
-{
-	unsigned		stopped = ep->stopped;
-
-	list_del_init(&req->queue);
-
-	if (likely (req->req.status == -EINPROGRESS))
-		req->req.status = status;
-	else
-		status = req->req.status;
-
-	if (status && status != -ESHUTDOWN)
-		DBG(DBG_VERBOSE, "complete %s req %p stat %d len %u/%u\n",
-			ep->ep.name, &req->req, status,
-			req->req.actual, req->req.length);
-
-	/* don't modify queue heads during completion callback */
-	ep->stopped = 1;
-	req->req.complete(&ep->ep, &req->req);
-	ep->stopped = stopped;
-}
-
-
-static inline void ep0_idle (struct pxa2xx_udc *dev)
-{
-	dev->ep0state = EP0_IDLE;
-}
-
-static int
-write_packet(volatile u32 *uddr, struct pxa2xx_request *req, unsigned max)
-{
-	u8		*buf;
-	unsigned	length, count;
-
-	buf = req->req.buf + req->req.actual;
-	prefetch(buf);
-
-	/* how big will this packet be? */
-	length = min(req->req.length - req->req.actual, max);
-	req->req.actual += length;
-
-	count = length;
-	while (likely(count--))
-		*uddr = *buf++;
-
-	return length;
-}
-
-/*
- * write to an IN endpoint fifo, as many packets as possible.
- * irqs will use this to write the rest later.
- * caller guarantees at least one packet buffer is ready (or a zlp).
- */
-static int
-write_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
-{
-	unsigned		max;
-
-	max = le16_to_cpu(ep->desc->wMaxPacketSize);
-	do {
-		unsigned	count;
-		int		is_last, is_short;
-
-		count = write_packet(ep->reg_uddr, req, max);
-
-		/* last packet is usually short (or a zlp) */
-		if (unlikely (count != max))
-			is_last = is_short = 1;
-		else {
-			if (likely(req->req.length != req->req.actual)
-					|| req->req.zero)
-				is_last = 0;
-			else
-				is_last = 1;
-			/* interrupt/iso maxpacket may not fill the fifo */
-			is_short = unlikely (max < ep->fifo_size);
-		}
-
-		DBG(DBG_VERY_NOISY, "wrote %s %d bytes%s%s %d left %p\n",
-			ep->ep.name, count,
-			is_last ? "/L" : "", is_short ? "/S" : "",
-			req->req.length - req->req.actual, req);
-
-		/* let loose that packet. maybe try writing another one,
-		 * double buffering might work.  TSP, TPC, and TFS
-		 * bit values are the same for all normal IN endpoints.
-		 */
-		*ep->reg_udccs = UDCCS_BI_TPC;
-		if (is_short)
-			*ep->reg_udccs = UDCCS_BI_TSP;
-
-		/* requests complete when all IN data is in the FIFO */
-		if (is_last) {
-			done (ep, req, 0);
-			if (list_empty(&ep->queue))
-				pio_irq_disable (ep->bEndpointAddress);
-			return 1;
-		}
-
-		// TODO experiment: how robust can fifo mode tweaking be?
-		// double buffering is off in the default fifo mode, which
-		// prevents TFS from being set here.
-
-	} while (*ep->reg_udccs & UDCCS_BI_TFS);
-	return 0;
-}
-
-/* caller asserts req->pending (ep0 irq status nyet cleared); starts
- * ep0 data stage.  these chips want very simple state transitions.
- */
-static inline
-void ep0start(struct pxa2xx_udc *dev, u32 flags, const char *tag)
-{
-	UDCCS0 = flags|UDCCS0_SA|UDCCS0_OPR;
-	USIR0 = USIR0_IR0;
-	dev->req_pending = 0;
-	DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n",
-		__func__, tag, UDCCS0, flags);
-}
-
-static int
-write_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
-{
-	unsigned	count;
-	int		is_short;
-
-	count = write_packet(&UDDR0, req, EP0_FIFO_SIZE);
-	ep->dev->stats.write.bytes += count;
-
-	/* last packet "must be" short (or a zlp) */
-	is_short = (count != EP0_FIFO_SIZE);
-
-	DBG(DBG_VERY_NOISY, "ep0in %d bytes %d left %p\n", count,
-		req->req.length - req->req.actual, req);
-
-	if (unlikely (is_short)) {
-		if (ep->dev->req_pending)
-			ep0start(ep->dev, UDCCS0_IPR, "short IN");
-		else
-			UDCCS0 = UDCCS0_IPR;
-
-		count = req->req.length;
-		done (ep, req, 0);
-		ep0_idle(ep->dev);
-#ifndef CONFIG_ARCH_IXP4XX
-#if 1
-		/* This seems to get rid of lost status irqs in some cases:
-		 * host responds quickly, or next request involves config
-		 * change automagic, or should have been hidden, or ...
-		 *
-		 * FIXME get rid of all udelays possible...
-		 */
-		if (count >= EP0_FIFO_SIZE) {
-			count = 100;
-			do {
-				if ((UDCCS0 & UDCCS0_OPR) != 0) {
-					/* clear OPR, generate ack */
-					UDCCS0 = UDCCS0_OPR;
-					break;
-				}
-				count--;
-				udelay(1);
-			} while (count);
-		}
-#endif
-#endif
-	} else if (ep->dev->req_pending)
-		ep0start(ep->dev, 0, "IN");
-	return is_short;
-}
-
-
-/*
- * read_fifo -  unload packet(s) from the fifo we use for usb OUT
- * transfers and put them into the request.  caller should have made
- * sure there's at least one packet ready.
- *
- * returns true if the request completed because of short packet or the
- * request buffer having filled (and maybe overran till end-of-packet).
- */
-static int
-read_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
-{
-	for (;;) {
-		u32		udccs;
-		u8		*buf;
-		unsigned	bufferspace, count, is_short;
-
-		/* make sure there's a packet in the FIFO.
-		 * UDCCS_{BO,IO}_RPC are all the same bit value.
-		 * UDCCS_{BO,IO}_RNE are all the same bit value.
-		 */
-		udccs = *ep->reg_udccs;
-		if (unlikely ((udccs & UDCCS_BO_RPC) == 0))
-			break;
-		buf = req->req.buf + req->req.actual;
-		prefetchw(buf);
-		bufferspace = req->req.length - req->req.actual;
-
-		/* read all bytes from this packet */
-		if (likely (udccs & UDCCS_BO_RNE)) {
-			count = 1 + (0x0ff & *ep->reg_ubcr);
-			req->req.actual += min (count, bufferspace);
-		} else /* zlp */
-			count = 0;
-		is_short = (count < ep->ep.maxpacket);
-		DBG(DBG_VERY_NOISY, "read %s %02x, %d bytes%s req %p %d/%d\n",
-			ep->ep.name, udccs, count,
-			is_short ? "/S" : "",
-			req, req->req.actual, req->req.length);
-		while (likely (count-- != 0)) {
-			u8	byte = (u8) *ep->reg_uddr;
-
-			if (unlikely (bufferspace == 0)) {
-				/* this happens when the driver's buffer
-				 * is smaller than what the host sent.
-				 * discard the extra data.
-				 */
-				if (req->req.status != -EOVERFLOW)
-					DMSG("%s overflow %d\n",
-						ep->ep.name, count);
-				req->req.status = -EOVERFLOW;
-			} else {
-				*buf++ = byte;
-				bufferspace--;
-			}
-		}
-		*ep->reg_udccs =  UDCCS_BO_RPC;
-		/* RPC/RSP/RNE could now reflect the other packet buffer */
-
-		/* iso is one request per packet */
-		if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
-			if (udccs & UDCCS_IO_ROF)
-				req->req.status = -EHOSTUNREACH;
-			/* more like "is_done" */
-			is_short = 1;
-		}
-
-		/* completion */
-		if (is_short || req->req.actual == req->req.length) {
-			done (ep, req, 0);
-			if (list_empty(&ep->queue))
-				pio_irq_disable (ep->bEndpointAddress);
-			return 1;
-		}
-
-		/* finished that packet.  the next one may be waiting... */
-	}
-	return 0;
-}
-
-/*
- * special ep0 version of the above.  no UBCR0 or double buffering; status
- * handshaking is magic.  most device protocols don't need control-OUT.
- * CDC vendor commands (and RNDIS), mass storage CB/CBI, and some other
- * protocols do use them.
- */
-static int
-read_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
-{
-	u8		*buf, byte;
-	unsigned	bufferspace;
-
-	buf = req->req.buf + req->req.actual;
-	bufferspace = req->req.length - req->req.actual;
-
-	while (UDCCS0 & UDCCS0_RNE) {
-		byte = (u8) UDDR0;
-
-		if (unlikely (bufferspace == 0)) {
-			/* this happens when the driver's buffer
-			 * is smaller than what the host sent.
-			 * discard the extra data.
-			 */
-			if (req->req.status != -EOVERFLOW)
-				DMSG("%s overflow\n", ep->ep.name);
-			req->req.status = -EOVERFLOW;
-		} else {
-			*buf++ = byte;
-			req->req.actual++;
-			bufferspace--;
-		}
-	}
-
-	UDCCS0 = UDCCS0_OPR | UDCCS0_IPR;
-
-	/* completion */
-	if (req->req.actual >= req->req.length)
-		return 1;
-
-	/* finished that packet.  the next one may be waiting... */
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
-{
-	struct pxa2xx_request	*req;
-	struct pxa2xx_ep	*ep;
-	struct pxa2xx_udc	*dev;
-	unsigned long		flags;
-
-	req = container_of(_req, struct pxa2xx_request, req);
-	if (unlikely (!_req || !_req->complete || !_req->buf
-			|| !list_empty(&req->queue))) {
-		DMSG("%s, bad params\n", __func__);
-		return -EINVAL;
-	}
-
-	ep = container_of(_ep, struct pxa2xx_ep, ep);
-	if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
-		DMSG("%s, bad ep\n", __func__);
-		return -EINVAL;
-	}
-
-	dev = ep->dev;
-	if (unlikely (!dev->driver
-			|| dev->gadget.speed == USB_SPEED_UNKNOWN)) {
-		DMSG("%s, bogus device state\n", __func__);
-		return -ESHUTDOWN;
-	}
-
-	/* iso is always one packet per request, that's the only way
-	 * we can report per-packet status.  that also helps with dma.
-	 */
-	if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
-			&& req->req.length > le16_to_cpu
-						(ep->desc->wMaxPacketSize)))
-		return -EMSGSIZE;
-
-	DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n",
-		_ep->name, _req, _req->length, _req->buf);
-
-	local_irq_save(flags);
-
-	_req->status = -EINPROGRESS;
-	_req->actual = 0;
-
-	/* kickstart this i/o queue? */
-	if (list_empty(&ep->queue) && !ep->stopped) {
-		if (ep->desc == NULL/* ep0 */) {
-			unsigned	length = _req->length;
-
-			switch (dev->ep0state) {
-			case EP0_IN_DATA_PHASE:
-				dev->stats.write.ops++;
-				if (write_ep0_fifo(ep, req))
-					req = NULL;
-				break;
-
-			case EP0_OUT_DATA_PHASE:
-				dev->stats.read.ops++;
-				/* messy ... */
-				if (dev->req_config) {
-					DBG(DBG_VERBOSE, "ep0 config ack%s\n",
-						dev->has_cfr ?  "" : " raced");
-					if (dev->has_cfr)
-						UDCCFR = UDCCFR_AREN|UDCCFR_ACM
-							|UDCCFR_MB1;
-					done(ep, req, 0);
-					dev->ep0state = EP0_END_XFER;
-					local_irq_restore (flags);
-					return 0;
-				}
-				if (dev->req_pending)
-					ep0start(dev, UDCCS0_IPR, "OUT");
-				if (length == 0 || ((UDCCS0 & UDCCS0_RNE) != 0
-						&& read_ep0_fifo(ep, req))) {
-					ep0_idle(dev);
-					done(ep, req, 0);
-					req = NULL;
-				}
-				break;
-
-			default:
-				DMSG("ep0 i/o, odd state %d\n", dev->ep0state);
-				local_irq_restore (flags);
-				return -EL2HLT;
-			}
-		/* can the FIFO can satisfy the request immediately? */
-		} else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
-			if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0
-					&& write_fifo(ep, req))
-				req = NULL;
-		} else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0
-				&& read_fifo(ep, req)) {
-			req = NULL;
-		}
-
-		if (likely (req && ep->desc))
-			pio_irq_enable(ep->bEndpointAddress);
-	}
-
-	/* pio or dma irq handler advances the queue. */
-	if (likely(req != NULL))
-		list_add_tail(&req->queue, &ep->queue);
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-
-/*
- *	nuke - dequeue ALL requests
- */
-static void nuke(struct pxa2xx_ep *ep, int status)
-{
-	struct pxa2xx_request *req;
-
-	/* called with irqs blocked */
-	while (!list_empty(&ep->queue)) {
-		req = list_entry(ep->queue.next,
-				struct pxa2xx_request,
-				queue);
-		done(ep, req, status);
-	}
-	if (ep->desc)
-		pio_irq_disable (ep->bEndpointAddress);
-}
-
-
-/* dequeue JUST ONE request */
-static int pxa2xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-	struct pxa2xx_ep	*ep;
-	struct pxa2xx_request	*req;
-	unsigned long		flags;
-
-	ep = container_of(_ep, struct pxa2xx_ep, ep);
-	if (!_ep || ep->ep.name == ep0name)
-		return -EINVAL;
-
-	local_irq_save(flags);
-
-	/* make sure it's actually queued on this endpoint */
-	list_for_each_entry (req, &ep->queue, queue) {
-		if (&req->req == _req)
-			break;
-	}
-	if (&req->req != _req) {
-		local_irq_restore(flags);
-		return -EINVAL;
-	}
-
-	done(ep, req, -ECONNRESET);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int pxa2xx_ep_set_halt(struct usb_ep *_ep, int value)
-{
-	struct pxa2xx_ep	*ep;
-	unsigned long		flags;
-
-	ep = container_of(_ep, struct pxa2xx_ep, ep);
-	if (unlikely (!_ep
-			|| (!ep->desc && ep->ep.name != ep0name))
-			|| ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
-		DMSG("%s, bad ep\n", __func__);
-		return -EINVAL;
-	}
-	if (value == 0) {
-		/* this path (reset toggle+halt) is needed to implement
-		 * SET_INTERFACE on normal hardware.  but it can't be
-		 * done from software on the PXA UDC, and the hardware
-		 * forgets to do it as part of SET_INTERFACE automagic.
-		 */
-		DMSG("only host can clear %s halt\n", _ep->name);
-		return -EROFS;
-	}
-
-	local_irq_save(flags);
-
-	if ((ep->bEndpointAddress & USB_DIR_IN) != 0
-			&& ((*ep->reg_udccs & UDCCS_BI_TFS) == 0
-			   || !list_empty(&ep->queue))) {
-		local_irq_restore(flags);
-		return -EAGAIN;
-	}
-
-	/* FST bit is the same for control, bulk in, bulk out, interrupt in */
-	*ep->reg_udccs = UDCCS_BI_FST|UDCCS_BI_FTF;
-
-	/* ep0 needs special care */
-	if (!ep->desc) {
-		start_watchdog(ep->dev);
-		ep->dev->req_pending = 0;
-		ep->dev->ep0state = EP0_STALL;
-
-	/* and bulk/intr endpoints like dropping stalls too */
-	} else {
-		unsigned i;
-		for (i = 0; i < 1000; i += 20) {
-			if (*ep->reg_udccs & UDCCS_BI_SST)
-				break;
-			udelay(20);
-		}
-	}
-	local_irq_restore(flags);
-
-	DBG(DBG_VERBOSE, "%s halt\n", _ep->name);
-	return 0;
-}
-
-static int pxa2xx_ep_fifo_status(struct usb_ep *_ep)
-{
-	struct pxa2xx_ep        *ep;
-
-	ep = container_of(_ep, struct pxa2xx_ep, ep);
-	if (!_ep) {
-		DMSG("%s, bad ep\n", __func__);
-		return -ENODEV;
-	}
-	/* pxa can't report unclaimed bytes from IN fifos */
-	if ((ep->bEndpointAddress & USB_DIR_IN) != 0)
-		return -EOPNOTSUPP;
-	if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN
-			|| (*ep->reg_udccs & UDCCS_BO_RFS) == 0)
-		return 0;
-	else
-		return (*ep->reg_ubcr & 0xfff) + 1;
-}
-
-static void pxa2xx_ep_fifo_flush(struct usb_ep *_ep)
-{
-	struct pxa2xx_ep        *ep;
-
-	ep = container_of(_ep, struct pxa2xx_ep, ep);
-	if (!_ep || ep->ep.name == ep0name || !list_empty(&ep->queue)) {
-		DMSG("%s, bad ep\n", __func__);
-		return;
-	}
-
-	/* toggle and halt bits stay unchanged */
-
-	/* for OUT, just read and discard the FIFO contents. */
-	if ((ep->bEndpointAddress & USB_DIR_IN) == 0) {
-		while (((*ep->reg_udccs) & UDCCS_BO_RNE) != 0)
-			(void) *ep->reg_uddr;
-		return;
-	}
-
-	/* most IN status is the same, but ISO can't stall */
-	*ep->reg_udccs = UDCCS_BI_TPC|UDCCS_BI_FTF|UDCCS_BI_TUR
-		| (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
-			? 0 : UDCCS_BI_SST;
-}
-
-
-static struct usb_ep_ops pxa2xx_ep_ops = {
-	.enable		= pxa2xx_ep_enable,
-	.disable	= pxa2xx_ep_disable,
-
-	.alloc_request	= pxa2xx_ep_alloc_request,
-	.free_request	= pxa2xx_ep_free_request,
-
-	.queue		= pxa2xx_ep_queue,
-	.dequeue	= pxa2xx_ep_dequeue,
-
-	.set_halt	= pxa2xx_ep_set_halt,
-	.fifo_status	= pxa2xx_ep_fifo_status,
-	.fifo_flush	= pxa2xx_ep_fifo_flush,
-};
-
-
-/* ---------------------------------------------------------------------------
- *	device-scoped parts of the api to the usb controller hardware
- * ---------------------------------------------------------------------------
- */
-
-static int pxa2xx_udc_get_frame(struct usb_gadget *_gadget)
-{
-	return ((UFNRH & 0x07) << 8) | (UFNRL & 0xff);
-}
-
-static int pxa2xx_udc_wakeup(struct usb_gadget *_gadget)
-{
-	/* host may not have enabled remote wakeup */
-	if ((UDCCS0 & UDCCS0_DRWF) == 0)
-		return -EHOSTUNREACH;
-	udc_set_mask_UDCCR(UDCCR_RSM);
-	return 0;
-}
-
-static void stop_activity(struct pxa2xx_udc *, struct usb_gadget_driver *);
-static void udc_enable (struct pxa2xx_udc *);
-static void udc_disable(struct pxa2xx_udc *);
-
-/* We disable the UDC -- and its 48 MHz clock -- whenever it's not
- * in active use.
- */
-static int pullup(struct pxa2xx_udc *udc)
-{
-	int is_active = udc->vbus && udc->pullup && !udc->suspended;
-	DMSG("%s\n", is_active ? "active" : "inactive");
-	if (is_active) {
-		if (!udc->active) {
-			udc->active = 1;
-			/* Enable clock for USB device */
-			clk_enable(udc->clk);
-			udc_enable(udc);
-		}
-	} else {
-		if (udc->active) {
-			if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
-				DMSG("disconnect %s\n", udc->driver
-					? udc->driver->driver.name
-					: "(no driver)");
-				stop_activity(udc, udc->driver);
-			}
-			udc_disable(udc);
-			/* Disable clock for USB device */
-			clk_disable(udc->clk);
-			udc->active = 0;
-		}
-
-	}
-	return 0;
-}
-
-/* VBUS reporting logically comes from a transceiver */
-static int pxa2xx_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
-{
-	struct pxa2xx_udc	*udc;
-
-	udc = container_of(_gadget, struct pxa2xx_udc, gadget);
-	udc->vbus = (is_active != 0);
-	DMSG("vbus %s\n", is_active ? "supplied" : "inactive");
-	pullup(udc);
-	return 0;
-}
-
-/* drivers may have software control over D+ pullup */
-static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active)
-{
-	struct pxa2xx_udc	*udc;
-
-	udc = container_of(_gadget, struct pxa2xx_udc, gadget);
-
-	/* not all boards support pullup control */
-	if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
-		return -EOPNOTSUPP;
-
-	udc->pullup = (is_active != 0);
-	pullup(udc);
-	return 0;
-}
-
-static const struct usb_gadget_ops pxa2xx_udc_ops = {
-	.get_frame	= pxa2xx_udc_get_frame,
-	.wakeup		= pxa2xx_udc_wakeup,
-	.vbus_session	= pxa2xx_udc_vbus_session,
-	.pullup		= pxa2xx_udc_pullup,
-
-	// .vbus_draw ... boards may consume current from VBUS, up to
-	// 100-500mA based on config.  the 500uA suspend ceiling means
-	// that exclusively vbus-powered PXA designs violate USB specs.
-};
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FS
-
-static int
-udc_seq_show(struct seq_file *m, void *_d)
-{
-	struct pxa2xx_udc	*dev = m->private;
-	unsigned long		flags;
-	int			i;
-	u32			tmp;
-
-	local_irq_save(flags);
-
-	/* basic device status */
-	seq_printf(m, DRIVER_DESC "\n"
-		"%s version: %s\nGadget driver: %s\nHost %s\n\n",
-		driver_name, DRIVER_VERSION SIZE_STR "(pio)",
-		dev->driver ? dev->driver->driver.name : "(none)",
-		is_vbus_present() ? "full speed" : "disconnected");
-
-	/* registers for device and ep0 */
-	seq_printf(m,
-		"uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
-		UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
-
-	tmp = UDCCR;
-	seq_printf(m,
-		"udccr %02X =%s%s%s%s%s%s%s%s\n", tmp,
-		(tmp & UDCCR_REM) ? " rem" : "",
-		(tmp & UDCCR_RSTIR) ? " rstir" : "",
-		(tmp & UDCCR_SRM) ? " srm" : "",
-		(tmp & UDCCR_SUSIR) ? " susir" : "",
-		(tmp & UDCCR_RESIR) ? " resir" : "",
-		(tmp & UDCCR_RSM) ? " rsm" : "",
-		(tmp & UDCCR_UDA) ? " uda" : "",
-		(tmp & UDCCR_UDE) ? " ude" : "");
-
-	tmp = UDCCS0;
-	seq_printf(m,
-		"udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp,
-		(tmp & UDCCS0_SA) ? " sa" : "",
-		(tmp & UDCCS0_RNE) ? " rne" : "",
-		(tmp & UDCCS0_FST) ? " fst" : "",
-		(tmp & UDCCS0_SST) ? " sst" : "",
-		(tmp & UDCCS0_DRWF) ? " dwrf" : "",
-		(tmp & UDCCS0_FTF) ? " ftf" : "",
-		(tmp & UDCCS0_IPR) ? " ipr" : "",
-		(tmp & UDCCS0_OPR) ? " opr" : "");
-
-	if (dev->has_cfr) {
-		tmp = UDCCFR;
-		seq_printf(m,
-			"udccfr %02X =%s%s\n", tmp,
-			(tmp & UDCCFR_AREN) ? " aren" : "",
-			(tmp & UDCCFR_ACM) ? " acm" : "");
-	}
-
-	if (!is_vbus_present() || !dev->driver)
-		goto done;
-
-	seq_printf(m, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
-		dev->stats.write.bytes, dev->stats.write.ops,
-		dev->stats.read.bytes, dev->stats.read.ops,
-		dev->stats.irqs);
-
-	/* dump endpoint queues */
-	for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
-		struct pxa2xx_ep	*ep = &dev->ep [i];
-		struct pxa2xx_request	*req;
-
-		if (i != 0) {
-			const struct usb_endpoint_descriptor	*desc;
-
-			desc = ep->desc;
-			if (!desc)
-				continue;
-			tmp = *dev->ep [i].reg_udccs;
-			seq_printf(m,
-				"%s max %d %s udccs %02x irqs %lu\n",
-				ep->ep.name, le16_to_cpu(desc->wMaxPacketSize),
-				"pio", tmp, ep->pio_irqs);
-			/* TODO translate all five groups of udccs bits! */
-
-		} else /* ep0 should only have one transfer queued */
-			seq_printf(m, "ep0 max 16 pio irqs %lu\n",
-				ep->pio_irqs);
-
-		if (list_empty(&ep->queue)) {
-			seq_printf(m, "\t(nothing queued)\n");
-			continue;
-		}
-		list_for_each_entry(req, &ep->queue, queue) {
-			seq_printf(m,
-					"\treq %p len %d/%d buf %p\n",
-					&req->req, req->req.actual,
-					req->req.length, req->req.buf);
-		}
-	}
-
-done:
-	local_irq_restore(flags);
-	return 0;
-}
-
-static int
-udc_debugfs_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, udc_seq_show, inode->i_private);
-}
-
-static const struct file_operations debug_fops = {
-	.open		= udc_debugfs_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-	.owner		= THIS_MODULE,
-};
-
-#define create_debug_files(dev) \
-	do { \
-		dev->debugfs_udc = debugfs_create_file(dev->gadget.name, \
-			S_IRUGO, NULL, dev, &debug_fops); \
-	} while (0)
-#define remove_debug_files(dev) \
-	do { \
-		if (dev->debugfs_udc) \
-			debugfs_remove(dev->debugfs_udc); \
-	} while (0)
-
-#else	/* !CONFIG_USB_GADGET_DEBUG_FILES */
-
-#define create_debug_files(dev) do {} while (0)
-#define remove_debug_files(dev) do {} while (0)
-
-#endif	/* CONFIG_USB_GADGET_DEBUG_FILES */
-
-/*-------------------------------------------------------------------------*/
-
-/*
- *	udc_disable - disable USB device controller
- */
-static void udc_disable(struct pxa2xx_udc *dev)
-{
-	/* block all irqs */
-	udc_set_mask_UDCCR(UDCCR_SRM|UDCCR_REM);
-	UICR0 = UICR1 = 0xff;
-	UFNRH = UFNRH_SIM;
-
-	/* if hardware supports it, disconnect from usb */
-	pullup_off();
-
-	udc_clear_mask_UDCCR(UDCCR_UDE);
-
-	ep0_idle (dev);
-	dev->gadget.speed = USB_SPEED_UNKNOWN;
-}
-
-
-/*
- *	udc_reinit - initialize software state
- */
-static void udc_reinit(struct pxa2xx_udc *dev)
-{
-	u32	i;
-
-	/* device/ep0 records init */
-	INIT_LIST_HEAD (&dev->gadget.ep_list);
-	INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
-	dev->ep0state = EP0_IDLE;
-
-	/* basic endpoint records init */
-	for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
-		struct pxa2xx_ep *ep = &dev->ep[i];
-
-		if (i != 0)
-			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
-
-		ep->desc = NULL;
-		ep->stopped = 0;
-		INIT_LIST_HEAD (&ep->queue);
-		ep->pio_irqs = 0;
-	}
-
-	/* the rest was statically initialized, and is read-only */
-}
-
-/* until it's enabled, this UDC should be completely invisible
- * to any USB host.
- */
-static void udc_enable (struct pxa2xx_udc *dev)
-{
-	udc_clear_mask_UDCCR(UDCCR_UDE);
-
-	/* try to clear these bits before we enable the udc */
-	udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
-
-	ep0_idle(dev);
-	dev->gadget.speed = USB_SPEED_UNKNOWN;
-	dev->stats.irqs = 0;
-
-	/*
-	 * sequence taken from chapter 12.5.10, PXA250 AppProcDevManual:
-	 * - enable UDC
-	 * - if RESET is already in progress, ack interrupt
-	 * - unmask reset interrupt
-	 */
-	udc_set_mask_UDCCR(UDCCR_UDE);
-	if (!(UDCCR & UDCCR_UDA))
-		udc_ack_int_UDCCR(UDCCR_RSTIR);
-
-	if (dev->has_cfr /* UDC_RES2 is defined */) {
-		/* pxa255 (a0+) can avoid a set_config race that could
-		 * prevent gadget drivers from configuring correctly
-		 */
-		UDCCFR = UDCCFR_ACM | UDCCFR_MB1;
-	} else {
-		/* "USB test mode" for pxa250 errata 40-42 (stepping a0, a1)
-		 * which could result in missing packets and interrupts.
-		 * supposedly one bit per endpoint, controlling whether it
-		 * double buffers or not; ACM/AREN bits fit into the holes.
-		 * zero bits (like USIR0_IRx) disable double buffering.
-		 */
-		UDC_RES1 = 0x00;
-		UDC_RES2 = 0x00;
-	}
-
-	/* enable suspend/resume and reset irqs */
-	udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
-
-	/* enable ep0 irqs */
-	UICR0 &= ~UICR0_IM0;
-
-	/* if hardware supports it, pullup D+ and wait for reset */
-	pullup_on();
-}
-
-
-/* when a driver is successfully registered, it will receive
- * control requests including set_configuration(), which enables
- * non-control requests.  then usb traffic follows until a
- * disconnect is reported.  then a host may connect again, or
- * the driver might get unbound.
- */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
-{
-	struct pxa2xx_udc	*dev = the_controller;
-	int			retval;
-
-	if (!driver
-			|| driver->speed < USB_SPEED_FULL
-			|| !driver->bind
-			|| !driver->disconnect
-			|| !driver->setup)
-		return -EINVAL;
-	if (!dev)
-		return -ENODEV;
-	if (dev->driver)
-		return -EBUSY;
-
-	/* first hook up the driver ... */
-	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
-	dev->pullup = 1;
-
-	retval = device_add (&dev->gadget.dev);
-	if (retval) {
-fail:
-		dev->driver = NULL;
-		dev->gadget.dev.driver = NULL;
-		return retval;
-	}
-	retval = driver->bind(&dev->gadget);
-	if (retval) {
-		DMSG("bind to driver %s --> error %d\n",
-				driver->driver.name, retval);
-		device_del (&dev->gadget.dev);
-		goto fail;
-	}
-
-	/* ... then enable host detection and ep0; and we're ready
-	 * for set_configuration as well as eventual disconnect.
-	 */
-	DMSG("registered gadget driver '%s'\n", driver->driver.name);
-	pullup(dev);
-	dump_state(dev);
-	return 0;
-}
-EXPORT_SYMBOL(usb_gadget_register_driver);
-
-static void
-stop_activity(struct pxa2xx_udc *dev, struct usb_gadget_driver *driver)
-{
-	int i;
-
-	/* don't disconnect drivers more than once */
-	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-		driver = NULL;
-	dev->gadget.speed = USB_SPEED_UNKNOWN;
-
-	/* prevent new request submissions, kill any outstanding requests  */
-	for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
-		struct pxa2xx_ep *ep = &dev->ep[i];
-
-		ep->stopped = 1;
-		nuke(ep, -ESHUTDOWN);
-	}
-	del_timer_sync(&dev->timer);
-
-	/* report disconnect; the driver is already quiesced */
-	if (driver)
-		driver->disconnect(&dev->gadget);
-
-	/* re-init driver-visible data structures */
-	udc_reinit(dev);
-}
-
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
-{
-	struct pxa2xx_udc	*dev = the_controller;
-
-	if (!dev)
-		return -ENODEV;
-	if (!driver || driver != dev->driver || !driver->unbind)
-		return -EINVAL;
-
-	local_irq_disable();
-	dev->pullup = 0;
-	pullup(dev);
-	stop_activity(dev, driver);
-	local_irq_enable();
-
-	driver->unbind(&dev->gadget);
-	dev->gadget.dev.driver = NULL;
-	dev->driver = NULL;
-
-	device_del (&dev->gadget.dev);
-
-	DMSG("unregistered gadget driver '%s'\n", driver->driver.name);
-	dump_state(dev);
-	return 0;
-}
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_ARCH_LUBBOCK
-
-/* Lubbock has separate connect and disconnect irqs.  More typical designs
- * use one GPIO as the VBUS IRQ, and another to control the D+ pullup.
- */
-
-static irqreturn_t
-lubbock_vbus_irq(int irq, void *_dev)
-{
-	struct pxa2xx_udc	*dev = _dev;
-	int			vbus;
-
-	dev->stats.irqs++;
-	switch (irq) {
-	case LUBBOCK_USB_IRQ:
-		vbus = 1;
-		disable_irq(LUBBOCK_USB_IRQ);
-		enable_irq(LUBBOCK_USB_DISC_IRQ);
-		break;
-	case LUBBOCK_USB_DISC_IRQ:
-		vbus = 0;
-		disable_irq(LUBBOCK_USB_DISC_IRQ);
-		enable_irq(LUBBOCK_USB_IRQ);
-		break;
-	default:
-		return IRQ_NONE;
-	}
-
-	pxa2xx_udc_vbus_session(&dev->gadget, vbus);
-	return IRQ_HANDLED;
-}
-
-#endif
-
-static irqreturn_t udc_vbus_irq(int irq, void *_dev)
-{
-	struct pxa2xx_udc	*dev = _dev;
-	int			vbus = gpio_get_value(dev->mach->gpio_vbus);
-
-	if (dev->mach->gpio_vbus_inverted)
-		vbus = !vbus;
-
-	pxa2xx_udc_vbus_session(&dev->gadget, vbus);
-	return IRQ_HANDLED;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static inline void clear_ep_state (struct pxa2xx_udc *dev)
-{
-	unsigned i;
-
-	/* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
-	 * fifos, and pending transactions mustn't be continued in any case.
-	 */
-	for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++)
-		nuke(&dev->ep[i], -ECONNABORTED);
-}
-
-static void udc_watchdog(unsigned long _dev)
-{
-	struct pxa2xx_udc	*dev = (void *)_dev;
-
-	local_irq_disable();
-	if (dev->ep0state == EP0_STALL
-			&& (UDCCS0 & UDCCS0_FST) == 0
-			&& (UDCCS0 & UDCCS0_SST) == 0) {
-		UDCCS0 = UDCCS0_FST|UDCCS0_FTF;
-		DBG(DBG_VERBOSE, "ep0 re-stall\n");
-		start_watchdog(dev);
-	}
-	local_irq_enable();
-}
-
-static void handle_ep0 (struct pxa2xx_udc *dev)
-{
-	u32			udccs0 = UDCCS0;
-	struct pxa2xx_ep	*ep = &dev->ep [0];
-	struct pxa2xx_request	*req;
-	union {
-		struct usb_ctrlrequest	r;
-		u8			raw [8];
-		u32			word [2];
-	} u;
-
-	if (list_empty(&ep->queue))
-		req = NULL;
-	else
-		req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
-
-	/* clear stall status */
-	if (udccs0 & UDCCS0_SST) {
-		nuke(ep, -EPIPE);
-		UDCCS0 = UDCCS0_SST;
-		del_timer(&dev->timer);
-		ep0_idle(dev);
-	}
-
-	/* previous request unfinished?  non-error iff back-to-back ... */
-	if ((udccs0 & UDCCS0_SA) != 0 && dev->ep0state != EP0_IDLE) {
-		nuke(ep, 0);
-		del_timer(&dev->timer);
-		ep0_idle(dev);
-	}
-
-	switch (dev->ep0state) {
-	case EP0_IDLE:
-		/* late-breaking status? */
-		udccs0 = UDCCS0;
-
-		/* start control request? */
-		if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))
-				== (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))) {
-			int i;
-
-			nuke (ep, -EPROTO);
-
-			/* read SETUP packet */
-			for (i = 0; i < 8; i++) {
-				if (unlikely(!(UDCCS0 & UDCCS0_RNE))) {
-bad_setup:
-					DMSG("SETUP %d!\n", i);
-					goto stall;
-				}
-				u.raw [i] = (u8) UDDR0;
-			}
-			if (unlikely((UDCCS0 & UDCCS0_RNE) != 0))
-				goto bad_setup;
-
-got_setup:
-			DBG(DBG_VERBOSE, "SETUP %02x.%02x v%04x i%04x l%04x\n",
-				u.r.bRequestType, u.r.bRequest,
-				le16_to_cpu(u.r.wValue),
-				le16_to_cpu(u.r.wIndex),
-				le16_to_cpu(u.r.wLength));
-
-			/* cope with automagic for some standard requests. */
-			dev->req_std = (u.r.bRequestType & USB_TYPE_MASK)
-						== USB_TYPE_STANDARD;
-			dev->req_config = 0;
-			dev->req_pending = 1;
-			switch (u.r.bRequest) {
-			/* hardware restricts gadget drivers here! */
-			case USB_REQ_SET_CONFIGURATION:
-				if (u.r.bRequestType == USB_RECIP_DEVICE) {
-					/* reflect hardware's automagic
-					 * up to the gadget driver.
-					 */
-config_change:
-					dev->req_config = 1;
-					clear_ep_state(dev);
-					/* if !has_cfr, there's no synch
-					 * else use AREN (later) not SA|OPR
-					 * USIR0_IR0 acts edge sensitive
-					 */
-				}
-				break;
-			/* ... and here, even more ... */
-			case USB_REQ_SET_INTERFACE:
-				if (u.r.bRequestType == USB_RECIP_INTERFACE) {
-					/* udc hardware is broken by design:
-					 *  - altsetting may only be zero;
-					 *  - hw resets all interfaces' eps;
-					 *  - ep reset doesn't include halt(?).
-					 */
-					DMSG("broken set_interface (%d/%d)\n",
-						le16_to_cpu(u.r.wIndex),
-						le16_to_cpu(u.r.wValue));
-					goto config_change;
-				}
-				break;
-			/* hardware was supposed to hide this */
-			case USB_REQ_SET_ADDRESS:
-				if (u.r.bRequestType == USB_RECIP_DEVICE) {
-					ep0start(dev, 0, "address");
-					return;
-				}
-				break;
-			}
-
-			if (u.r.bRequestType & USB_DIR_IN)
-				dev->ep0state = EP0_IN_DATA_PHASE;
-			else
-				dev->ep0state = EP0_OUT_DATA_PHASE;
-
-			i = dev->driver->setup(&dev->gadget, &u.r);
-			if (i < 0) {
-				/* hardware automagic preventing STALL... */
-				if (dev->req_config) {
-					/* hardware sometimes neglects to tell
-					 * tell us about config change events,
-					 * so later ones may fail...
-					 */
-					WARN("config change %02x fail %d?\n",
-						u.r.bRequest, i);
-					return;
-					/* TODO experiment:  if has_cfr,
-					 * hardware didn't ACK; maybe we
-					 * could actually STALL!
-					 */
-				}
-				DBG(DBG_VERBOSE, "protocol STALL, "
-					"%02x err %d\n", UDCCS0, i);
-stall:
-				/* the watchdog timer helps deal with cases
-				 * where udc seems to clear FST wrongly, and
-				 * then NAKs instead of STALLing.
-				 */
-				ep0start(dev, UDCCS0_FST|UDCCS0_FTF, "stall");
-				start_watchdog(dev);
-				dev->ep0state = EP0_STALL;
-
-			/* deferred i/o == no response yet */
-			} else if (dev->req_pending) {
-				if (likely(dev->ep0state == EP0_IN_DATA_PHASE
-						|| dev->req_std || u.r.wLength))
-					ep0start(dev, 0, "defer");
-				else
-					ep0start(dev, UDCCS0_IPR, "defer/IPR");
-			}
-
-			/* expect at least one data or status stage irq */
-			return;
-
-		} else if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA))
-				== (UDCCS0_OPR|UDCCS0_SA))) {
-			unsigned i;
-
-			/* pxa210/250 erratum 131 for B0/B1 says RNE lies.
-			 * still observed on a pxa255 a0.
-			 */
-			DBG(DBG_VERBOSE, "e131\n");
-			nuke(ep, -EPROTO);
-
-			/* read SETUP data, but don't trust it too much */
-			for (i = 0; i < 8; i++)
-				u.raw [i] = (u8) UDDR0;
-			if ((u.r.bRequestType & USB_RECIP_MASK)
-					> USB_RECIP_OTHER)
-				goto stall;
-			if (u.word [0] == 0 && u.word [1] == 0)
-				goto stall;
-			goto got_setup;
-		} else {
-			/* some random early IRQ:
-			 * - we acked FST
-			 * - IPR cleared
-			 * - OPR got set, without SA (likely status stage)
-			 */
-			UDCCS0 = udccs0 & (UDCCS0_SA|UDCCS0_OPR);
-		}
-		break;
-	case EP0_IN_DATA_PHASE:			/* GET_DESCRIPTOR etc */
-		if (udccs0 & UDCCS0_OPR) {
-			UDCCS0 = UDCCS0_OPR|UDCCS0_FTF;
-			DBG(DBG_VERBOSE, "ep0in premature status\n");
-			if (req)
-				done(ep, req, 0);
-			ep0_idle(dev);
-		} else /* irq was IPR clearing */ {
-			if (req) {
-				/* this IN packet might finish the request */
-				(void) write_ep0_fifo(ep, req);
-			} /* else IN token before response was written */
-		}
-		break;
-	case EP0_OUT_DATA_PHASE:		/* SET_DESCRIPTOR etc */
-		if (udccs0 & UDCCS0_OPR) {
-			if (req) {
-				/* this OUT packet might finish the request */
-				if (read_ep0_fifo(ep, req))
-					done(ep, req, 0);
-				/* else more OUT packets expected */
-			} /* else OUT token before read was issued */
-		} else /* irq was IPR clearing */ {
-			DBG(DBG_VERBOSE, "ep0out premature status\n");
-			if (req)
-				done(ep, req, 0);
-			ep0_idle(dev);
-		}
-		break;
-	case EP0_END_XFER:
-		if (req)
-			done(ep, req, 0);
-		/* ack control-IN status (maybe in-zlp was skipped)
-		 * also appears after some config change events.
-		 */
-		if (udccs0 & UDCCS0_OPR)
-			UDCCS0 = UDCCS0_OPR;
-		ep0_idle(dev);
-		break;
-	case EP0_STALL:
-		UDCCS0 = UDCCS0_FST;
-		break;
-	}
-	USIR0 = USIR0_IR0;
-}
-
-static void handle_ep(struct pxa2xx_ep *ep)
-{
-	struct pxa2xx_request	*req;
-	int			is_in = ep->bEndpointAddress & USB_DIR_IN;
-	int			completed;
-	u32			udccs, tmp;
-
-	do {
-		completed = 0;
-		if (likely (!list_empty(&ep->queue)))
-			req = list_entry(ep->queue.next,
-					struct pxa2xx_request, queue);
-		else
-			req = NULL;
-
-		// TODO check FST handling
-
-		udccs = *ep->reg_udccs;
-		if (unlikely(is_in)) {	/* irq from TPC, SST, or (ISO) TUR */
-			tmp = UDCCS_BI_TUR;
-			if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK))
-				tmp |= UDCCS_BI_SST;
-			tmp &= udccs;
-			if (likely (tmp))
-				*ep->reg_udccs = tmp;
-			if (req && likely ((udccs & UDCCS_BI_TFS) != 0))
-				completed = write_fifo(ep, req);
-
-		} else {	/* irq from RPC (or for ISO, ROF) */
-			if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK))
-				tmp = UDCCS_BO_SST | UDCCS_BO_DME;
-			else
-				tmp = UDCCS_IO_ROF | UDCCS_IO_DME;
-			tmp &= udccs;
-			if (likely(tmp))
-				*ep->reg_udccs = tmp;
-
-			/* fifos can hold packets, ready for reading... */
-			if (likely(req)) {
-				completed = read_fifo(ep, req);
-			} else
-				pio_irq_disable (ep->bEndpointAddress);
-		}
-		ep->pio_irqs++;
-	} while (completed);
-}
-
-/*
- *	pxa2xx_udc_irq - interrupt handler
- *
- * avoid delays in ep0 processing. the control handshaking isn't always
- * under software control (pxa250c0 and the pxa255 are better), and delays
- * could cause usb protocol errors.
- */
-static irqreturn_t
-pxa2xx_udc_irq(int irq, void *_dev)
-{
-	struct pxa2xx_udc	*dev = _dev;
-	int			handled;
-
-	dev->stats.irqs++;
-	do {
-		u32		udccr = UDCCR;
-
-		handled = 0;
-
-		/* SUSpend Interrupt Request */
-		if (unlikely(udccr & UDCCR_SUSIR)) {
-			udc_ack_int_UDCCR(UDCCR_SUSIR);
-			handled = 1;
-			DBG(DBG_VERBOSE, "USB suspend%s\n", is_vbus_present()
-				? "" : "+disconnect");
-
-			if (!is_vbus_present())
-				stop_activity(dev, dev->driver);
-			else if (dev->gadget.speed != USB_SPEED_UNKNOWN
-					&& dev->driver
-					&& dev->driver->suspend)
-				dev->driver->suspend(&dev->gadget);
-			ep0_idle (dev);
-		}
-
-		/* RESume Interrupt Request */
-		if (unlikely(udccr & UDCCR_RESIR)) {
-			udc_ack_int_UDCCR(UDCCR_RESIR);
-			handled = 1;
-			DBG(DBG_VERBOSE, "USB resume\n");
-
-			if (dev->gadget.speed != USB_SPEED_UNKNOWN
-					&& dev->driver
-					&& dev->driver->resume
-					&& is_vbus_present())
-				dev->driver->resume(&dev->gadget);
-		}
-
-		/* ReSeT Interrupt Request - USB reset */
-		if (unlikely(udccr & UDCCR_RSTIR)) {
-			udc_ack_int_UDCCR(UDCCR_RSTIR);
-			handled = 1;
-
-			if ((UDCCR & UDCCR_UDA) == 0) {
-				DBG(DBG_VERBOSE, "USB reset start\n");
-
-				/* reset driver and endpoints,
-				 * in case that's not yet done
-				 */
-				stop_activity (dev, dev->driver);
-
-			} else {
-				DBG(DBG_VERBOSE, "USB reset end\n");
-				dev->gadget.speed = USB_SPEED_FULL;
-				memset(&dev->stats, 0, sizeof dev->stats);
-				/* driver and endpoints are still reset */
-			}
-
-		} else {
-			u32	usir0 = USIR0 & ~UICR0;
-			u32	usir1 = USIR1 & ~UICR1;
-			int	i;
-
-			if (unlikely (!usir0 && !usir1))
-				continue;
-
-			DBG(DBG_VERY_NOISY, "irq %02x.%02x\n", usir1, usir0);
-
-			/* control traffic */
-			if (usir0 & USIR0_IR0) {
-				dev->ep[0].pio_irqs++;
-				handle_ep0(dev);
-				handled = 1;
-			}
-
-			/* endpoint data transfers */
-			for (i = 0; i < 8; i++) {
-				u32	tmp = 1 << i;
-
-				if (i && (usir0 & tmp)) {
-					handle_ep(&dev->ep[i]);
-					USIR0 |= tmp;
-					handled = 1;
-				}
-				if (usir1 & tmp) {
-					handle_ep(&dev->ep[i+8]);
-					USIR1 |= tmp;
-					handled = 1;
-				}
-			}
-		}
-
-		/* we could also ask for 1 msec SOF (SIR) interrupts */
-
-	} while (handled);
-	return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void nop_release (struct device *dev)
-{
-	DMSG("%s %s\n", __func__, dev->bus_id);
-}
-
-/* this uses load-time allocation and initialization (instead of
- * doing it at run-time) to save code, eliminate fault paths, and
- * be more obviously correct.
- */
-static struct pxa2xx_udc memory = {
-	.gadget = {
-		.ops		= &pxa2xx_udc_ops,
-		.ep0		= &memory.ep[0].ep,
-		.name		= driver_name,
-		.dev = {
-			.bus_id		= "gadget",
-			.release	= nop_release,
-		},
-	},
-
-	/* control endpoint */
-	.ep[0] = {
-		.ep = {
-			.name		= ep0name,
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= EP0_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.reg_udccs	= &UDCCS0,
-		.reg_uddr	= &UDDR0,
-	},
-
-	/* first group of endpoints */
-	.ep[1] = {
-		.ep = {
-			.name		= "ep1in-bulk",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= BULK_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= BULK_FIFO_SIZE,
-		.bEndpointAddress = USB_DIR_IN | 1,
-		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
-		.reg_udccs	= &UDCCS1,
-		.reg_uddr	= &UDDR1,
-	},
-	.ep[2] = {
-		.ep = {
-			.name		= "ep2out-bulk",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= BULK_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= BULK_FIFO_SIZE,
-		.bEndpointAddress = 2,
-		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
-		.reg_udccs	= &UDCCS2,
-		.reg_ubcr	= &UBCR2,
-		.reg_uddr	= &UDDR2,
-	},
-#ifndef CONFIG_USB_PXA2XX_SMALL
-	.ep[3] = {
-		.ep = {
-			.name		= "ep3in-iso",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= ISO_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= ISO_FIFO_SIZE,
-		.bEndpointAddress = USB_DIR_IN | 3,
-		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
-		.reg_udccs	= &UDCCS3,
-		.reg_uddr	= &UDDR3,
-	},
-	.ep[4] = {
-		.ep = {
-			.name		= "ep4out-iso",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= ISO_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= ISO_FIFO_SIZE,
-		.bEndpointAddress = 4,
-		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
-		.reg_udccs	= &UDCCS4,
-		.reg_ubcr	= &UBCR4,
-		.reg_uddr	= &UDDR4,
-	},
-	.ep[5] = {
-		.ep = {
-			.name		= "ep5in-int",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= INT_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= INT_FIFO_SIZE,
-		.bEndpointAddress = USB_DIR_IN | 5,
-		.bmAttributes	= USB_ENDPOINT_XFER_INT,
-		.reg_udccs	= &UDCCS5,
-		.reg_uddr	= &UDDR5,
-	},
-
-	/* second group of endpoints */
-	.ep[6] = {
-		.ep = {
-			.name		= "ep6in-bulk",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= BULK_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= BULK_FIFO_SIZE,
-		.bEndpointAddress = USB_DIR_IN | 6,
-		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
-		.reg_udccs	= &UDCCS6,
-		.reg_uddr	= &UDDR6,
-	},
-	.ep[7] = {
-		.ep = {
-			.name		= "ep7out-bulk",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= BULK_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= BULK_FIFO_SIZE,
-		.bEndpointAddress = 7,
-		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
-		.reg_udccs	= &UDCCS7,
-		.reg_ubcr	= &UBCR7,
-		.reg_uddr	= &UDDR7,
-	},
-	.ep[8] = {
-		.ep = {
-			.name		= "ep8in-iso",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= ISO_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= ISO_FIFO_SIZE,
-		.bEndpointAddress = USB_DIR_IN | 8,
-		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
-		.reg_udccs	= &UDCCS8,
-		.reg_uddr	= &UDDR8,
-	},
-	.ep[9] = {
-		.ep = {
-			.name		= "ep9out-iso",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= ISO_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= ISO_FIFO_SIZE,
-		.bEndpointAddress = 9,
-		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
-		.reg_udccs	= &UDCCS9,
-		.reg_ubcr	= &UBCR9,
-		.reg_uddr	= &UDDR9,
-	},
-	.ep[10] = {
-		.ep = {
-			.name		= "ep10in-int",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= INT_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= INT_FIFO_SIZE,
-		.bEndpointAddress = USB_DIR_IN | 10,
-		.bmAttributes	= USB_ENDPOINT_XFER_INT,
-		.reg_udccs	= &UDCCS10,
-		.reg_uddr	= &UDDR10,
-	},
-
-	/* third group of endpoints */
-	.ep[11] = {
-		.ep = {
-			.name		= "ep11in-bulk",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= BULK_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= BULK_FIFO_SIZE,
-		.bEndpointAddress = USB_DIR_IN | 11,
-		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
-		.reg_udccs	= &UDCCS11,
-		.reg_uddr	= &UDDR11,
-	},
-	.ep[12] = {
-		.ep = {
-			.name		= "ep12out-bulk",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= BULK_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= BULK_FIFO_SIZE,
-		.bEndpointAddress = 12,
-		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
-		.reg_udccs	= &UDCCS12,
-		.reg_ubcr	= &UBCR12,
-		.reg_uddr	= &UDDR12,
-	},
-	.ep[13] = {
-		.ep = {
-			.name		= "ep13in-iso",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= ISO_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= ISO_FIFO_SIZE,
-		.bEndpointAddress = USB_DIR_IN | 13,
-		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
-		.reg_udccs	= &UDCCS13,
-		.reg_uddr	= &UDDR13,
-	},
-	.ep[14] = {
-		.ep = {
-			.name		= "ep14out-iso",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= ISO_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= ISO_FIFO_SIZE,
-		.bEndpointAddress = 14,
-		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
-		.reg_udccs	= &UDCCS14,
-		.reg_ubcr	= &UBCR14,
-		.reg_uddr	= &UDDR14,
-	},
-	.ep[15] = {
-		.ep = {
-			.name		= "ep15in-int",
-			.ops		= &pxa2xx_ep_ops,
-			.maxpacket	= INT_FIFO_SIZE,
-		},
-		.dev		= &memory,
-		.fifo_size	= INT_FIFO_SIZE,
-		.bEndpointAddress = USB_DIR_IN | 15,
-		.bmAttributes	= USB_ENDPOINT_XFER_INT,
-		.reg_udccs	= &UDCCS15,
-		.reg_uddr	= &UDDR15,
-	},
-#endif /* !CONFIG_USB_PXA2XX_SMALL */
-};
-
-#define CP15R0_VENDOR_MASK	0xffffe000
-
-#if	defined(CONFIG_ARCH_PXA)
-#define CP15R0_XSCALE_VALUE	0x69052000	/* intel/arm/xscale */
-
-#elif	defined(CONFIG_ARCH_IXP4XX)
-#define CP15R0_XSCALE_VALUE	0x69054000	/* intel/arm/ixp4xx */
-
-#endif
-
-#define CP15R0_PROD_MASK	0x000003f0
-#define PXA25x			0x00000100	/* and PXA26x */
-#define PXA210			0x00000120
-
-#define CP15R0_REV_MASK		0x0000000f
-
-#define CP15R0_PRODREV_MASK	(CP15R0_PROD_MASK | CP15R0_REV_MASK)
-
-#define PXA255_A0		0x00000106	/* or PXA260_B1 */
-#define PXA250_C0		0x00000105	/* or PXA26x_B0 */
-#define PXA250_B2		0x00000104
-#define PXA250_B1		0x00000103	/* or PXA260_A0 */
-#define PXA250_B0		0x00000102
-#define PXA250_A1		0x00000101
-#define PXA250_A0		0x00000100
-
-#define PXA210_C0		0x00000125
-#define PXA210_B2		0x00000124
-#define PXA210_B1		0x00000123
-#define PXA210_B0		0x00000122
-#define IXP425_A0		0x000001c1
-#define IXP425_B0		0x000001f1
-#define IXP465_AD		0x00000200
-
-/*
- *	probe - binds to the platform device
- */
-static int __init pxa2xx_udc_probe(struct platform_device *pdev)
-{
-	struct pxa2xx_udc *dev = &memory;
-	int retval, vbus_irq, irq;
-	u32 chiprev;
-
-	/* insist on Intel/ARM/XScale */
-	asm("mrc%? p15, 0, %0, c0, c0" : "=r" (chiprev));
-	if ((chiprev & CP15R0_VENDOR_MASK) != CP15R0_XSCALE_VALUE) {
-		pr_err("%s: not XScale!\n", driver_name);
-		return -ENODEV;
-	}
-
-	/* trigger chiprev-specific logic */
-	switch (chiprev & CP15R0_PRODREV_MASK) {
-#if	defined(CONFIG_ARCH_PXA)
-	case PXA255_A0:
-		dev->has_cfr = 1;
-		break;
-	case PXA250_A0:
-	case PXA250_A1:
-		/* A0/A1 "not released"; ep 13, 15 unusable */
-		/* fall through */
-	case PXA250_B2: case PXA210_B2:
-	case PXA250_B1: case PXA210_B1:
-	case PXA250_B0: case PXA210_B0:
-		/* OUT-DMA is broken ... */
-		/* fall through */
-	case PXA250_C0: case PXA210_C0:
-		break;
-#elif	defined(CONFIG_ARCH_IXP4XX)
-	case IXP425_A0:
-	case IXP425_B0:
-	case IXP465_AD:
-		dev->has_cfr = 1;
-		break;
-#endif
-	default:
-		pr_err("%s: unrecognized processor: %08x\n",
-			driver_name, chiprev);
-		/* iop3xx, ixp4xx, ... */
-		return -ENODEV;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return -ENODEV;
-
-	dev->clk = clk_get(&pdev->dev, "UDCCLK");
-	if (IS_ERR(dev->clk)) {
-		retval = PTR_ERR(dev->clk);
-		goto err_clk;
-	}
-
-	pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
-		dev->has_cfr ? "" : " (!cfr)",
-		SIZE_STR "(pio)"
-		);
-
-	/* other non-static parts of init */
-	dev->dev = &pdev->dev;
-	dev->mach = pdev->dev.platform_data;
-
-	if (dev->mach->gpio_vbus) {
-		if ((retval = gpio_request(dev->mach->gpio_vbus,
-				"pxa2xx_udc GPIO VBUS"))) {
-			dev_dbg(&pdev->dev,
-				"can't get vbus gpio %d, err: %d\n",
-				dev->mach->gpio_vbus, retval);
-			goto err_gpio_vbus;
-		}
-		gpio_direction_input(dev->mach->gpio_vbus);
-		vbus_irq = gpio_to_irq(dev->mach->gpio_vbus);
-	} else
-		vbus_irq = 0;
-
-	if (dev->mach->gpio_pullup) {
-		if ((retval = gpio_request(dev->mach->gpio_pullup,
-				"pca2xx_udc GPIO PULLUP"))) {
-			dev_dbg(&pdev->dev,
-				"can't get pullup gpio %d, err: %d\n",
-				dev->mach->gpio_pullup, retval);
-			goto err_gpio_pullup;
-		}
-		gpio_direction_output(dev->mach->gpio_pullup, 0);
-	}
-
-	init_timer(&dev->timer);
-	dev->timer.function = udc_watchdog;
-	dev->timer.data = (unsigned long) dev;
-
-	device_initialize(&dev->gadget.dev);
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
-	the_controller = dev;
-	platform_set_drvdata(pdev, dev);
-
-	udc_disable(dev);
-	udc_reinit(dev);
-
-	dev->vbus = is_vbus_present();
-
-	/* irq setup after old hardware state is cleaned up */
-	retval = request_irq(irq, pxa2xx_udc_irq,
-			IRQF_DISABLED, driver_name, dev);
-	if (retval != 0) {
-		pr_err("%s: can't get irq %d, err %d\n",
-			driver_name, irq, retval);
-		goto err_irq1;
-	}
-	dev->got_irq = 1;
-
-#ifdef CONFIG_ARCH_LUBBOCK
-	if (machine_is_lubbock()) {
-		retval = request_irq(LUBBOCK_USB_DISC_IRQ,
-				lubbock_vbus_irq,
-				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
-				driver_name, dev);
-		if (retval != 0) {
-			pr_err("%s: can't get irq %i, err %d\n",
-				driver_name, LUBBOCK_USB_DISC_IRQ, retval);
-lubbock_fail0:
-			goto err_irq_lub;
-		}
-		retval = request_irq(LUBBOCK_USB_IRQ,
-				lubbock_vbus_irq,
-				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
-				driver_name, dev);
-		if (retval != 0) {
-			pr_err("%s: can't get irq %i, err %d\n",
-				driver_name, LUBBOCK_USB_IRQ, retval);
-			free_irq(LUBBOCK_USB_DISC_IRQ, dev);
-			goto lubbock_fail0;
-		}
-	} else
-#endif
-	if (vbus_irq) {
-		retval = request_irq(vbus_irq, udc_vbus_irq,
-				IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
-				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-				driver_name, dev);
-		if (retval != 0) {
-			pr_err("%s: can't get irq %i, err %d\n",
-				driver_name, vbus_irq, retval);
-			goto err_vbus_irq;
-		}
-	}
-	create_debug_files(dev);
-
-	return 0;
-
- err_vbus_irq:
-#ifdef	CONFIG_ARCH_LUBBOCK
-	free_irq(LUBBOCK_USB_DISC_IRQ, dev);
- err_irq_lub:
-#endif
-	free_irq(irq, dev);
- err_irq1:
-	if (dev->mach->gpio_pullup)
-		gpio_free(dev->mach->gpio_pullup);
- err_gpio_pullup:
-	if (dev->mach->gpio_vbus)
-		gpio_free(dev->mach->gpio_vbus);
- err_gpio_vbus:
-	clk_put(dev->clk);
- err_clk:
-	return retval;
-}
-
-static void pxa2xx_udc_shutdown(struct platform_device *_dev)
-{
-	pullup_off();
-}
-
-static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
-{
-	struct pxa2xx_udc *dev = platform_get_drvdata(pdev);
-
-	if (dev->driver)
-		return -EBUSY;
-
-	dev->pullup = 0;
-	pullup(dev);
-
-	remove_debug_files(dev);
-
-	if (dev->got_irq) {
-		free_irq(platform_get_irq(pdev, 0), dev);
-		dev->got_irq = 0;
-	}
-#ifdef CONFIG_ARCH_LUBBOCK
-	if (machine_is_lubbock()) {
-		free_irq(LUBBOCK_USB_DISC_IRQ, dev);
-		free_irq(LUBBOCK_USB_IRQ, dev);
-	}
-#endif
-	if (dev->mach->gpio_vbus) {
-		free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev);
-		gpio_free(dev->mach->gpio_vbus);
-	}
-	if (dev->mach->gpio_pullup)
-		gpio_free(dev->mach->gpio_pullup);
-
-	clk_put(dev->clk);
-
-	platform_set_drvdata(pdev, NULL);
-	the_controller = NULL;
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	CONFIG_PM
-
-/* USB suspend (controlled by the host) and system suspend (controlled
- * by the PXA) don't necessarily work well together.  If USB is active,
- * the 48 MHz clock is required; so the system can't enter 33 MHz idle
- * mode, or any deeper PM saving state.
- *
- * For now, we punt and forcibly disconnect from the USB host when PXA
- * enters any suspend state.  While we're disconnected, we always disable
- * the 48MHz USB clock ... allowing PXA sleep and/or 33 MHz idle states.
- * Boards without software pullup control shouldn't use those states.
- * VBUS IRQs should probably be ignored so that the PXA device just acts
- * "dead" to USB hosts until system resume.
- */
-static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct pxa2xx_udc	*udc = platform_get_drvdata(dev);
-	unsigned long flags;
-
-	if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
-		WARN("USB host won't detect disconnect!\n");
-	udc->suspended = 1;
-
-	local_irq_save(flags);
-	pullup(udc);
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-static int pxa2xx_udc_resume(struct platform_device *dev)
-{
-	struct pxa2xx_udc	*udc = platform_get_drvdata(dev);
-	unsigned long flags;
-
-	udc->suspended = 0;
-	local_irq_save(flags);
-	pullup(udc);
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-#else
-#define	pxa2xx_udc_suspend	NULL
-#define	pxa2xx_udc_resume	NULL
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-static struct platform_driver udc_driver = {
-	.shutdown	= pxa2xx_udc_shutdown,
-	.remove		= __exit_p(pxa2xx_udc_remove),
-	.suspend	= pxa2xx_udc_suspend,
-	.resume		= pxa2xx_udc_resume,
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "pxa2xx-udc",
-	},
-};
-
-static int __init udc_init(void)
-{
-	pr_info("%s: version %s\n", driver_name, DRIVER_VERSION);
-	return platform_driver_probe(&udc_driver, pxa2xx_udc_probe);
-}
-module_init(udc_init);
-
-static void __exit udc_exit(void)
-{
-	platform_driver_unregister(&udc_driver);
-}
-module_exit(udc_exit);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Frank Becker, Robert Schwebel, David Brownell");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-udc");
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
deleted file mode 100644
index e2c19e8..0000000
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * linux/drivers/usb/gadget/pxa2xx_udc.h
- * Intel PXA2xx on-chip full speed USB device controller
- *
- * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
- * Copyright (C) 2003 David Brownell
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef __LINUX_USB_GADGET_PXA2XX_H
-#define __LINUX_USB_GADGET_PXA2XX_H
-
-#include <linux/types.h>
-
-/*-------------------------------------------------------------------------*/
-
-/* pxa2xx has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */
-#define UFNRH_SIR	(1 << 7)	/* SOF interrupt request */
-#define UFNRH_SIM	(1 << 6)	/* SOF interrupt mask */
-#define UFNRH_IPE14	(1 << 5)	/* ISO packet error, ep14 */
-#define UFNRH_IPE9	(1 << 4)	/* ISO packet error, ep9 */
-#define UFNRH_IPE4	(1 << 3)	/* ISO packet error, ep4 */
-
-/* pxa255 has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */
-#define	UDCCFR		UDC_RES2	/* UDC Control Function Register */
-#define UDCCFR_AREN	(1 << 7)	/* ACK response enable (now) */
-#define UDCCFR_ACM	(1 << 2)	/* ACK control mode (wait for AREN) */
-
-/* latest pxa255 errata define new "must be one" bits in UDCCFR */
-#define	UDCCFR_MB1	(0xff & ~(UDCCFR_AREN|UDCCFR_ACM))
-
-/*-------------------------------------------------------------------------*/
-
-struct pxa2xx_udc;
-
-struct pxa2xx_ep {
-	struct usb_ep				ep;
-	struct pxa2xx_udc			*dev;
-
-	const struct usb_endpoint_descriptor	*desc;
-	struct list_head			queue;
-	unsigned long				pio_irqs;
-
-	unsigned short				fifo_size;
-	u8					bEndpointAddress;
-	u8					bmAttributes;
-
-	unsigned				stopped : 1;
-	unsigned				dma_fixup : 1;
-
-	/* UDCCS = UDC Control/Status for this EP
-	 * UBCR = UDC Byte Count Remaining (contents of OUT fifo)
-	 * UDDR = UDC Endpoint Data Register (the fifo)
-	 * DRCM = DMA Request Channel Map
-	 */
-	volatile u32				*reg_udccs;
-	volatile u32				*reg_ubcr;
-	volatile u32				*reg_uddr;
-};
-
-struct pxa2xx_request {
-	struct usb_request			req;
-	struct list_head			queue;
-};
-
-enum ep0_state {
-	EP0_IDLE,
-	EP0_IN_DATA_PHASE,
-	EP0_OUT_DATA_PHASE,
-	EP0_END_XFER,
-	EP0_STALL,
-};
-
-#define EP0_FIFO_SIZE	((unsigned)16)
-#define BULK_FIFO_SIZE	((unsigned)64)
-#define ISO_FIFO_SIZE	((unsigned)256)
-#define INT_FIFO_SIZE	((unsigned)8)
-
-struct udc_stats {
-	struct ep0stats {
-		unsigned long		ops;
-		unsigned long		bytes;
-	} read, write;
-	unsigned long			irqs;
-};
-
-#ifdef CONFIG_USB_PXA2XX_SMALL
-/* when memory's tight, SMALL config saves code+data.  */
-#define	PXA_UDC_NUM_ENDPOINTS	3
-#endif
-
-#ifndef	PXA_UDC_NUM_ENDPOINTS
-#define	PXA_UDC_NUM_ENDPOINTS	16
-#endif
-
-struct pxa2xx_udc {
-	struct usb_gadget			gadget;
-	struct usb_gadget_driver		*driver;
-
-	enum ep0_state				ep0state;
-	struct udc_stats			stats;
-	unsigned				got_irq : 1,
-						vbus : 1,
-						pullup : 1,
-						has_cfr : 1,
-						req_pending : 1,
-						req_std : 1,
-						req_config : 1,
-						suspended : 1,
-						active : 1;
-
-#define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200))
-	struct timer_list			timer;
-
-	struct device				*dev;
-	struct clk				*clk;
-	struct pxa2xx_udc_mach_info		*mach;
-	u64					dma_mask;
-	struct pxa2xx_ep			ep [PXA_UDC_NUM_ENDPOINTS];
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FS
-	struct dentry				*debugfs_udc;
-#endif
-};
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_ARCH_LUBBOCK
-#include <asm/arch/lubbock.h>
-/* lubbock can also report usb connect/disconnect irqs */
-#endif
-
-static struct pxa2xx_udc *the_controller;
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Debugging support vanishes in non-debug builds.  DBG_NORMAL should be
- * mostly silent during normal use/testing, with no timing side-effects.
- */
-#define DBG_NORMAL	1	/* error paths, device state transitions */
-#define DBG_VERBOSE	2	/* add some success path trace info */
-#define DBG_NOISY	3	/* ... even more: request level */
-#define DBG_VERY_NOISY	4	/* ... even more: packet level */
-
-#define DMSG(stuff...)	pr_debug("udc: " stuff)
-
-#ifdef DEBUG
-
-static int is_vbus_present(void);
-
-static const char *state_name[] = {
-	"EP0_IDLE",
-	"EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE",
-	"EP0_END_XFER", "EP0_STALL"
-};
-
-#ifdef VERBOSE_DEBUG
-#    define UDC_DEBUG DBG_VERBOSE
-#else
-#    define UDC_DEBUG DBG_NORMAL
-#endif
-
-static void __maybe_unused
-dump_udccr(const char *label)
-{
-	u32	udccr = UDCCR;
-	DMSG("%s %02X =%s%s%s%s%s%s%s%s\n",
-		label, udccr,
-		(udccr & UDCCR_REM) ? " rem" : "",
-		(udccr & UDCCR_RSTIR) ? " rstir" : "",
-		(udccr & UDCCR_SRM) ? " srm" : "",
-		(udccr & UDCCR_SUSIR) ? " susir" : "",
-		(udccr & UDCCR_RESIR) ? " resir" : "",
-		(udccr & UDCCR_RSM) ? " rsm" : "",
-		(udccr & UDCCR_UDA) ? " uda" : "",
-		(udccr & UDCCR_UDE) ? " ude" : "");
-}
-
-static void __maybe_unused
-dump_udccs0(const char *label)
-{
-	u32		udccs0 = UDCCS0;
-
-	DMSG("%s %s %02X =%s%s%s%s%s%s%s%s\n",
-		label, state_name[the_controller->ep0state], udccs0,
-		(udccs0 & UDCCS0_SA) ? " sa" : "",
-		(udccs0 & UDCCS0_RNE) ? " rne" : "",
-		(udccs0 & UDCCS0_FST) ? " fst" : "",
-		(udccs0 & UDCCS0_SST) ? " sst" : "",
-		(udccs0 & UDCCS0_DRWF) ? " dwrf" : "",
-		(udccs0 & UDCCS0_FTF) ? " ftf" : "",
-		(udccs0 & UDCCS0_IPR) ? " ipr" : "",
-		(udccs0 & UDCCS0_OPR) ? " opr" : "");
-}
-
-static void __maybe_unused
-dump_state(struct pxa2xx_udc *dev)
-{
-	u32		tmp;
-	unsigned	i;
-
-	DMSG("%s %s, uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
-		is_vbus_present() ? "host " : "disconnected",
-		state_name[dev->ep0state],
-		UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
-	dump_udccr("udccr");
-	if (dev->has_cfr) {
-		tmp = UDCCFR;
-		DMSG("udccfr %02X =%s%s\n", tmp,
-			(tmp & UDCCFR_AREN) ? " aren" : "",
-			(tmp & UDCCFR_ACM) ? " acm" : "");
-	}
-
-	if (!dev->driver) {
-		DMSG("no gadget driver bound\n");
-		return;
-	} else
-		DMSG("ep0 driver '%s'\n", dev->driver->driver.name);
-
-	if (!is_vbus_present())
-		return;
-
-	dump_udccs0 ("udccs0");
-	DMSG("ep0 IN %lu/%lu, OUT %lu/%lu\n",
-		dev->stats.write.bytes, dev->stats.write.ops,
-		dev->stats.read.bytes, dev->stats.read.ops);
-
-	for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) {
-		if (dev->ep [i].desc == NULL)
-			continue;
-		DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccs);
-	}
-}
-
-#else
-
-#define	dump_udccr(x)	do{}while(0)
-#define	dump_udccs0(x)	do{}while(0)
-#define	dump_state(x)	do{}while(0)
-
-#define UDC_DEBUG ((unsigned)0)
-
-#endif
-
-#define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
-
-#define ERR(stuff...)		pr_err("udc: " stuff)
-#define WARN(stuff...)		pr_warning("udc: " stuff)
-#define INFO(stuff...)		pr_info("udc: " stuff)
-
-
-#endif /* __LINUX_USB_GADGET_PXA2XX_H */
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index d0677f5..7228e85 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -1,8 +1,6 @@
 /*
  * RNDIS MSG parser
  *
- * Version:     $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $
- *
  * Authors:	Benedikt Spranger, Pengutronix
  *		Robert Schwebel, Pengutronix
  *
@@ -30,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/netdevice.h>
 
 #include <asm/io.h>
@@ -38,9 +37,7 @@
 #include <asm/unaligned.h>
 
 
-#undef	RNDIS_PM
-#undef	RNDIS_WAKEUP
-#undef	VERBOSE
+#undef	VERBOSE_DEBUG
 
 #include "rndis.h"
 
@@ -96,9 +93,6 @@ static const u32 oid_supported_list [] =
 	OID_GEN_MAXIMUM_TOTAL_SIZE,
 	OID_GEN_MEDIA_CONNECT_STATUS,
 	OID_GEN_PHYSICAL_MEDIUM,
-#if 0
-	OID_GEN_RNDIS_CONFIG_PARAMETER,
-#endif
 
 	/* the statistical stuff */
 	OID_GEN_XMIT_OK,
@@ -146,7 +140,14 @@ static const u32 oid_supported_list [] =
 #endif	/* RNDIS_OPTIONAL_STATS */
 
 #ifdef	RNDIS_PM
-	/* PM and wakeup are mandatory for USB: */
+	/* PM and wakeup are "mandatory" for USB, but the RNDIS specs
+	 * don't say what they mean ... and the NDIS specs are often
+	 * confusing and/or ambiguous in this context.  (That is, more
+	 * so than their specs for the other OIDs.)
+	 *
+	 * FIXME someone who knows what these should do, please
+	 * implement them!
+	 */
 
 	/* power management */
 	OID_PNP_CAPABILITIES,
@@ -173,6 +174,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	__le32			*outbuf;
 	int			i, count;
 	rndis_query_cmplt_type	*resp;
+	struct net_device	*net;
+	struct net_device_stats	*stats;
 
 	if (!r) return -ENOMEM;
 	resp = (rndis_query_cmplt_type *) r->buf;
@@ -194,6 +197,12 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	outbuf = (__le32 *) &resp[1];
 	resp->InformationBufferOffset = __constant_cpu_to_le32 (16);
 
+	net = rndis_per_dev_params[configNr].dev;
+	if (net->get_stats)
+		stats = net->get_stats(net);
+	else
+		stats = NULL;
+
 	switch (OID) {
 
 	/* general oids (table 4-1) */
@@ -350,11 +359,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	case OID_GEN_XMIT_OK:
 		if (rndis_debug > 1)
 			DBG("%s: OID_GEN_XMIT_OK\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (
-			    rndis_per_dev_params [configNr].stats->tx_packets -
-			    rndis_per_dev_params [configNr].stats->tx_errors -
-			    rndis_per_dev_params [configNr].stats->tx_dropped);
+		if (stats) {
+			*outbuf = cpu_to_le32(stats->tx_packets
+				- stats->tx_errors - stats->tx_dropped);
 			retval = 0;
 		}
 		break;
@@ -363,11 +370,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	case OID_GEN_RCV_OK:
 		if (rndis_debug > 1)
 			DBG("%s: OID_GEN_RCV_OK\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (
-			    rndis_per_dev_params [configNr].stats->rx_packets -
-			    rndis_per_dev_params [configNr].stats->rx_errors -
-			    rndis_per_dev_params [configNr].stats->rx_dropped);
+		if (stats) {
+			*outbuf = cpu_to_le32(stats->rx_packets
+				- stats->rx_errors - stats->rx_dropped);
 			retval = 0;
 		}
 		break;
@@ -376,9 +381,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	case OID_GEN_XMIT_ERROR:
 		if (rndis_debug > 1)
 			DBG("%s: OID_GEN_XMIT_ERROR\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->tx_errors);
+		if (stats) {
+			*outbuf = cpu_to_le32(stats->tx_errors);
 			retval = 0;
 		}
 		break;
@@ -387,9 +391,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	case OID_GEN_RCV_ERROR:
 		if (rndis_debug > 1)
 			DBG("%s: OID_GEN_RCV_ERROR\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->rx_errors);
+		if (stats) {
+			*outbuf = cpu_to_le32(stats->rx_errors);
 			retval = 0;
 		}
 		break;
@@ -397,150 +400,12 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	/* mandatory */
 	case OID_GEN_RCV_NO_BUFFER:
 		DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->rx_dropped);
-			retval = 0;
-		}
-		break;
-
-#ifdef	RNDIS_OPTIONAL_STATS
-	case OID_GEN_DIRECTED_BYTES_XMIT:
-		DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __func__);
-		/*
-		 * Aunt Tilly's size of shoes
-		 * minus antarctica count of penguins
-		 * divided by weight of Alpha Centauri
-		 */
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (
-				(rndis_per_dev_params [configNr]
-					.stats->tx_packets -
-				 rndis_per_dev_params [configNr]
-					 .stats->tx_errors -
-				 rndis_per_dev_params [configNr]
-					 .stats->tx_dropped)
-				* 123);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_DIRECTED_FRAMES_XMIT:
-		DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __func__);
-		/* dito */
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (
-				(rndis_per_dev_params [configNr]
-					.stats->tx_packets -
-				 rndis_per_dev_params [configNr]
-					 .stats->tx_errors -
-				 rndis_per_dev_params [configNr]
-					 .stats->tx_dropped)
-				/ 123);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_MULTICAST_BYTES_XMIT:
-		DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->multicast*1234);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_MULTICAST_FRAMES_XMIT:
-		DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->multicast);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_BROADCAST_BYTES_XMIT:
-		DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->tx_packets/42*255);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_BROADCAST_FRAMES_XMIT:
-		DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->tx_packets/42);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_DIRECTED_BYTES_RCV:
-		DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __func__);
-		*outbuf = __constant_cpu_to_le32 (0);
-		retval = 0;
-		break;
-
-	case OID_GEN_DIRECTED_FRAMES_RCV:
-		DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __func__);
-		*outbuf = __constant_cpu_to_le32 (0);
-		retval = 0;
-		break;
-
-	case OID_GEN_MULTICAST_BYTES_RCV:
-		DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->multicast * 1111);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_MULTICAST_FRAMES_RCV:
-		DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->multicast);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_BROADCAST_BYTES_RCV:
-		DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->rx_packets/42*255);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_BROADCAST_FRAMES_RCV:
-		DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->rx_packets/42);
+		if (stats) {
+			*outbuf = cpu_to_le32(stats->rx_dropped);
 			retval = 0;
 		}
 		break;
 
-	case OID_GEN_RCV_CRC_ERROR:
-		DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->rx_crc_errors);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-		DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __func__);
-		*outbuf = __constant_cpu_to_le32 (0);
-		retval = 0;
-		break;
-#endif	/* RNDIS_OPTIONAL_STATS */
-
 	/* ieee802.3 OIDs (table 4-3) */
 
 	/* mandatory */
@@ -592,9 +457,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	/* mandatory */
 	case OID_802_3_RCV_ERROR_ALIGNMENT:
 		DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->rx_frame_errors);
+		if (stats) {
+			*outbuf = cpu_to_le32(stats->rx_frame_errors);
 			retval = 0;
 		}
 		break;
@@ -613,64 +477,6 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 		retval = 0;
 		break;
 
-#ifdef	RNDIS_OPTIONAL_STATS
-	case OID_802_3_XMIT_DEFERRED:
-		DBG("%s: OID_802_3_XMIT_DEFERRED\n", __func__);
-		/* TODO */
-		break;
-
-	case OID_802_3_XMIT_MAX_COLLISIONS:
-		DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __func__);
-		/* TODO */
-		break;
-
-	case OID_802_3_RCV_OVERRUN:
-		DBG("%s: OID_802_3_RCV_OVERRUN\n", __func__);
-		/* TODO */
-		break;
-
-	case OID_802_3_XMIT_UNDERRUN:
-		DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __func__);
-		/* TODO */
-		break;
-
-	case OID_802_3_XMIT_HEARTBEAT_FAILURE:
-		DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __func__);
-		/* TODO */
-		break;
-
-	case OID_802_3_XMIT_TIMES_CRS_LOST:
-		DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __func__);
-		/* TODO */
-		break;
-
-	case OID_802_3_XMIT_LATE_COLLISIONS:
-		DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __func__);
-		/* TODO */
-		break;
-#endif	/* RNDIS_OPTIONAL_STATS */
-
-#ifdef	RNDIS_PM
-	/* power management OIDs (table 4-5) */
-	case OID_PNP_CAPABILITIES:
-		DBG("%s: OID_PNP_CAPABILITIES\n", __func__);
-
-		/* for now, no wakeup capabilities */
-		length = sizeof (struct NDIS_PNP_CAPABILITIES);
-		memset(outbuf, 0, length);
-		retval = 0;
-		break;
-	case OID_PNP_QUERY_POWER:
-		DBG("%s: OID_PNP_QUERY_POWER D%d\n", __func__,
-				get_unaligned_le32(buf) - 1);
-		/* only suspend is a real power state, and
-		 * it can't be entered by OID_PNP_SET_POWER...
-		 */
-		length = 0;
-		retval = 0;
-		break;
-#endif
-
 	default:
 		pr_warning("%s: query unknown OID 0x%08X\n",
 			 __func__, OID);
@@ -726,9 +532,6 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
 		 * what makes the packet flow start and stop, like
 		 * activating the CDC Ethernet altsetting.
 		 */
-#ifdef	RNDIS_PM
-update_linkstate:
-#endif
 		retval = 0;
 		if (*params->filter) {
 			params->state = RNDIS_DATA_INITIALIZED;
@@ -747,49 +550,6 @@ update_linkstate:
 		DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
 		retval = 0;
 		break;
-#if 0
-	case OID_GEN_RNDIS_CONFIG_PARAMETER:
-		{
-		struct rndis_config_parameter	*param;
-		param = (struct rndis_config_parameter *) buf;
-		DBG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
-			__func__,
-			min(cpu_to_le32(param->ParameterNameLength),80),
-			buf + param->ParameterNameOffset);
-		retval = 0;
-		}
-		break;
-#endif
-
-#ifdef	RNDIS_PM
-	case OID_PNP_SET_POWER:
-		/* The only real power state is USB suspend, and RNDIS requests
-		 * can't enter it; this one isn't really about power.  After
-		 * resuming, Windows forces a reset, and then SET_POWER D0.
-		 * FIXME ... then things go batty; Windows wedges itself.
-		 */
-		i = get_unaligned_le32(buf);
-		DBG("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1);
-		switch (i) {
-		case NdisDeviceStateD0:
-			*params->filter = params->saved_filter;
-			goto update_linkstate;
-		case NdisDeviceStateD3:
-		case NdisDeviceStateD2:
-		case NdisDeviceStateD1:
-			params->saved_filter = *params->filter;
-			retval = 0;
-			break;
-		}
-		break;
-
-#ifdef	RNDIS_WAKEUP
-	// no wakeup support advertised, so wakeup OIDs always fail:
-	//  - OID_PNP_ENABLE_WAKE_UP
-	//  - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN
-#endif
-
-#endif	/* RNDIS_PM */
 
 	default:
 		pr_warning("%s: set unknown OID 0x%08X, size %d\n",
@@ -807,8 +567,10 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
 {
 	rndis_init_cmplt_type	*resp;
 	rndis_resp_t            *r;
+	struct rndis_params	*params = rndis_per_dev_params + configNr;
 
-	if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
+	if (!params->dev)
+		return -ENOTSUPP;
 
 	r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));
 	if (!r)
@@ -826,7 +588,7 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
 	resp->Medium = __constant_cpu_to_le32 (RNDIS_MEDIUM_802_3);
 	resp->MaxPacketsPerTransfer = __constant_cpu_to_le32 (1);
 	resp->MaxTransferSize = cpu_to_le32 (
-		  rndis_per_dev_params [configNr].dev->mtu
+		  params->dev->mtu
 		+ sizeof (struct ethhdr)
 		+ sizeof (struct rndis_packet_msg_type)
 		+ 22);
@@ -834,10 +596,7 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
 	resp->AFListOffset = __constant_cpu_to_le32 (0);
 	resp->AFListSize = __constant_cpu_to_le32 (0);
 
-	if (rndis_per_dev_params [configNr].ack)
-		rndis_per_dev_params [configNr].ack (
-			rndis_per_dev_params [configNr].dev);
-
+	params->resp_avail(params->v);
 	return 0;
 }
 
@@ -845,9 +604,11 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
 {
 	rndis_query_cmplt_type *resp;
 	rndis_resp_t            *r;
+	struct rndis_params	*params = rndis_per_dev_params + configNr;
 
 	// DBG("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID));
-	if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
+	if (!params->dev)
+		return -ENOTSUPP;
 
 	/*
 	 * we need more memory:
@@ -878,9 +639,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
 	} else
 		resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
 
-	if (rndis_per_dev_params [configNr].ack)
-		rndis_per_dev_params [configNr].ack (
-			rndis_per_dev_params [configNr].dev);
+	params->resp_avail(params->v);
 	return 0;
 }
 
@@ -889,6 +648,7 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
 	u32			BufLength, BufOffset;
 	rndis_set_cmplt_type	*resp;
 	rndis_resp_t		*r;
+	struct rndis_params	*params = rndis_per_dev_params + configNr;
 
 	r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
 	if (!r)
@@ -898,7 +658,7 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
 	BufLength = le32_to_cpu (buf->InformationBufferLength);
 	BufOffset = le32_to_cpu (buf->InformationBufferOffset);
 
-#ifdef	VERBOSE
+#ifdef	VERBOSE_DEBUG
 	DBG("%s: Length: %d\n", __func__, BufLength);
 	DBG("%s: Offset: %d\n", __func__, BufOffset);
 	DBG("%s: InfoBuffer: ", __func__);
@@ -919,10 +679,7 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
 	else
 		resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
 
-	if (rndis_per_dev_params [configNr].ack)
-		rndis_per_dev_params [configNr].ack (
-			rndis_per_dev_params [configNr].dev);
-
+	params->resp_avail(params->v);
 	return 0;
 }
 
@@ -930,6 +687,7 @@ static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf)
 {
 	rndis_reset_cmplt_type	*resp;
 	rndis_resp_t		*r;
+	struct rndis_params	*params = rndis_per_dev_params + configNr;
 
 	r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));
 	if (!r)
@@ -942,10 +700,7 @@ static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf)
 	/* resent information */
 	resp->AddressingReset = __constant_cpu_to_le32 (1);
 
-	if (rndis_per_dev_params [configNr].ack)
-		rndis_per_dev_params [configNr].ack (
-			rndis_per_dev_params [configNr].dev);
-
+	params->resp_avail(params->v);
 	return 0;
 }
 
@@ -954,6 +709,7 @@ static int rndis_keepalive_response (int configNr,
 {
 	rndis_keepalive_cmplt_type	*resp;
 	rndis_resp_t			*r;
+	struct rndis_params	*params = rndis_per_dev_params + configNr;
 
 	/* host "should" check only in RNDIS_DATA_INITIALIZED state */
 
@@ -968,10 +724,7 @@ static int rndis_keepalive_response (int configNr,
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
 	resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
 
-	if (rndis_per_dev_params [configNr].ack)
-		rndis_per_dev_params [configNr].ack (
-			rndis_per_dev_params [configNr].dev);
-
+	params->resp_avail(params->v);
 	return 0;
 }
 
@@ -983,8 +736,9 @@ static int rndis_indicate_status_msg (int configNr, u32 status)
 {
 	rndis_indicate_status_msg_type	*resp;
 	rndis_resp_t			*r;
+	struct rndis_params	*params = rndis_per_dev_params + configNr;
 
-	if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED)
+	if (params->state == RNDIS_UNINITIALIZED)
 		return -ENOTSUPP;
 
 	r = rndis_add_response (configNr,
@@ -1000,9 +754,7 @@ static int rndis_indicate_status_msg (int configNr, u32 status)
 	resp->StatusBufferLength = __constant_cpu_to_le32 (0);
 	resp->StatusBufferOffset = __constant_cpu_to_le32 (0);
 
-	if (rndis_per_dev_params [configNr].ack)
-		rndis_per_dev_params [configNr].ack (
-			rndis_per_dev_params [configNr].dev);
+	params->resp_avail(params->v);
 	return 0;
 }
 
@@ -1029,7 +781,6 @@ void rndis_uninit (int configNr)
 
 	if (configNr >= RNDIS_MAX_CONFIGS)
 		return;
-	rndis_per_dev_params [configNr].used = 0;
 	rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED;
 
 	/* drain the response queue */
@@ -1142,21 +893,25 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
 	return -ENOTSUPP;
 }
 
-int rndis_register (int (* rndis_control_ack) (struct net_device *))
+int rndis_register(void (*resp_avail)(void *v), void *v)
 {
 	u8 i;
 
+	if (!resp_avail)
+		return -EINVAL;
+
 	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
 		if (!rndis_per_dev_params [i].used) {
 			rndis_per_dev_params [i].used = 1;
-			rndis_per_dev_params [i].ack = rndis_control_ack;
+			rndis_per_dev_params [i].resp_avail = resp_avail;
+			rndis_per_dev_params [i].v = v;
 			DBG("%s: configNr = %d\n", __func__, i);
 			return i;
 		}
 	}
 	DBG("failed\n");
 
-	return -1;
+	return -ENODEV;
 }
 
 void rndis_deregister (int configNr)
@@ -1169,16 +924,14 @@ void rndis_deregister (int configNr)
 	return;
 }
 
-int rndis_set_param_dev (u8 configNr, struct net_device *dev,
-			 struct net_device_stats *stats,
-			 u16 *cdc_filter)
+int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
 {
 	DBG("%s:\n", __func__ );
-	if (!dev || !stats) return -1;
+	if (!dev)
+		return -EINVAL;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
 	rndis_per_dev_params [configNr].dev = dev;
-	rndis_per_dev_params [configNr].stats = stats;
 	rndis_per_dev_params [configNr].filter = cdc_filter;
 
 	return 0;
@@ -1296,14 +1049,11 @@ int rndis_rm_hdr(struct sk_buff *skb)
 
 #ifdef	CONFIG_USB_GADGET_DEBUG_FILES
 
-static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof,
-		void *data)
+static int rndis_proc_show(struct seq_file *m, void *v)
 {
-	char *out = page;
-	int len;
-	rndis_params *param = (rndis_params *) data;
+	rndis_params *param = m->private;
 
-	out += snprintf (out, count,
+	seq_printf(m,
 			 "Config Nr. %d\n"
 			 "used      : %s\n"
 			 "state     : %s\n"
@@ -1326,25 +1076,13 @@ static int rndis_proc_read (char *page, char **start, off_t off, int count, int
 			 (param->media_state) ? 0 : param->speed*100,
 			 (param->media_state) ? "disconnected" : "connected",
 			 param->vendorID, param->vendorDescr);
-
-	len = out - page;
-	len -= off;
-
-	if (len < count) {
-		*eof = 1;
-		if (len <= 0)
-			return 0;
-	} else
-		len = count;
-
-	*start = page + off;
-	return len;
+	return 0;
 }
 
-static int rndis_proc_write (struct file *file, const char __user *buffer,
-		unsigned long count, void *data)
+static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
+		size_t count, loff_t *ppos)
 {
-	rndis_params *p = data;
+	rndis_params *p = PDE(file->f_path.dentry->d_inode)->data;
 	u32 speed = 0;
 	int i, fl_speed = 0;
 
@@ -1386,6 +1124,20 @@ static int rndis_proc_write (struct file *file, const char __user *buffer,
 	return count;
 }
 
+static int rndis_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, rndis_proc_show, PDE(inode)->data);
+}
+
+static const struct file_operations rndis_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= rndis_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= rndis_proc_write,
+};
+
 #define	NAME_TEMPLATE	"driver/rndis-%03d"
 
 static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
@@ -1403,7 +1155,9 @@ int __init rndis_init (void)
 
 		sprintf (name, NAME_TEMPLATE, i);
 		if (!(rndis_connect_state [i]
-				= create_proc_entry (name, 0660, NULL)))
+				= proc_create_data(name, 0660, NULL,
+					&rndis_proc_fops,
+					(void *)(rndis_per_dev_params + i))))
 		{
 			DBG("%s :remove entries", __func__);
 			while (i) {
@@ -1413,11 +1167,6 @@ int __init rndis_init (void)
 			DBG("\n");
 			return -EIO;
 		}
-
-		rndis_connect_state [i]->write_proc = rndis_proc_write;
-		rndis_connect_state [i]->read_proc = rndis_proc_read;
-		rndis_connect_state [i]->data = (void *)
-				(rndis_per_dev_params + i);
 #endif
 		rndis_per_dev_params [i].confignr = i;
 		rndis_per_dev_params [i].used = 0;
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
index 397b149..aac61df 100644
--- a/drivers/usb/gadget/rndis.h
+++ b/drivers/usb/gadget/rndis.h
@@ -1,8 +1,6 @@
 /*
  * RNDIS	Definitions for Remote NDIS
  *
- * Version:	$Id: rndis.h,v 1.15 2004/03/25 21:33:46 robert Exp $
- *
  * Authors:	Benedikt Spranger, Pengutronix
  *		Robert Schwebel, Pengutronix
  *
@@ -235,20 +233,19 @@ typedef struct rndis_params
 	const u8		*host_mac;
 	u16			*filter;
 	struct net_device	*dev;
-	struct net_device_stats *stats;
 
 	u32			vendorID;
 	const char		*vendorDescr;
-	int			(*ack) (struct net_device *);
+	void			(*resp_avail)(void *v);
+	void			*v;
 	struct list_head	resp_queue;
 } rndis_params;
 
 /* RNDIS Message parser and other useless functions */
 int  rndis_msg_parser (u8 configNr, u8 *buf);
-int  rndis_register (int (*rndis_control_ack) (struct net_device *));
+int  rndis_register(void (*resp_avail)(void *v), void *v);
 void rndis_deregister (int configNr);
 int  rndis_set_param_dev (u8 configNr, struct net_device *dev,
-			 struct net_device_stats *stats,
 			 u16 *cdc_filter);
 int  rndis_set_param_vendor (u8 configNr, u32 vendorID,
 			    const char *vendorDescr);
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 6b1ef48..29d13eb 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -35,7 +35,6 @@
 #include <linux/list.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <linux/version.h>
 #include <linux/clk.h>
 
 #include <linux/debugfs.h>
@@ -49,15 +48,14 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
-#include <asm/arch/irqs.h>
+#include <mach/irqs.h>
 
-#include <asm/arch/hardware.h>
-#include <asm/arch/regs-gpio.h>
+#include <mach/hardware.h>
+#include <mach/regs-gpio.h>
 
 #include <asm/plat-s3c24xx/regs-udc.h>
 #include <asm/plat-s3c24xx/udc.h>
 
-#include <asm/mach-types.h>
 
 #include "s3c2410_udc.h"
 
@@ -888,7 +886,7 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
 	}
 }
 
-#include <asm/arch/regs-irq.h>
+#include <mach/regs-irq.h>
 
 /*
  *	s3c2410_udc_irq - interrupt handler
diff --git a/drivers/usb/gadget/sa1100_udc.c b/drivers/usb/gadget/sa1100_udc.c
new file mode 100644
index 0000000..3a9f24f
--- /dev/null
+++ b/drivers/usb/gadget/sa1100_udc.c
@@ -0,0 +1,2421 @@
+/*
+ * SA1100 USB Device Controller (UDC) driver.
+ *
+ * Copyright (C) Compaq Computer Corporation, 1998, 1999
+ * Copyright (C) Extenex Corporation, 2001
+ * Copyright (C) David Brownell, 2003
+ * Copyright (C) Nick Bane, 2005, 2006, 2007
+ *   Many fragments from pxa2xx_udc.c and mach-sa1100 driver with various
+ *   GPL Copyright authors incl Russel king and Nicolas Pitre
+ *   Working port to 2.6.32-1 by N C Bane
+ *
+ * This file provides interrupt routing and overall coordination for the
+ * sa1100 USB endpoints: ep0, ep1out-bulk, ep2in-bulk, as well as device
+ * initialization and some parts of USB "Chapter 9" device behavior.
+ *
+ * It implements the "USB gadget controller" API, abstracting most hardware
+ * details so that drivers running on top of this API are mostly independent
+ * of hardware.  A key exception is that ep0 logic needs to understand which
+ * endpoints a given controller has, and their capabilities.  Also, hardware
+ * that doesn't fully support USB (like sa1100) may need workarounds in the
+ * protocols implemented by device functions.
+ *
+ * See linux/Documentation/arm/SA1100/SA1100_USB for more info, or the
+ * kerneldoc for the API exposed to gadget drivers.
+ *
+ */
+//#define DEBUG	1
+//#define	VERBOSE	1
+
+//#define SA1100_USB_DEBUG
+#ifdef SA1100_USB_DEBUG
+static int sa1100_usb_debug=0;
+#endif
+
+#define NCB_DMA_FIX
+#ifdef NCB_DMA_FIX
+// This is a clunky fix for dma alignemnt issues
+// It should probably be done better by someone more 
+// steeped in DMA lore
+#include <linux/slab.h>
+#define SEND_BUFFER_SIZE 4096	/* this is probably a bit big */
+#define RECEIVE_BUFFER_SIZE 256	/* 64 may be all that is necessary */
+static char *send_buffer=NULL;
+static char *receive_buffer=NULL;
+#endif
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/version.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <asm/unaligned.h>
+
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#if CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif
+
+#if defined(CONFIG_SA1100_BALLOON)
+#include <asm/arch/balloon2.h>
+#endif
+
+#if defined(CONFIG_SA1100_COLLIE)
+#include <asm/hardware/scoop.h>
+#include <asm/arch/collie.h>
+#endif
+
+#define	DRIVER_VERSION		__DATE__
+
+#define	DMA_ADDR_INVALID (~(dma_addr_t)0)
+
+
+static const char driver_name [] = "sa1100_udc";
+static const char driver_desc [] = "SA-1110 USB Device Controller";
+
+static const char ep0name [] = "ep0";
+
+#ifdef	DEBUG
+static char *type_string (u8 bmAttributes)
+{
+	switch ( (bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) {
+	case USB_ENDPOINT_XFER_BULK:	return "bulk";
+	//case USB_ENDPOINT_XFER_ISOC:	return "iso";
+	case USB_ENDPOINT_XFER_INT:	return "intr";
+	};
+	return "control";
+}
+#endif
+
+#include <linux/dma-mapping.h>
+struct usb_stats_t {
+	 unsigned long ep0_fifo_write_failures;
+	 unsigned long ep0_bytes_written;
+	 unsigned long ep0_fifo_read_failures;
+	 unsigned long ep0_bytes_read;
+};
+
+struct usb_info_t {
+	dma_regs_t *dmaregs_tx, *dmaregs_rx;
+	int state;
+	unsigned char address;
+	struct usb_stats_t stats;
+};
+
+enum { kError=-1, kEvSuspend=0, kEvReset=1,
+	   kEvResume=2, kEvAddress=3, kEvConfig=4, kEvDeConfig=5 };
+int usbctl_next_state_on_event( int event ) {
+    return 0;
+}
+static struct usb_info_t usbd_info;
+
+/* receiver */
+void ep1_reset(void);
+void ep1_stall(void);
+int sa1100_usb_recv (struct usb_request *req, void (*callback) (int,int));
+
+/* xmitter */
+void ep2_reset(void);
+void ep2_stall(void);
+int sa1100_usb_send (struct usb_request *req, void (*callback) (int,int));
+
+/* UDC register utility functions */
+#define UDC_write(reg, val) { \
+	int i = 10000; \
+	do { \
+	  	(reg) = (val); \
+		if (i-- <= 0) { \
+			printk( "%s [%d]: write %#x to %p (%#lx) failed\n", \
+				__FUNCTION__, __LINE__, (val), &(reg), (reg)); \
+			break; \
+		} \
+	} while((reg) != (val)); \
+}
+
+#define UDC_set(reg, val) { \
+	int i = 10000; \
+	do { \
+		(reg) |= (val); \
+		if (i-- <= 0) { \
+			printk( "%s [%d]: set %#x of %p (%#lx) failed\n", \
+				__FUNCTION__, __LINE__, (val), &(reg), (reg)); \
+			break; \
+		} \
+	} while(!((reg) & (val))); \
+}
+
+#define UDC_clear(reg, val) { \
+	int i = 10000; \
+	do { \
+		(reg) &= ~(val); \
+		if (i-- <= 0) { \
+			printk( "%s [%d]: clear %#x of %p (%#lx) failed\n", \
+				__FUNCTION__, __LINE__, (val), &(reg), (reg)); \
+			break; \
+		} \
+	} while((reg) & (val)); \
+}
+
+#define UDC_flip(reg, val) { \
+	int i = 10000; \
+	(reg) = (val); \
+	do { \
+		(reg) = (val); \
+		if (i-- <= 0) { \
+			printk( "%s [%d]: flip %#x of %p (%#lx) failed\n", \
+				__FUNCTION__, __LINE__, (val), &(reg), (reg)); \
+			break; \
+		} \
+	} while(((reg) & (val))); \
+}
+
+#include "sa1100_udc.h"
+
+static struct sa1100_udc	*the_controller;
+static void nuke (struct sa1100_ep *, int status);
+static void done (struct sa1100_ep *ep, struct sa1100_request *req, int status);
+static inline void ep0_idle (struct sa1100_udc *dev)
+{
+	dev->ep0state = EP0_IDLE;
+}
+
+// ep0 handlers
+
+// 1 == lots of trace noise,  0 = only "important' stuff
+#define VERBOSITY 0
+
+#if 1 && !defined( ASSERT )
+#  define ASSERT(expr) \
+          if(!(expr)) { \
+          printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+          #expr,__FILE__,__FUNCTION__,__LINE__); \
+          }
+#else
+#  define ASSERT(expr)
+#endif
+
+#if VERBOSITY
+#define PRINTKD(fmt, args...) printk( fmt , ## args)
+#else
+#define PRINTKD(fmt, args...)
+#endif
+
+/* other subroutines */
+unsigned int (*wrint)(void);
+void ep0_int_hndlr( void );
+static void ep0_queue(void *buf, unsigned int req, unsigned int act);
+static void write_fifo( void );
+static int read_fifo( struct usb_ctrlrequest * p );
+
+/* some voodo helpers  01Mar01ww */
+static void set_cs_bits( __u32 set_bits );
+static void set_de( void );
+static void set_ipr( void );
+static void set_ipr_and_de( void );
+static bool clear_opr( void );
+
+/***************************************************************************
+Inline Helpers
+***************************************************************************/
+
+/* Data extraction from usb_request_t fields */
+enum { kTargetDevice=0, kTargetInterface=1, kTargetEndpoint=2 };
+static inline int request_target( __u8 b ) { return (int) ( b & 0x0F); }
+
+static inline int windex_to_ep_num( __u16 w ) { return (int) ( w & 0x000F); }
+inline int type_code_from_request( __u8 by ) { return (( by >> 4 ) & 3); }
+
+/* following is hook for self-powered flag in GET_STATUS. Some devices
+   .. might like to override and return real info */
+static inline bool self_powered_hook( void ) { return true; }
+
+#if VERBOSITY
+/* "pcs" == "print control status" */
+static inline void pcs( void )
+{
+	 __u32 foo = Ser0UDCCS0;
+	 printk( "%8.8X: %s %s %s %s\n",
+			 foo,
+			 foo & UDCCS0_SE ? "SE" : "",
+			 foo & UDCCS0_OPR ? "OPR" : "",
+			 foo & UDCCS0_IPR ? "IPR" : "",
+			 foo & UDCCS0_SST ? "SST" : ""
+	 );
+}
+static inline void preq( struct usb_ctrlrequest * pReq )
+{
+	 static char * tnames[] = { "dev", "intf", "ep", "oth" };
+	 static char * rnames[] = { "std", "class", "vendor", "???" };
+	 char * psz;
+	 switch( pReq->bRequest ) {
+	 case USB_REQ_GET_STATUS: psz = "get stat"; break;
+	 case USB_REQ_CLEAR_FEATURE: psz = "clr feat"; break;
+	 case USB_REQ_SET_FEATURE: psz = "set feat"; break;
+	 case USB_REQ_SET_ADDRESS: psz = "set addr"; break;
+	 case USB_REQ_GET_DESCRIPTOR: psz = "get desc"; break;
+	 case USB_REQ_SET_DESCRIPTOR: psz = "set desc"; break;
+	 case USB_REQ_GET_CONFIGURATION: psz = "get cfg"; break;
+	 case USB_REQ_SET_CONFIGURATION: psz = "set cfg"; break;
+	 case USB_REQ_GET_INTERFACE: psz = "get intf"; break;
+	 case USB_REQ_SET_INTERFACE: psz = "set intf"; break;
+	 default: psz = "unknown"; break;
+	 }
+	 printk( "- [%s: %s req to %s. dir=%s]\n", psz,
+			 rnames[ (pReq->bRequestType >> 5) & 3 ],
+			 tnames[ pReq->bRequestType & 3 ],
+			 ( pReq->bRequestType & 0x80 ) ? "in" : "out" );
+}
+
+static inline void usbctl_dump_request(const char *prefix, const struct usb_ctrlrequest *req)
+{
+	printk("%s: bRequestType=0x%02x bRequest=0x%02x "
+		"wValue=0x%04x wIndex=0x%04x wLength=0x%04x\n",
+		prefix, req->bRequestType, req->bRequest,
+		le16_to_cpu(req->wValue), le16_to_cpu(req->wIndex),
+		le16_to_cpu(req->wLength));
+}
+#else
+static inline void pcs( void ){}
+//static inline void preq( void ){}
+static inline void preq( void *x ){}
+static inline void usbctl_dump_request(const char *prefix, const struct usb_ctrlrequest *req) {}
+#endif
+
+/***************************************************************************
+Globals
+***************************************************************************/
+static const char pszMe[] = "usbep0: ";
+
+
+/* global write struct to keep write
+   ..state around across interrupts */
+static struct {
+		unsigned char *p;
+		int bytes_left;
+} wr;
+
+/***************************************************************************
+Public Interface
+***************************************************************************/
+
+/* reset received from HUB (or controller just went nuts and reset by itself!)
+  so udc core has been reset, track this state here  */
+void ep0_reset(void)
+{
+	/* reset state machine */
+	wr.p = NULL;
+	wr.bytes_left = 0;
+	usbd_info.address=0;
+// needed?
+	Ser0UDCAR = 0;
+}
+
+
+/* handle interrupt for endpoint zero */
+
+inline void ep0_clear_write(void) {
+	wr.p = NULL;
+	wr.bytes_left = 0;
+}
+
+/* this is a config packet parser based on that from the updated HH 2.6 udc */
+static void ep0_read_packet(void)
+{
+	 unsigned char status_buf[2];  /* returned in GET_STATUS */
+	 struct usb_ctrlrequest req;
+	 int request_type;
+	 int n;
+	 __u32 address;
+	 __u32 in, out;
+
+	 /* reset previous count */
+	 the_controller->ep0_req_len=-1;
+
+	 /* read the setup request */
+	 n = read_fifo( &req );
+	 usbctl_dump_request("ep0_read_packet",&req);
+
+	 if ( n != sizeof( req ) ) {
+		  printk( "%ssetup begin: fifo READ ERROR wanted %d bytes got %d. "
+				  " Stalling out...\n",
+				  pszMe, sizeof( req ), n );
+		  /* force stall, serviced out */
+		  set_cs_bits( UDCCS0_FST | UDCCS0_SO  );
+		  goto sh_sb_end;
+	 }
+
+	 /* Is it a standard request? (not vendor or class request) */
+	 request_type = type_code_from_request( req.bRequestType );
+	 if ( request_type != 0 ) {
+		  printk( "%ssetup begin: unsupported bRequestType: %d ignored\n",
+				  pszMe, request_type );
+		  set_cs_bits( UDCCS0_DE | UDCCS0_SO );
+		  goto sh_sb_end;
+	 }
+
+	/* save requested reply size */
+	the_controller->ep0_req_len=le16_to_cpu(req.wLength);
+	PRINTKD("%s: request length is %d\n",__FUNCTION__,the_controller->ep0_req_len);
+
+#if VERBOSITY
+	 {
+	 unsigned char * pdb = (unsigned char *) &req;
+	 PRINTKD( "%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X ",
+			 pdb[0], pdb[1], pdb[2], pdb[3], pdb[4], pdb[5], pdb[6], pdb[7]
+		  );
+	 preq( &req );
+	 }
+#endif
+
+	 /* Handle it */
+	 switch( req.bRequest ) {
+
+		  /* This first bunch have no data phase */
+
+	 case USB_REQ_SET_ADDRESS:
+		  address = (__u32) (req.wValue & 0x7F);
+		  /* when SO and DE sent, UDC will enter status phase and ack,
+			 ..propagating new address to udc core. Next control transfer
+			 ..will be on the new address. You can't see the change in a
+			 ..read back of CAR until then. (about 250us later, on my box).
+			 ..The original Intel driver sets S0 and DE and code to check
+			 ..that address has propagated here. I tried this, but it
+			 ..would only work sometimes! The rest of the time it would
+			 ..never propagate and we'd spin forever. So now I just set
+			 ..it and pray...
+		  */
+		  Ser0UDCAR = address;
+		  usbd_info.address = address;
+		  usbctl_next_state_on_event( kEvAddress );
+		  set_cs_bits( UDCCS0_SO | UDCCS0_DE );  /* no data phase */
+		  printk( "%sI have been assigned address: %d\n", pszMe, address );
+		  break;
+
+
+	 case USB_REQ_SET_CONFIGURATION:
+		  if ( req.wValue == 1 ) {
+			   /* configured */
+			   if (usbctl_next_state_on_event( kEvConfig ) != kError) {
+				/* (re)set the out and in max packet sizes */
+				PRINTKD( "%s: calling the_controller.driver->setup with SET_CONFIGURATION\n", __FUNCTION__ );
+				the_controller->driver->setup(&the_controller->gadget, &req);
+					in  = __le16_to_cpu( the_controller->ep[1].ep.maxpacket );
+					out = __le16_to_cpu( the_controller->ep[2].ep.maxpacket );
+					Ser0UDCOMP = ( out - 1 );
+					Ser0UDCIMP = ( in - 1 );
+				// we are configured
+				usbd_info.state = USB_STATE_CONFIGURED;
+				// enable rx and tx interrupts
+				Ser0UDCCR &= ~(UDCCR_RIM | UDCCR_TIM);
+
+				printk( "%sConfigured (OMP=%8.8X IMP=%8.8X)\n", pszMe, out, in );
+				break;
+			   }
+		  } else if ( req.wValue == 0 ) {
+			   /* de-configured */
+			   if (usbctl_next_state_on_event( kEvDeConfig ) != kError )
+					printk( "%sDe-Configured\n", pszMe );
+			usbd_info.state = 0;
+			Ser0UDCCR |= UDCCR_RIM | UDCCR_TIM;
+			ep1_reset ();
+			ep2_reset ();
+			printk("%s: de-configured. Tx and Rx interrupts disabled. ep1 and ep2 reset\n",__FUNCTION__);
+		  } else {
+			   printk( "%ssetup phase: Unknown "
+					   "\"set configuration\" data %d\n",
+					   pszMe, req.wValue );
+		  }
+		  set_cs_bits( UDCCS0_SO | UDCCS0_DE );  /* no data phase */
+		  break;
+
+	 case USB_REQ_CLEAR_FEATURE:
+		  /* could check data length, direction...26Jan01ww */
+		  if ( req.wValue == 0 ) { /* clearing ENDPOINT_HALT/STALL */
+			   int ep = windex_to_ep_num( req.wIndex );
+			   if ( ep == 1 ) {
+					printk( "%sclear feature \"endpoint halt\" "
+							" on receiver\n", pszMe );
+					ep1_reset();
+			   }
+			   else if ( ep == 2 ) {
+					printk( "%sclear feature \"endpoint halt\" "
+							"on xmitter\n", pszMe );
+					ep2_reset();
+			   } else {
+					printk( "%sclear feature \"endpoint halt\" "
+							"on unsupported ep # %d\n",
+							pszMe, ep );
+			   }
+		  } else {
+			   printk( "%sUnsupported feature selector (%d) "
+					   "in clear feature. Ignored.\n" ,
+					   pszMe, req.wValue );
+		  }
+		  set_cs_bits( UDCCS0_SO | UDCCS0_DE );  /* no data phase */
+		  break;
+
+	 case USB_REQ_SET_FEATURE:
+		  if ( req.wValue == 0 ) { /* setting ENDPOINT_HALT/STALL */
+			   int ep = windex_to_ep_num( req.wValue );
+			   if ( ep == 1 ) {
+					printk( "%set feature \"endpoint halt\" "
+							"on receiver\n", pszMe );
+					ep1_stall();
+			   }
+			   else if ( ep == 2 ) {
+					printk( "%sset feature \"endpoint halt\" "
+							" on xmitter\n", pszMe );
+					ep2_stall();
+			   } else {
+					printk( "%sset feature \"endpoint halt\" "
+							"on unsupported ep # %d\n",
+							pszMe, ep );
+			   }
+		  }
+		  else {
+			   printk( "%sUnsupported feature selector "
+					   "(%d) in set feature\n",
+					   pszMe, req.wValue );
+		  }
+		  set_cs_bits( UDCCS0_SO | UDCCS0_DE );  /* no data phase */
+		  break;
+
+		  /* The rest have a data phase that writes back to the host */
+	 case USB_REQ_GET_STATUS:
+		  /* return status bit flags */
+		  status_buf[0] = status_buf[1] = 0;
+		  n = request_target(req.bRequestType);
+		  switch( n ) {
+		  case kTargetDevice:
+			   if ( self_powered_hook() )
+					status_buf[0] |= 1;
+			   break;
+		  case kTargetInterface:
+			   break;
+		  case kTargetEndpoint:
+			   /* return stalled bit */
+			   n = windex_to_ep_num( req.wIndex );
+			   if ( n == 1 )
+					status_buf[0] |= (Ser0UDCCS1 & UDCCS1_FST) >> 4;
+			   else if ( n == 2 )
+					status_buf[0] |= (Ser0UDCCS2 & UDCCS2_FST) >> 5;
+			   else {
+					printk( "%sUnknown endpoint (%d) "
+							"in GET_STATUS\n", pszMe, n );
+			   }
+			   break;
+		  default:
+			   printk( "%sUnknown target (%d) in GET_STATUS\n",
+					   pszMe, n );
+			   /* fall thru */
+			   break;
+		  }
+		  PRINTKD("%s: GET_STATUS writing %d\n",__FUNCTION__,req.wLength);
+		  ep0_queue( status_buf, req.wLength, sizeof( status_buf ));
+		  break;
+	 case USB_REQ_GET_DESCRIPTOR:
+		  PRINTKD( "%s: calling the_controller.driver->setup with GET_DESCRIPTOR\n", __FUNCTION__ );
+		  the_controller->driver->setup(&the_controller->gadget, &req);
+		  break;
+	 case USB_REQ_GET_CONFIGURATION:
+		  PRINTKD( "%s: calling the_controller.driver->setup with GET_CONFIGURATION\n", __FUNCTION__ );
+		  the_controller->driver->setup(&the_controller->gadget, &req);
+		  break;
+	 case USB_REQ_GET_INTERFACE:
+		  PRINTKD( "%s: calling the_controller->driver->setup with GET_INTERFACE\n", __FUNCTION__ );
+		  the_controller->driver->setup(&the_controller->gadget, &req);
+		  break;
+	 case USB_REQ_SET_INTERFACE:
+		  PRINTKD( "%s: calling the_controller->driver->setup with SET_INTERFACE\n", __FUNCTION__ );
+		  the_controller->driver->setup(&the_controller->gadget, &req);
+		  break;
+	 default :
+		  printk("%sunknown request 0x%x\n", pszMe, req.bRequest);
+		  break;
+	 } /* switch( bRequest ) */
+
+sh_sb_end:
+	 return;
+
+}
+
+void ep0_int_hndlr(void)
+{
+	u32 cs_reg_in;
+
+	pcs();
+
+	cs_reg_in = Ser0UDCCS0;
+
+	/*
+	 * If "setup end" has been set, the usb controller has terminated
+	 * a setup transaction before we set DE. This happens during
+	 * enumeration with some hosts. For example, the host will ask for
+	 * our device descriptor and specify a return of 64 bytes. When we
+	 * hand back the first 8, the host will know our max packet size
+	 * and turn around and issue a new setup immediately. This causes
+	 * the UDC to auto-ack the new setup and set SE. We must then
+	 * "unload" (process) the new setup, which is what will happen
+	 * after this preamble is finished executing.
+	 */
+	if (cs_reg_in & UDCCS0_SE) {
+		PRINTKD("UDC: early termination of setup\n");
+
+		/*
+		 * Clear setup end
+		 */
+		set_cs_bits(UDCCS0_SSE);
+
+		/*
+		 * Clear any pending write.
+		 */
+		ep0_clear_write();
+	}
+
+	/*
+	 * UDC sent a stall due to a protocol violation.
+	 */
+	if (cs_reg_in & UDCCS0_SST) {
+		PRINTKD("UDC: write_preamble: UDC sent stall\n");
+
+		/*
+		 * Clear sent stall
+		 */
+		set_cs_bits(UDCCS0_SST);
+
+		/*
+		 * Clear any pending write.
+		 */
+		ep0_clear_write();
+	}
+
+	switch (cs_reg_in & (UDCCS0_OPR | UDCCS0_IPR)) {
+	case UDCCS0_OPR | UDCCS0_IPR:
+		PRINTKD("UDC: write_preamble: see OPR. Stopping write to "
+			"handle new SETUP\n");
+
+		/*
+		 * very rarely, you can get OPR and
+		 * leftover IPR. Try to clear
+		 */
+		UDC_clear(Ser0UDCCS0, UDCCS0_IPR);
+
+		/*
+		 * Clear any pending write.
+		 */
+		ep0_clear_write();
+
+		/*FALLTHROUGH*/
+	case UDCCS0_OPR:
+		/*
+		 * A new setup request is pending.  Handle
+		 * it. Note that we don't try to read a
+		 * packet if SE was set and OPR is clear.
+		 */
+		ep0_read_packet();
+		break;
+
+	case 0:
+		// if data pending ...
+		if (wr.p) {
+			unsigned int cs_bits = 0;
+			if (wr.bytes_left != 0) {
+				/*
+				 * More data to go
+				 */
+				write_fifo();
+				// packet ready
+				cs_bits |= UDCCS0_IPR;
+			}
+
+			if (wr.bytes_left == 0) {
+				/*
+				 * All data sent.
+				 */
+				cs_bits |= wrint();
+				// a null packet may be following
+				if (!wrint)
+				    ep0_clear_write();
+			}
+			set_cs_bits(cs_bits);
+		}
+		else
+		    PRINTKD("%s: No data - probably an ACK\n",__FUNCTION__);
+		break;
+
+	case UDCCS0_IPR:
+		PRINTKD("UDC: IPR set, not writing\n");
+		break;
+	}
+
+	pcs();
+	PRINTKD( "-end-\n" );
+}
+
+static unsigned int ep0_sh_write_data(void)
+{
+	/*
+	 * If bytes left is zero, we are coming in on the
+	 * interrupt after the last packet went out. And
+	 * we know we don't have to empty packet this
+	 * transfer so just set DE and we are done
+	 */
+	PRINTKD("UDC: normal packet ended\n");
+	wrint=NULL;
+	return UDCCS0_DE;
+}
+
+static unsigned int ep0_sh_write_with_empty_packet(void)
+{
+	/*
+	 * If bytes left is zero, we are coming in on the
+	 * interrupt after the last packet went out.
+	 * We must do short packet suff, so set DE and IPR
+	 */
+	PRINTKD("UDC: short packet sent\n");
+	wrint=NULL;
+	return UDCCS0_IPR | UDCCS0_DE;
+}
+
+static unsigned int ep0_sh_write_data_then_empty_packet(void)
+{
+	PRINTKD("UDC: last packet full. Send empty packet next\n");
+	wrint=ep0_sh_write_with_empty_packet;
+	return 0;
+}
+
+static void ep0_queue(void *buf, unsigned int len, unsigned int req_len)
+{
+	__u32 cs_reg_bits = UDCCS0_IPR;
+
+	PRINTKD("a=%d r=%d\n", len, req_len);
+
+	if (len == 0) {
+	    // no output packet to wait for
+	    PRINTKD("%s: zero byte packet being queued. Setting DE and OPR end exiting\n",__FUNCTION__);
+	    set_cs_bits(UDCCS0_DE | UDCCS0_SO);
+	    return;
+	}
+
+	/*
+	 * thou shalt not enter data phase until
+	 * Out Packet Ready is clear
+	 */
+	if (!clear_opr()) {
+		printk("UDC: SO did not clear OPR\n");
+		set_cs_bits(UDCCS0_DE | UDCCS0_SO);
+		return;
+	}
+
+	// note data to xmit stored
+	wr.p=buf;
+	wr.bytes_left=min(len, req_len);
+
+	// write the first block
+	write_fifo();
+
+	// done already?
+	if (wr.bytes_left == 0) {
+		/*
+		 * out in one, so data end
+		 */
+		cs_reg_bits |= UDCCS0_DE;
+		ep0_clear_write();
+	// rest is a shorter than expected reply?
+	} else if (len < req_len) {
+		/*
+		 * we are going to short-change host
+		 * so need nul to not stall
+		 */
+		 if (len % 8) {
+		    PRINTKD("%s: %d more to go ending in a short packet.\n",__FUNCTION__,wr.bytes_left);
+		    wrint=ep0_sh_write_with_empty_packet;
+		}
+		// unless we are on a packet boundary. Then send full packet plus null packet.
+		else {
+		    PRINTKD("%s: %d more to go then add empty packet.\n",__FUNCTION__,wr.bytes_left);
+		    wrint=ep0_sh_write_data_then_empty_packet;
+		}
+	} else {
+		/*
+		 * we have as much or more than requested
+		 */
+		PRINTKD("%s: %d more to go.\n",__FUNCTION__,wr.bytes_left);
+		wrint=ep0_sh_write_data;
+	}
+
+	/*
+	 * note: IPR was set uncondtionally at start of routine
+	 */
+	set_cs_bits(cs_reg_bits);
+}
+
+/*
+ * write_fifo()
+ * Stick bytes in the 8 bytes endpoint zero FIFO.
+ * This version uses a variety of tricks to make sure the bytes
+ * are written correctly. 1. The count register is checked to
+ * see if the byte went in, and the write is attempted again
+ * if not. 2. An overall counter is used to break out so we
+ * don't hang in those (rare) cases where the UDC reverses
+ * direction of the FIFO underneath us without notification
+ * (in response to host aborting a setup transaction early).
+ *
+ */
+static void write_fifo( void )
+{
+	int bytes_this_time = min(wr.bytes_left, 8);
+	int bytes_written = 0;
+
+	PRINTKD( "WF=%d: ", bytes_this_time );
+
+	while( bytes_this_time-- ) {
+		unsigned int cwc;
+		int i;
+		 PRINTKD( "%2.2X ", *wr.p );
+		cwc = Ser0UDCWC & 15;
+		 i = 10;
+		 do {
+			  Ser0UDCD0 = *wr.p;
+			  udelay( 20 );  /* voodo 28Feb01ww */
+		 } while( (Ser0UDCWC &15) == cwc && --i );
+
+		 if ( i == 0 ) {
+			  printk( "%swrite_fifo: write failure\n", pszMe );
+			  usbd_info.stats.ep0_fifo_write_failures++;
+		 }
+
+		 wr.p++;
+		 bytes_written++;
+	}
+	wr.bytes_left -= bytes_written;
+
+	/* following propagation voodo so maybe caller writing IPR in
+	   ..a moment might actually get it to stick 28Feb01ww */
+	udelay( 300 );
+
+	usbd_info.stats.ep0_bytes_written += bytes_written;
+	PRINTKD( "L=%d WCR=%8.8lX\n", wr.bytes_left, Ser0UDCWC );
+}
+/*
+ * read_fifo()
+ * Read 1-8 bytes out of FIFO and put in request.
+ * Called to do the initial read of setup requests
+ * from the host. Return number of bytes read.
+ *
+ * Like write fifo above, this driver uses multiple
+ * reads checked agains the count register with an
+ * overall timeout.
+ *
+ */
+static int
+read_fifo( struct usb_ctrlrequest * request )
+{
+	int bytes_read = 0;
+	int fifo_count;
+
+	unsigned char * pOut = (unsigned char*) request;
+
+	fifo_count = ( Ser0UDCWC & 0xFF );
+
+	ASSERT( fifo_count <= 8 );
+	PRINTKD( "RF=%d ", fifo_count );
+
+	while( fifo_count-- ) {
+		unsigned int cwc;
+		int i;
+
+		cwc = Ser0UDCWC & 15;
+
+		 i = 10;
+		 do {
+			  *pOut = (unsigned char) Ser0UDCD0;
+			  udelay( 20 );
+		 } while( ( Ser0UDCWC & 15 ) == cwc && --i );
+
+		 if ( i == 0 ) {
+			  printk( "%sread_fifo(): read failure\n", pszMe );
+			  usbd_info.stats.ep0_fifo_read_failures++;
+		 }
+		 pOut++;
+		 bytes_read++;
+	}
+
+	PRINTKD( "fc=%d\n", bytes_read );
+	usbd_info.stats.ep0_bytes_read++;
+	return bytes_read;
+}
+
+/* some voodo I am adding, since the vanilla macros just aren't doing it  1Mar01ww */
+
+#define ABORT_BITS ( UDCCS0_SST | UDCCS0_SE )
+#define OK_TO_WRITE (!( Ser0UDCCS0 & ABORT_BITS ))
+#define BOTH_BITS (UDCCS0_IPR | UDCCS0_DE)
+
+static void set_cs_bits( __u32 bits )
+{
+	 if ( bits & ( UDCCS0_SO | UDCCS0_SSE | UDCCS0_FST | UDCCS0_SST) )
+		  Ser0UDCCS0 = bits;
+	 else if ( (bits & BOTH_BITS) == BOTH_BITS )
+		  set_ipr_and_de();
+	 else if ( bits & UDCCS0_IPR )
+		  set_ipr();
+	 else if ( bits & UDCCS0_DE )
+		  set_de();
+}
+
+static void set_de( void )
+{
+	 int i = 1;
+	 while( 1 ) {
+		  if ( OK_TO_WRITE ) {
+				Ser0UDCCS0 |= UDCCS0_DE;
+		  } else {
+			   PRINTKD( "%sQuitting set DE because SST or SE set\n", pszMe );
+			   break;
+		  }
+		  if ( Ser0UDCCS0 & UDCCS0_DE )
+			   break;
+		  udelay( i );
+		  if ( ++i == 50  ) {
+			   printk( "%sDangnabbbit! Cannot set DE! (DE=%8.8X CCS0=%8.8lX)\n",
+					   pszMe, UDCCS0_DE, Ser0UDCCS0 );
+			   break;
+		  }
+	 }
+}
+
+static void set_ipr( void )
+{
+	 int i = 1;
+	 while( 1 ) {
+		  if ( OK_TO_WRITE ) {
+				Ser0UDCCS0 |= UDCCS0_IPR;
+		  } else {
+			   PRINTKD( "%sQuitting set IPR because SST or SE set\n", pszMe );
+			   break;
+		  }
+		  if ( Ser0UDCCS0 & UDCCS0_IPR )
+			   break;
+		  udelay( i );
+		  if ( ++i == 50  ) {
+			   printk( "%sDangnabbbit! Cannot set IPR! (IPR=%8.8X CCS0=%8.8lX)\n",
+					   pszMe, UDCCS0_IPR, Ser0UDCCS0 );
+			   break;
+		  }
+	 }
+}
+
+static void set_ipr_and_de( void )
+{
+	 int i = 1;
+	 while( 1 ) {
+		  if ( OK_TO_WRITE ) {
+			   Ser0UDCCS0 |= BOTH_BITS;
+		  } else {
+			   PRINTKD( "%sQuitting set IPR/DE because SST or SE set\n", pszMe );
+			   break;
+		  }
+		  if ( (Ser0UDCCS0 & BOTH_BITS) == BOTH_BITS)
+			   break;
+		  udelay( i );
+		  if ( ++i == 50  ) {
+			   printk( "%sDangnabbbit! Cannot set DE/IPR! (DE=%8.8X IPR=%8.8X CCS0=%8.8lX)\n",
+					   pszMe, UDCCS0_DE, UDCCS0_IPR, Ser0UDCCS0 );
+			   break;
+		  }
+	 }
+}
+
+static bool clear_opr( void )
+{
+	 int i = 10000;
+	 bool is_clear;
+	 do {
+		  Ser0UDCCS0 = UDCCS0_SO;
+		  is_clear  = ! ( Ser0UDCCS0 & UDCCS0_OPR );
+		  if ( i-- <= 0 ) {
+			   printk( "%sclear_opr(): failed\n", pszMe );
+			   break;
+		  }
+	 } while( ! is_clear );
+	 return is_clear;
+}
+
+
+
+// ep1 handlers
+
+static char *ep1_buf;
+static int ep1_len;
+static void (*ep1_callback)(int flag, int size);
+static char *ep1_curdmabuf;
+static dma_addr_t ep1_curdmapos;
+static int ep1_curdmalen;
+static int ep1_remain;
+static int ep1_used;
+
+static dma_regs_t *dmaregs_rx = NULL;
+static int rx_pktsize;
+
+static int naking;
+
+static void
+ep1_start(void)
+{
+	sa1100_reset_dma(dmaregs_rx);
+	if (!ep1_curdmalen) {
+	  	ep1_curdmalen = rx_pktsize;
+		if (ep1_curdmalen > ep1_remain)
+			ep1_curdmalen = ep1_remain;
+		ep1_curdmapos = dma_map_single(NULL, ep1_curdmabuf, ep1_curdmalen,
+					       DMA_FROM_DEVICE);
+	}
+
+	UDC_write( Ser0UDCOMP, ep1_curdmalen-1 );
+
+	sa1100_start_dma(dmaregs_rx, ep1_curdmapos, ep1_curdmalen);
+
+	if ( naking ) {
+		/* turn off NAK of OUT packets, if set */
+		UDC_flip( Ser0UDCCS1, UDCCS1_RPC );
+		naking = 0;
+	}
+}
+
+static void
+ep1_done(int flag)
+{
+	int size = ep1_len - ep1_remain;
+
+	if (!ep1_len)
+		return;
+	if (ep1_curdmalen)
+		dma_unmap_single(NULL, ep1_curdmapos, ep1_curdmalen,
+				 DMA_FROM_DEVICE);
+	ep1_len = ep1_curdmalen = 0;
+	if (ep1_callback)
+		ep1_callback(flag, size);
+}
+
+void
+ep1_state_change_notify( int new_state )
+{
+
+}
+
+void
+ep1_stall( void )
+{
+	/* SET_FEATURE force stall at UDC */
+	UDC_set( Ser0UDCCS1, UDCCS1_FST );
+}
+
+int
+ep1_init(dma_regs_t *dmaregs)
+{
+	dmaregs_rx = dmaregs;
+	sa1100_reset_dma(dmaregs_rx);
+	ep1_done(-EAGAIN);
+	return 0;
+}
+
+void
+ep1_reset(void)
+{
+	if (dmaregs_rx)
+	    sa1100_reset_dma(dmaregs_rx);
+	UDC_clear(Ser0UDCCS1, UDCCS1_FST);
+	ep1_done(-EINTR);
+}
+
+void ep1_int_hndlr(int udcsr)
+{
+	dma_addr_t dma_addr;
+	unsigned int len;
+	int status = Ser0UDCCS1;
+
+	if ( naking ) printk( "%sEh? in ISR but naking = %d\n", "usbrx: ", naking );
+
+	if (status & UDCCS1_RPC) {
+
+		if (!ep1_curdmalen) {
+			printk("usb_recv: RPC for non-existent buffer\n");
+			naking=1;
+			return;
+		}
+
+		sa1100_stop_dma(dmaregs_rx);
+
+		if (status & UDCCS1_SST) {
+			printk("usb_recv: stall sent OMP=%ld\n", Ser0UDCOMP);
+			UDC_flip(Ser0UDCCS1, UDCCS1_SST);
+			ep1_done(-EIO); // UDC aborted current transfer, so we do
+			return;
+		}
+
+		if (status & UDCCS1_RPE) {
+			printk("usb_recv: RPError %x\n", status);
+			UDC_flip(Ser0UDCCS1, UDCCS1_RPC);
+			ep1_done(-EIO);
+			return;
+		}
+
+		dma_addr=sa1100_get_dma_pos(dmaregs_rx);
+		dma_unmap_single(NULL, ep1_curdmapos, ep1_curdmalen,
+				 DMA_FROM_DEVICE);
+		len = dma_addr - ep1_curdmapos;
+#ifdef SA1100_USB_DEBUG
+		if (sa1100_usb_debug) {
+		    int i;
+		    printk("usb rx %d :\n  ",len);
+		    if (sa1100_usb_debug>1) {
+				for (i=0; i<len; i++) {
+			    	if ((i % 32)==31)
+					printk("\n  ");
+			    	printk("%2.2x ",((char *)ep1_curdmapos)[i]);
+				}
+		    }
+		    printk("\n");
+		}
+#endif
+		if (len < ep1_curdmalen) {
+			char *buf = ep1_curdmabuf + len;
+			while (Ser0UDCCS1 & UDCCS1_RNE) {
+				if (len >= ep1_curdmalen) {
+					printk("usb_recv: too much data in fifo\n");
+					break;
+				}
+				*buf++ = Ser0UDCDR;
+				len++;
+			}
+		} else if (Ser0UDCCS1 & UDCCS1_RNE) {
+			printk("usb_recv: fifo screwed, shouldn't contain data\n");
+			len = 0;
+		}
+
+#if defined(NCB_DMA_FIX)
+//		if (len && (ep1_buf != ep1_curdmabuf))
+//		    memcpy(ep1_buf,ep1_curdmabuf,len);
+		if (len)
+		    memcpy(&(((unsigned char *)ep1_buf)[ep1_used]),ep1_curdmabuf,len);
+#endif
+
+		ep1_curdmalen = 0;  /* dma unmap already done */
+		ep1_remain -= len;
+		ep1_used += len;
+//		ep1_curdmabuf += len;	// use same buffer again
+		naking = 1;
+//printk("%s: received %d, %d remaining\n",__FUNCTION__,len,ep1_remain);
+		if (len && (len == rx_pktsize))
+		    ep1_start();
+		else
+		ep1_done((len) ? 0 : -EPIPE);
+	}
+	/* else, you can get here if we are holding NAK */
+}
+
+int
+sa1100_usb_recv(struct usb_request *req, void (*callback)(int flag, int size))
+{
+	unsigned long flags;
+	char *buf=req->buf;
+	int len=req->length;
+
+	if (ep1_len)
+		return -EBUSY;
+
+	local_irq_save(flags);
+	ep1_buf = buf;
+	ep1_len = len;
+	ep1_callback = callback;
+	ep1_remain = len;
+	ep1_used = 0;
+#ifdef NCB_DMA_FIX
+//	if (((size_t)buf)&3)
+ 	if (1)
+	    ep1_curdmabuf = receive_buffer;
+	else
+#else
+	ep1_curdmabuf = buf;
+#endif
+	ep1_curdmalen = 0;
+	ep1_start();
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+// ep2 handlers
+
+static char *ep2_buf;
+static int ep2_len;
+static void (*ep2_callback)(int status, int size);
+static dma_addr_t ep2_dma;
+static dma_addr_t ep2_curdmapos;
+static int ep2_curdmalen;
+static int ep2_remain;
+static dma_regs_t *dmaregs_tx = NULL;
+static int tx_pktsize;
+
+/* device state is changing, async */
+void
+ep2_state_change_notify( int new_state )
+{
+}
+
+/* set feature stall executing, async */
+void
+ep2_stall( void )
+{
+	UDC_set( Ser0UDCCS2, UDCCS2_FST );  /* force stall at UDC */
+}
+
+static void
+ep2_start(void)
+{
+	if (!ep2_len)
+		return;
+
+	ep2_curdmalen = tx_pktsize;
+	if (ep2_curdmalen > ep2_remain)
+		ep2_curdmalen = ep2_remain;
+
+	/* must do this _before_ queue buffer.. */
+	UDC_flip( Ser0UDCCS2,UDCCS2_TPC );  /* stop NAKing IN tokens */
+	UDC_write( Ser0UDCIMP, ep2_curdmalen-1 );
+
+	Ser0UDCAR = usbd_info.address; // fighting stupid silicon bug
+	sa1100_start_dma(dmaregs_tx, ep2_curdmapos, ep2_curdmalen);
+}
+
+static void
+ep2_done(int flag)
+{
+	int size = ep2_len - ep2_remain;
+	if (ep2_len) {
+		dma_unmap_single(NULL, ep2_dma, ep2_len, DMA_TO_DEVICE);
+		ep2_len = 0;
+		if (ep2_callback)
+			ep2_callback(flag, size);
+	}
+}
+
+int ep2_init(dma_regs_t *dmaregs)
+{
+	dmaregs_tx = dmaregs;
+	sa1100_reset_dma(dmaregs_tx);
+	ep2_done(-EAGAIN);
+	return 0;
+}
+
+void ep2_reset(void)
+{
+	UDC_clear(Ser0UDCCS2, UDCCS2_FST);
+	if (dmaregs_tx)
+	    sa1100_reset_dma(dmaregs_tx);
+	ep2_done(-EINTR);
+}
+
+void ep2_int_hndlr(int udcsr)
+{
+	int status = Ser0UDCCS2;
+
+	if (Ser0UDCAR != usbd_info.address) // check for stupid silicon bug.
+		Ser0UDCAR = usbd_info.address;
+
+	if (status & UDCCS2_TPC) {
+
+		UDC_flip(Ser0UDCCS2, UDCCS2_SST);
+
+		sa1100_reset_dma(dmaregs_tx);
+
+		if (status & (UDCCS2_TPE | UDCCS2_TUR)) {
+			printk("usb_send: transmit error %x\n", status);
+			ep2_done(-EIO);
+		} else {
+			ep2_curdmapos += ep2_curdmalen;
+			ep2_remain -= ep2_curdmalen;
+
+			if (ep2_remain != 0)
+				ep2_start();
+			else
+				ep2_done(0);
+		}
+	} else {
+		printk("usb_send: Not TPC: UDCCS2 = %x\n", status);
+	}
+}
+
+int
+sa1100_usb_send(struct usb_request *req, void (*callback)(int status, int size))
+{
+	char *buf=req->buf;
+	int len=req->length;
+	unsigned long flags;
+
+	if (usbd_info.state != USB_STATE_CONFIGURED) {
+		PRINTKD("%s: return -ENODEV\n",__FUNCTION__);
+		return -ENODEV;
+	}
+
+	if (ep2_len) {
+		PRINTKD("%s: return -EBUSY\n",__FUNCTION__);
+		return -EBUSY;
+	}
+
+	local_irq_save(flags);
+#ifdef NCB_DMA_FIX
+	// if misaligned, copy to aligned buffer
+//	if (((size_t)buf)&3) {
+	if (1) {
+	    PRINTKD("%s: copying %d bytes to send_buffer\n",__FUNCTION__,len);
+	    memcpy(send_buffer,buf,len);
+	    ep2_buf = send_buffer;
+	}
+	else
+#endif
+	ep2_buf = buf;
+
+	ep2_len = len;
+	ep2_dma = dma_map_single(NULL, ep2_buf, len,DMA_TO_DEVICE);
+	PRINTKD("%s: mapped dma to buffer(%p0\n",__FUNCTION__,buf);
+
+	ep2_callback = callback;
+	ep2_remain = len;
+	ep2_curdmapos = ep2_dma;
+
+	PRINTKD("%s: calling ep2_start\n",__FUNCTION__);
+	ep2_start();
+	local_irq_restore(flags);
+
+	return 0;
+}
+/*-------------------------------------------------------------------------*/
+
+static int
+sa1100_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+{
+	struct sa1100_udc	*dev;
+	struct sa1100_ep	*ep;
+	u32			max;
+	int			type;
+
+	ep = container_of (_ep, struct sa1100_ep, ep);
+	if (!_ep || !desc || ep->desc || _ep->name == ep0name
+			|| desc->bDescriptorType != USB_DT_ENDPOINT) {
+		PRINTKD("%s: _ep = %p, desc = %p\n",__FUNCTION__,_ep,desc);
+		if (_ep && desc)
+		    PRINTKD("%s: ep->desc = %p, _ep->name = %s desc->bDescriptorType = %s\n",__FUNCTION__,ep->desc,_ep->name,
+			(desc->bDescriptorType == USB_DT_ENDPOINT) ? "USB_DT_ENDPOINT":"bad!!");
+		return -EINVAL;
+	}
+
+	dev = ep->dev;
+	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+	max = le16_to_cpu (desc->wMaxPacketSize);
+	switch (max) {
+	case 64: case 32:
+	/* note:  maxpacket > 16 means DMA might overrun/underrun */
+	case 16: case 8:
+		break;
+	default:
+		if (type == USB_ENDPOINT_XFER_INT && max < 64)
+			break;
+		return -EDOM;
+	}
+
+	switch (type) {
+	case USB_ENDPOINT_XFER_BULK:
+	case USB_ENDPOINT_XFER_INT:
+		if (ep == &dev->ep[2]) {
+			if (desc->bEndpointAddress != (USB_DIR_IN|2)) {
+				PRINTKD("%s: ep[2] has invalid endpoint\n",__FUNCTION__);
+				return -EINVAL;
+			}
+			tx_pktsize = max;
+			Ser0UDCOMP = max - 1;
+			PRINTKD("%s: ep2 max packet size is %d\n",__FUNCTION__,max);
+			break;
+		} else if (ep == &dev->ep[1]) {
+			if (desc->bEndpointAddress != (USB_DIR_OUT|1)) {
+				PRINTKD("%s: ep[1] has invalid endpoint\n",__FUNCTION__);
+				return -EINVAL;
+			}
+			rx_pktsize = max;
+			Ser0UDCIMP = max - 1;
+			PRINTKD("%s: ep1 max packet size is %d\n",__FUNCTION__,max);
+			break;
+		}
+		// FALLTHROUGH
+	default:
+		PRINTKD("%s: Invalid endpoint\n",__FUNCTION__);
+		return -EINVAL;
+	}
+
+	_ep->maxpacket = max;
+	ep->desc = desc;
+	ep->stopped = 0;
+
+	DEBUG (dev, "enabled %s %s max %04x\n", _ep->name,
+		type_string (desc->bmAttributes), max);
+
+	return 0;
+}
+
+static int sa1100_disable (struct usb_ep *_ep)
+{
+	struct sa1100_ep	*ep;
+
+	ep = container_of (_ep, struct sa1100_ep, ep);
+	if (!_ep || !ep->desc || _ep->name == ep0name)
+		return -EINVAL;
+
+	nuke (ep, -ESHUTDOWN);
+
+	DEBUG (ep->dev, "disabled %s\n", _ep->name);
+
+	ep->desc = NULL;
+	ep->stopped = 1;
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_request *
+sa1100_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
+{
+	struct sa1100_request *req;
+
+	if (!_ep)
+		return 0;
+
+	req = kzalloc(sizeof *req, gfp_flags);
+	if (!req)
+		return 0;
+
+	memset (req, 0, sizeof *req);
+	req->req.dma = DMA_ADDR_INVALID;
+	INIT_LIST_HEAD (&req->queue);
+	return &req->req;
+}
+
+static void sa1100_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct sa1100_request	*req;
+
+	req = container_of (_req, struct sa1100_request, req);
+	WARN_ON (!list_empty (&req->queue));
+	kfree(req);	//NCB - see pxa2xx_udc
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void done(struct sa1100_ep *ep, struct sa1100_request *req, int status)
+{
+	unsigned		stopped = ep->stopped;
+
+	list_del_init (&req->queue);
+
+	if (likely(req->req.status == -EINPROGRESS))
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	if (status && status != -ESHUTDOWN)
+		VDEBUG (ep->dev, "complete %s req %p stat %d len %u/%u\n",
+			ep->ep.name, &req->req, status,
+			req->req.actual, req->req.length);
+
+	/* don't modify queue heads during completion callback */
+	ep->stopped = 1;
+	req->req.complete (&ep->ep, &req->req);
+	ep->stopped = stopped;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* FIXME move away from the old non-queued api.
+ * - forces extra work on us
+ * - stores request state twice
+ * - doesn't let gadget driver handle dma mapping
+ * - status codes need mapping
+ */
+
+static int map_status(int status)
+{
+	switch (status) {
+	case 0:
+	case -EIO:	/* ep[12]_int_handler */
+		return status;
+	case -EPIPE:	/* ep1_int_handler */
+		return 0;
+	//  case -EAGAIN: 	/* ep[12]_init */
+	//  case -EINTR:	/* ep[12]_reset */
+	default:
+		return -ESHUTDOWN;
+	}
+}
+
+static void tx_callback(int status, int size)
+{
+	struct sa1100_ep	*ep = &the_controller->ep[2];
+	struct sa1100_request	*req;
+
+	if (list_empty (&ep->queue)) {
+		if (status != -EAGAIN)
+			DEBUG (ep->dev, "%s, bogus tx callback %d/%d\n",
+				ep->ep.name, status, size);
+		return;
+	}
+	req = list_entry (ep->queue.next, struct sa1100_request, queue);
+	req->req.actual = size;
+	done (ep, req, map_status (status));
+
+	if (ep->stopped || list_empty (&ep->queue))
+		return;
+	req = list_entry (ep->queue.next, struct sa1100_request, queue);
+	sa1100_usb_send (&req->req, tx_callback);
+}
+
+static void rx_callback (int status, int size)
+{
+	struct sa1100_ep	*ep = &the_controller->ep[1];
+	struct sa1100_request	*req;
+
+	if (list_empty (&ep->queue)) {
+		if (status != -EAGAIN)
+			DEBUG (ep->dev, "%s, bogus tx callback %d/%d\n",
+				ep->ep.name, status, size);
+		return;
+	}
+	req = list_entry (ep->queue.next, struct sa1100_request, queue);
+	req->req.actual = size;
+	done (ep, req, map_status (status));
+
+	if (ep->stopped || list_empty (&ep->queue))
+		return;
+	req = list_entry (ep->queue.next, struct sa1100_request, queue);
+	sa1100_usb_recv (&req->req, rx_callback);
+}
+
+
+static int
+sa1100_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+	struct sa1100_request	*req;
+	struct sa1100_ep	*ep;
+	struct sa1100_udc	*dev;
+	unsigned long		flags;
+
+	req = container_of (_req, struct sa1100_request, req);
+	if (!_req || !_req->complete || !_req->buf
+			|| !list_empty (&req->queue))
+		return -EINVAL;
+
+	ep = container_of (_ep, struct sa1100_ep, ep);
+	if (unlikely(!_ep || (!ep->desc && _ep->name != ep0name)))
+		return -EINVAL;
+
+	dev = ep->dev;
+	if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))
+		return -ESHUTDOWN;
+
+	// handle ep0
+	if (_ep->name == ep0name) {
+	    ep0_queue( _req->buf, _req->length, dev->ep0_req_len >=0 ? dev->ep0_req_len: _req->length );
+	    return 0;
+	}
+
+	/* sa1100 udc can't write zlps */
+	if (ep == &dev->ep[2] && _req->length == 0)
+		return -ERANGE;
+
+	/* the old sa1100 api doesn't use 'unsigned' for lengths */
+	if (_req->length > INT_MAX)
+		return -ERANGE;
+
+	VDEBUG (dev, "%s queue req %p, len %d buf %p\n",
+			_ep->name, _req, _req->length, _req->buf);
+
+	local_irq_save (flags);
+
+	_req->status = -EINPROGRESS;
+	_req->actual = 0;
+
+	if (list_empty (&ep->queue) && !ep->stopped) {
+		/* FIXME this does DMA mapping wrong.  caller is allowed
+		 * to provide buffers that don't need mapping, but this
+		 * doesn't use them.
+		 */
+		if (ep == &ep->dev->ep[2]) {
+			PRINTKD("%s: sa1100_usb_send buf %p length %d\n",__FUNCTION__,_req->buf,_req->length);
+			sa1100_usb_send (_req, tx_callback);
+		}
+		else if (ep == &ep->dev->ep[1]) {
+			PRINTKD("%s: sa1100_usb_recv buf %p length %d\n",__FUNCTION__,_req->buf,_req->length);
+			sa1100_usb_recv (_req, rx_callback);
+		}
+		/* ep0 rx/tx is handled separately */
+	}
+	list_add_tail (&req->queue, &ep->queue);
+
+	local_irq_restore (flags);
+
+	return 0;
+}
+
+/* dequeue ALL requests */
+static void nuke (struct sa1100_ep *ep, int status)
+{
+	struct sa1100_request	*req;
+
+	/* called with irqs blocked */
+	while (!list_empty (&ep->queue)) {
+		req = list_entry (ep->queue.next,
+				struct sa1100_request,
+				queue);
+		done (ep, req, status);
+	}
+	if (ep == &ep->dev->ep[1])
+		ep1_reset ();
+	else if (ep == &ep->dev->ep[2])
+		ep2_reset ();
+}
+
+/* dequeue JUST ONE request */
+static int sa1100_dequeue (struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct sa1100_ep	*ep;
+	struct sa1100_request	*req;
+	unsigned long		flags;
+
+	ep = container_of (_ep, struct sa1100_ep, ep);
+	if (!_ep || (!ep->desc && _ep->name != ep0name) || !_req)
+		return -EINVAL;
+
+	local_irq_save (flags);
+
+	/* make sure it's actually queued on this endpoint */
+	list_for_each_entry (req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+	if (&req->req != _req) {
+		local_irq_restore(flags);
+		return -EINVAL;
+	}
+
+	done(ep, req, -ECONNRESET);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+sa1100_set_halt (struct usb_ep *_ep, int value)
+{
+	struct sa1100_ep	*ep;
+
+	ep = container_of (_ep, struct sa1100_ep, ep);
+	if (unlikely(!_ep 
+		|| (!ep->desc && _ep->name != ep0name))
+		|| (ep->desc->bmAttributes & 0x03) == USB_ENDPOINT_XFER_ISOC)
+		return -EINVAL;
+	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	VDEBUG (ep->dev, "%s %s halt\n", _ep->name, value ? "set" : "clear");
+
+	/* set/clear, then synch memory views with the device */
+	if (value) {
+		if (ep == &ep->dev->ep[1])
+			ep1_stall ();
+		else
+			ep2_stall ();
+	} else {
+		if (ep == &ep->dev->ep[1])
+			ep1_reset ();
+		else
+			ep2_reset ();
+	}
+
+	return 0;
+}
+
+static struct usb_ep_ops sa1100_ep_ops = {
+	.enable		= sa1100_enable,
+	.disable	= sa1100_disable,
+
+	.alloc_request	= sa1100_alloc_request,
+	.free_request	= sa1100_free_request,
+
+	.queue		= sa1100_queue,
+	.dequeue	= sa1100_dequeue,
+
+	.set_halt	= sa1100_set_halt,
+	// .fifo_status	= sa1100_fifo_status,
+	// .fifo_flush	= sa1100_fifo_flush,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int sa1100_get_frame (struct usb_gadget *_gadget)
+{
+	return -EOPNOTSUPP;
+}
+
+static int sa1100_wakeup (struct usb_gadget *_gadget)
+{
+	struct sa1100_udc	*dev;
+
+	if (!_gadget)
+		return 0;
+	dev = container_of (_gadget, struct sa1100_udc, gadget);
+
+	// FIXME
+
+	return 0;
+}
+
+static const struct usb_gadget_ops sa1100_ops = {
+	.get_frame	= sa1100_get_frame,
+	.wakeup		= sa1100_wakeup,
+
+	// .set_selfpowered = sa1100_set_selfpowered,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static inline void enable_resume_mask_suspend (void)
+{
+	 int i = 0;
+
+	 while (1) {
+		  Ser0UDCCR |= UDCCR_SUSIM; // mask future suspend events
+		  udelay (i);
+		  if ( (Ser0UDCCR & UDCCR_SUSIM) || (Ser0UDCSR & UDCSR_RSTIR))
+			   break;
+		  if (++i == 50) {
+			   WARN (&the_controller, "%s Could not set SUSIM %8.8lX\n",
+			   		__FUNCTION__, Ser0UDCCR);
+			   break;
+		  }
+	 }
+
+	 i = 0;
+	 while (1) {
+		  Ser0UDCCR &= ~UDCCR_RESIM;
+		  udelay (i);
+		  if ( (Ser0UDCCR & UDCCR_RESIM) == 0
+			   	|| (Ser0UDCSR & UDCSR_RSTIR))
+			   break;
+		  if (++i == 50) {
+			   WARN (&the_controller, "%s Could not clear RESIM %8.8lX\n",
+			   		__FUNCTION__, Ser0UDCCR);
+			   break;
+		  }
+	 }
+}
+
+static inline void enable_suspend_mask_resume (void)
+{
+	 int i = 0;
+	 while (1) {
+		  Ser0UDCCR |= UDCCR_RESIM; // mask future resume events
+		  udelay (i);
+		  if (Ser0UDCCR & UDCCR_RESIM || (Ser0UDCSR & UDCSR_RSTIR))
+			   break;
+		  if (++i == 50) {
+			   WARN (&the_controller, "%s could not set RESIM %8.8lX\n",
+			   		__FUNCTION__, Ser0UDCCR);
+			   break;
+		  }
+	 }
+	 i = 0;
+	 while (1) {
+		  Ser0UDCCR &= ~UDCCR_SUSIM;
+		  udelay (i);
+		  if ( (Ser0UDCCR & UDCCR_SUSIM) == 0
+			   	|| (Ser0UDCSR & UDCSR_RSTIR))
+			   break;
+		  if (++i == 50) {
+			   WARN (&the_controller, "%s Could not clear SUSIM %8.8lX\n",
+			   		__FUNCTION__, Ser0UDCCR);
+			   break;
+		  }
+	 }
+}
+
+// HACK DEBUG  3Mar01ww
+// Well, maybe not, it really seems to help!  08Mar01ww
+static void core_kicker (void)
+{
+	u32 car = Ser0UDCAR;
+	u32 imp = Ser0UDCIMP;
+	u32 omp = Ser0UDCOMP;
+
+	UDC_set (Ser0UDCCR, UDCCR_UDD);
+	udelay (300);
+	UDC_clear (Ser0UDCCR, UDCCR_UDD);
+
+	Ser0UDCAR = car;
+	Ser0UDCIMP = imp;
+	Ser0UDCOMP = omp;
+}
+
+static irqreturn_t udc_int_hndlr(int irq, void *_dev)
+{
+	struct sa1100_udc	*dev = _dev;
+  	u32			status = Ser0UDCSR;
+
+	PRINTKD("%s: status = 0x%x and control = 0x%lx\n", __FUNCTION__,
+			status, Ser0UDCCR);
+	/* ReSeT Interrupt Request - UDC has been reset */
+	if (status & UDCSR_RSTIR) {
+		PRINTKD("%s: processing UDCSR_RSTIR\n", __FUNCTION__);
+		if (usbctl_next_state_on_event(kEvReset) != kError) {
+			/* starting 20ms or so reset sequence now... */
+			INFO (dev, "Resetting\n");
+			ep0_reset();  // just set state to idle
+			ep1_reset();  // flush dma, clear false stall
+			ep2_reset();  // flush dma, clear false stall
+		}
+		// mask reset ints, they flood during sequence, enable
+		// suspend and resume
+		UDC_set(Ser0UDCCR, UDCCR_REM);    // mask reset
+		UDC_clear(Ser0UDCCR, (UDCCR_SUSIM | UDCCR_RESIM)); // enable suspend and resume
+		UDC_flip(Ser0UDCSR, status);	// clear all pending sources
+		PRINTKD("%s: setting USB_FULL_SPEED\n",__FUNCTION__);
+		dev->gadget.speed = USB_SPEED_FULL;
+		return IRQ_HANDLED;	// NCB
+	}
+
+	/* else we have done something other than reset,
+	 * so be sure reset enabled
+	 */
+	UDC_clear(Ser0UDCCR, UDCCR_REM);
+
+	/* RESume Interrupt Request */
+	if (status & UDCSR_RESIR) {
+		struct usb_gadget_driver	*driver = dev->driver;
+
+		PRINTKD("%s: processing UDCSR_RESIR\n",__FUNCTION__);
+		if (driver->resume)
+			driver->resume (&dev->gadget);
+		core_kicker ();
+		enable_suspend_mask_resume ();
+	}
+
+	/* SUSpend Interrupt Request */
+	if (status & UDCSR_SUSIR) {
+		struct usb_gadget_driver	*driver = dev->driver;
+
+		PRINTKD("%s: processing UDCSR_SUSIR\n",__FUNCTION__);
+		if (driver->suspend)
+			driver->suspend (&dev->gadget);
+		enable_resume_mask_suspend ();
+	}
+
+	UDC_flip(Ser0UDCSR, status); // clear all pending sources
+
+	if (status & UDCSR_EIR)
+		PRINTKD("%s: processing ep0_int_hndlr\n",__FUNCTION__);
+		 ep0_int_hndlr();
+
+	if (status & UDCSR_RIR) {
+		PRINTKD("%s: processing ep1_int_hndlr\n",__FUNCTION__);
+		ep1_int_hndlr(status);
+	}
+	if (status & UDCSR_TIR) {
+		PRINTKD("%s: processing ep2_int_hndlr\n",__FUNCTION__);
+		ep2_int_hndlr(status);
+	}
+
+	return IRQ_HANDLED;	// NCB
+}
+
+/* soft_connect_hook ()
+ * Some devices have platform-specific circuitry to make USB
+ * not seem to be plugged in, even when it is. This allows
+ * software to control when a device 'appears' on the USB bus
+ * (after Linux has booted and this driver has loaded, for
+ * example). If you have such a circuit, control it here.
+ */
+#ifdef CONFIG_SA1100_EXTENEX1
+static void soft_connect_hook(int enable)
+{
+	if (machine_is_extenex1 ()) {
+		if (enable) {
+			PPDR |= PPC_USB_SOFT_CON;
+			PPSR |= PPC_USB_SOFT_CON;
+		} else {
+			PPSR &= ~PPC_USB_SOFT_CON;
+			PPDR &= ~PPC_USB_SOFT_CON;
+		}
+	}
+}
+#elif defined(CONFIG_SA1100_BALLOON)
+static void soft_connect_hook(int enable)
+{
+	if (machine_is_balloon()) {
+	    if (enable)
+			balloon_cpld_control(BALLOON_UDC_DISCONNECT, 0);
+	    else
+			balloon_cpld_control(BALLOON_UDC_DISCONNECT, 1);
+	}
+}
+#elif defined(CONFIG_SA1100_COLLIE)
+extern struct platform_device colliescoop_device;
+
+static void soft_connect_hook(int enable)
+{
+	if(enable)
+		set_scoop_gpio(&colliescoop_device.dev, COLLIE_SCP_LB_VOL_CHG);
+	else
+		reset_scoop_gpio(&colliescoop_device.dev, COLLIE_SCP_LB_VOL_CHG);
+}
+#else
+#define soft_connect_hook(x) do { } while (0);
+#endif
+
+/* "function" sysfs attribute */
+static ssize_t
+show_function(struct device *_dev, struct device_attribute *attr, char *buf)
+{
+	struct sa1100_udc	*dev = dev_get_drvdata (_dev);
+
+	if (!dev->driver
+			|| !dev->driver->function
+			|| strlen(dev->driver->function) > PAGE_SIZE)
+		return 0;
+	return scnprintf (buf, PAGE_SIZE, "%s\n", dev->driver->function);
+}
+static DEVICE_ATTR(function, S_IRUGO, show_function, NULL);
+
+/* disable the UDC at the source */
+static void udc_disable(struct sa1100_udc *dev)
+{
+	soft_connect_hook(0);
+	UDC_set(Ser0UDCCR, UDCCR_UDD);
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+	ep0_idle(dev);
+}
+
+static void udc_reinit(struct sa1100_udc *dev)
+{
+	u32	i;
+
+	/* Initialize the gadget controller data structure */
+	INIT_LIST_HEAD(&dev->gadget.ep_list);
+	INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+	ep0_idle(dev);
+	for ( i = 0 ; i < 3 ; i++) {
+		struct sa1100_ep *ep = &dev->ep[i];
+		if (i != 0)
+			list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+		ep->desc     = NULL;
+		ep->stopped  = 0;
+		INIT_LIST_HEAD(&ep->queue);
+	}
+}
+
+/*  enable the udc at the source */
+static void udc_enable(struct sa1100_udc *dev)
+{
+	UDC_clear (Ser0UDCCR, UDCCR_UDD);
+	ep0_idle(dev);
+}
+
+static void ep0_start(struct sa1100_udc *dev)
+{
+	udc_enable(dev);
+	udelay(100);
+
+	/* clear stall - receiver seems to start stalled? 19Jan01ww */
+	/* also clear other stuff just to be thurough 22Feb01ww */
+	UDC_clear(Ser0UDCCS1, UDCCS1_FST | UDCCS1_RPE | UDCCS1_RPC );
+	UDC_clear(Ser0UDCCS2, UDCCS2_FST | UDCCS2_TPE | UDCCS2_TPC );
+
+	/* mask everything */
+	Ser0UDCCR = 0xFC;
+
+	/* flush DMA and fire through some -EAGAINs */
+	ep1_init(dev->ep[1].dmaregs);
+	ep2_init(dev->ep[2].dmaregs);
+
+	/* enable any platform specific hardware */
+	soft_connect_hook(1);
+
+	/* clear all top-level sources */
+	Ser0UDCSR = UDCSR_RSTIR | UDCSR_RESIR | UDCSR_EIR |
+		         UDCSR_RIR | UDCSR_TIR | UDCSR_SUSIR ;
+
+	/* EXERIMENT - a short line in the spec says toggling this
+	 * bit diddles the internal state machine in the udc to
+	 * expect a suspend
+	 */
+	Ser0UDCCR  |= UDCCR_RESIM;
+	/* END EXPERIMENT 10Feb01ww */
+
+	/* enable any platform specific hardware */
+	soft_connect_hook(1);
+
+	/* Enable interrupts. If you are unplugged you will immediately
+	 * get a suspend interrupt. If you are plugged and have a soft
+	 * connect-circuit, you will get a reset.  If you are plugged
+	 * without a soft-connect, I think you also get suspend. In short,
+	 * start with suspend masked and everything else enabled
+	 */
+	UDC_write(Ser0UDCCR, UDCCR_SUSIM);
+}
+
+
+/* when a driver is successfully registered, it will receive
+ * control requests including set_configuration(), which enables
+ * non-control requests.  then usb traffic follows until a
+ * disconnect is reported.  then a host may connect again, or
+ * the driver might get unbound.
+ */
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+	struct sa1100_udc	*dev = the_controller;
+	int			retval;
+
+	if (!driver || !driver->bind || !driver->setup)
+		return -EINVAL;
+	if (!dev)
+		return -ENODEV;
+	if (dev->driver)
+		return -EBUSY;
+
+	/* hook up the driver ... */
+	dev->driver = driver;
+	dev->gadget.dev.driver = &driver->driver;
+
+	retval = device_add(&dev->gadget.dev);
+	if (retval != 0) {
+		printk(KERN_ERR "Error in device_add() : %d\n",retval);
+		goto register_error;
+	}
+
+	retval = driver->bind (&dev->gadget);
+	if (retval != 0) {
+		DEBUG(dev, "bind to driver %s --> %d\n",
+				driver->driver.name, retval);
+		device_del(&dev->gadget.dev);
+		goto register_error;
+	}
+
+	retval = device_create_file(dev->dev, &dev_attr_function);
+
+	/* ... then enable host detection and ep0; and we're ready
+	 * for set_configuration as well as eventual disconnect.
+	 */
+	ep0_start(dev);
+
+	DEBUG(dev, "%s ready\n", driver->driver.name);
+
+	return 0;
+
+register_error:
+	dev->driver = NULL;
+	dev->gadget.dev.driver = NULL;
+	return retval;
+}
+EXPORT_SYMBOL (usb_gadget_register_driver);
+
+static void
+stop_activity(struct sa1100_udc *dev, struct usb_gadget_driver *driver)
+{
+	int i;
+
+	/* don't disconnect if it's not connected */
+	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+		driver = NULL;
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+	/* mask everything */
+	Ser0UDCCR = 0xFC;
+
+	/* stop hardware; prevent new request submissions;
+	 * and kill any outstanding requests.
+	 */
+	for (i = 0; i < 3; i++) {
+		struct sa1100_ep *ep = &dev->ep[i];
+		ep->stopped = 1;
+		nuke(ep, -ESHUTDOWN);
+	}
+	udc_disable (dev);
+
+	/* report disconnect; the driver is already quiesced */
+	if (driver)
+		driver->disconnect(&dev->gadget);
+
+	/* re-init driver-visible data structures */
+	udc_reinit(dev);
+}
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct sa1100_udc	*dev = the_controller;
+
+	if (!dev)
+		return -ENODEV;
+	if (!driver || driver != dev->driver)
+		return -EINVAL;
+
+	local_irq_disable();
+	stop_activity (dev, driver);
+	local_irq_enable();
+	if (driver->unbind)
+		driver->unbind(&dev->gadget);
+	dev->driver = 0;
+
+	device_del(&dev->gadget.dev);
+	device_remove_file(dev->dev, &dev_attr_function);
+
+	DEBUG (dev, "unregistered driver '%s'\n", driver->driver.name);
+	return 0;
+}
+EXPORT_SYMBOL (usb_gadget_unregister_driver);
+
+
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+
+//////////////////////////////////////////////////////////////////////////////
+// Proc Filesystem Support
+//////////////////////////////////////////////////////////////////////////////
+
+#if CONFIG_PROC_FS
+
+#define SAY(fmt,args...)  p += sprintf (p, fmt, ## args)
+#define SAYV(num)         p += sprintf (p, num_fmt, "Value", num)
+#define SAYC(label,yn)    p += sprintf (p, yn_fmt, label, yn)
+#define SAYS(label,v)     p += sprintf (p, cnt_fmt, label, v)
+
+static int usbctl_read_proc (char *page, char **start, off_t off,
+			    int count, int *eof, void *data)
+{
+	 const char * num_fmt   = "%25.25s: %8.8lX\n";
+	 const char * cnt_fmt   = "%25.25s: %lu\n";
+	 const char * yn_fmt    = "%25.25s: %s\n";
+	 const char * yes       = "YES";
+	 const char * no        = "NO";
+	 unsigned long v;
+	 char * p = page;
+	 int len;
+
+ 	 SAY ("SA1100 USB Controller Core\n");
+
+	 SAYS ("ep0 bytes read", usbd_info.stats.ep0_bytes_read);
+	 SAYS ("ep0 bytes written", usbd_info.stats.ep0_bytes_written);
+	 SAYS ("ep0 FIFO read failures", usbd_info.stats.ep0_fifo_read_failures);
+	 SAYS ("ep0 FIFO write failures", usbd_info.stats.ep0_fifo_write_failures);
+
+	 SAY ("\n");
+
+	 v = Ser0UDCAR;
+	 SAY ("%25.25s: 0x%8.8lX - %ld\n", "Address Register", v, v);
+	 v = Ser0UDCIMP;
+	 SAY ("%25.25s: %ld (%8.8lX)\n", "IN  max packet size", v+1, v);
+	 v = Ser0UDCOMP;
+	 SAY ("%25.25s: %ld (%8.8lX)\n", "OUT max packet size", v+1, v);
+
+	 v = Ser0UDCCR;
+	 SAY ("\nUDC Mask Register\n");
+	 SAYV (v);
+	 SAYC ("UDC Active", (v & UDCCR_UDA) ? yes : no);
+	 SAYC ("Suspend interrupts masked", (v & UDCCR_SUSIM) ? yes : no);
+	 SAYC ("Resume interrupts masked", (v & UDCCR_RESIM) ? yes : no);
+	 SAYC ("Reset interrupts masked", (v & UDCCR_REM) ? yes : no);
+
+	 v = Ser0UDCSR;
+	 SAY ("\nUDC Interrupt Request Register\n");
+	 SAYV (v);
+	 SAYC ("Reset pending", (v & UDCSR_RSTIR) ? yes : no);
+	 SAYC ("Suspend pending", (v & UDCSR_SUSIR) ? yes : no);
+	 SAYC ("Resume pending", (v & UDCSR_RESIR) ? yes : no);
+	 SAYC ("ep0 pending", (v & UDCSR_EIR)   ? yes : no);
+	 SAYC ("receiver pending", (v & UDCSR_RIR)   ? yes : no);
+	 SAYC ("tramsitter pending", (v & UDCSR_TIR)   ? yes : no);
+
+#ifdef CONFIG_SA1100_EXTENEX1
+	 SAYC ("\nSoft connect", (PPSR & PPC_USB_SOFT_CON) ? "Visible" : "Hidden");
+#endif
+
+#if 1
+	 SAY ("\nDMA Tx registers\n");
+	 {
+	 dma_regs_t *r=the_controller->ep[2].dmaregs;
+	 SAY (" DDAR");
+	 SAYV(r->DDAR);
+	 SAY (" DCSR");
+	 SAYV(r->RdDCSR);
+	 SAY (" DBSA (address buf A) ");
+	 SAYV(r->DBSA);
+	 SAY (" DBTA (transfer count A) ");
+	 SAYV(r->DBTA);
+	 SAY (" DBSB (address buf B) ");
+	 SAYV(r->DBSB);
+	 SAY (" DBTB (transfer count B) ");
+	 SAYV(r->DBTB);
+
+	 }
+	 SAY ("\nDMA Rx registers\n");
+	 {
+	 dma_regs_t *r=the_controller->ep[1].dmaregs;
+	 SAY (" DDAR");
+	 SAYV(r->DDAR);
+	 SAY (" DCSR");
+	 SAYV(r->RdDCSR);
+	 SAY (" DBSA (address buf A) ");
+	 SAYV(r->DBSA);
+	 SAY (" DBTA (transfer count A) ");
+	 SAYV(r->DBTA);
+	 SAY (" DBSB (address buf B) ");
+	 SAYV(r->DBSB);
+	 SAY (" DBTB (transfer count B) ");
+	 SAYV(r->DBTB);
+
+	 }
+#endif
+#if 1
+	 v = Ser0UDCCS0;
+	 SAY ("\nUDC Endpoint Zero Status Register\n");
+	 SAYV (v);
+	 SAYC ("Out Packet Ready", (v & UDCCS0_OPR) ? yes : no);
+	 SAYC ("In Packet Ready", (v & UDCCS0_IPR) ? yes : no);
+	 SAYC ("Sent Stall", (v & UDCCS0_SST) ? yes : no);
+	 SAYC ("Force Stall", (v & UDCCS0_FST) ? yes : no);
+	 SAYC ("Data End", (v & UDCCS0_DE)  ? yes : no);
+	 SAYC ("Data Setup End", (v & UDCCS0_SE)  ? yes : no);
+	 SAYC ("Serviced (SO)", (v & UDCCS0_SO)  ? yes : no);
+
+	 v = Ser0UDCCS1;
+	 SAY ("\nUDC Receiver Status Register\n");
+	 SAYV (v);
+	 SAYC ("Receive Packet Complete", (v & UDCCS1_RPC) ? yes : no);
+	 SAYC ("Sent Stall", (v & UDCCS1_SST) ? yes : no);
+	 SAYC ("Force Stall", (v & UDCCS1_FST) ? yes : no);
+	 SAYC ("Receive Packet Error", (v & UDCCS1_RPE) ? yes : no);
+	 SAYC ("Receive FIFO not empty", (v & UDCCS1_RNE) ? yes : no);
+
+	 v = Ser0UDCCS2;
+	 SAY ("\nUDC Transmitter Status Register\n");
+	 SAYV (v);
+	 SAYC ("FIFO has < 8 of 16 chars", (v & UDCCS2_TFS) ? yes : no);
+	 SAYC ("Transmit Packet Complete", (v & UDCCS2_TPC) ? yes : no);
+	 SAYC ("Transmit FIFO underrun", (v & UDCCS2_TUR) ? yes : no);
+	 SAYC ("Transmit Packet Error", (v & UDCCS2_TPE) ? yes : no);
+	 SAYC ("Sent Stall", (v & UDCCS2_SST) ? yes : no);
+	 SAYC ("Force Stall", (v & UDCCS2_FST) ? yes : no);
+#endif
+
+	 len = (p - page) - off;
+	 if (len < 0)
+		  len = 0;
+	 *eof = (len <=count) ? 1 : 0;
+	 *start = page + off;
+	 return len;
+}
+
+static inline void register_proc_entry (void)
+{
+	create_proc_read_entry (driver_name, 0, NULL,
+		usbctl_read_proc, NULL);
+}
+
+static inline void unregister_proc_entry (void)
+{
+	remove_proc_entry (driver_name, NULL);
+}
+
+#else
+
+#define register_proc_entry() do {} while (0)
+#define unregister_proc_entry() do {} while (0)
+
+#endif  /* CONFIG_PROC_FS */
+
+/*-------------------------------------------------------------------------*/
+
+MODULE_DESCRIPTION ("sa1100_udc");
+MODULE_AUTHOR ("Various");
+MODULE_LICENSE ("GPL");
+
+static struct sa1100_udc memory = {
+	.gadget = {
+		.ops		= &sa1100_ops,
+		.ep0		= &memory.ep[0].ep,
+		.name		= driver_name,
+		.dev = {
+			.bus_id		= "gadget",
+		},
+	},
+
+	/* control endpoint */
+	.ep[0] = {
+		.ep = {
+			.name		= ep0name,
+			.ops		= &sa1100_ep_ops,
+			.maxpacket	= EP0_FIFO_SIZE,
+		},
+		.dev		= &memory,
+	},
+
+	/* first group of endpoints */
+	.ep[1] = {
+		.ep = {
+			.name		= "ep1out-bulk",
+			.ops		= &sa1100_ep_ops,
+			.maxpacket	= BULK_FIFO_SIZE,
+		},
+		.dev		= &memory,
+	},
+	.ep[2] = {
+		.ep = {
+			.name		= "ep2in-bulk",
+			.ops		= &sa1100_ep_ops,
+			.maxpacket	= BULK_FIFO_SIZE,
+		},
+		.dev		= &memory,
+	}
+};
+
+static int __init sa1100_udc_probe(struct device *_dev)
+{
+	struct sa1100_udc *dev = &memory;
+	int retval = 0;
+
+	/* setup dev */
+	dev->dev = _dev;
+//	dev->mach = _dev->platform_data;
+
+	device_initialize(&dev->gadget.dev);
+	dev->gadget.dev.parent = _dev;
+	dev->gadget.dev.dma_mask = _dev->dma_mask;
+
+	the_controller = dev;
+	dev_set_drvdata(_dev, dev);
+
+	/* controller stays disabled until gadget driver is bound */
+	udc_disable(dev);
+	udc_reinit(dev);
+
+//	spin_lock_init(&the_udc.lock);
+	register_proc_entry();
+
+	/* setup dma channels and IRQ */
+	retval = sa1100_request_dma(DMA_Ser0UDCRd, "USB receive",
+				    NULL, NULL, &dev->ep[1].dmaregs);
+	if (retval) {
+		ERROR(dev, "couldn't get rx dma, err %d\n", retval);
+		goto err_rx_dma;
+	}
+	retval = sa1100_request_dma(DMA_Ser0UDCWr, "USB transmit",
+				    NULL, NULL, &dev->ep[2].dmaregs);
+	if (retval) {
+		ERROR(dev, "couldn't get tx dma, err %d\n", retval);
+		goto err_tx_dma;
+	}
+	retval = request_irq(IRQ_Ser0UDC, udc_int_hndlr, IRQF_DISABLED,
+			driver_name, dev);
+	if (retval) {
+		ERROR(dev, "couldn't get irq, err %d\n", retval);
+		goto err_irq;
+	}
+
+	INFO(dev, "initialized, rx %p tx %p irq %d\n",
+		dev->ep[1].dmaregs, dev->ep[2].dmaregs, IRQ_Ser0UDC);
+	return 0;
+
+err_irq:
+	sa1100_free_dma(dev->ep[2].dmaregs);
+	usbd_info.dmaregs_rx = 0;
+err_tx_dma:
+	sa1100_free_dma(dev->ep[1].dmaregs);
+	usbd_info.dmaregs_tx = 0;
+err_rx_dma:
+	return retval;
+}
+
+static int __exit sa1100_udc_remove(struct device *_dev)
+{
+	struct sa1100_udc *dev = dev_get_drvdata(_dev);
+
+	udc_disable(dev);
+	unregister_proc_entry();
+	usb_gadget_unregister_driver(dev->driver);
+	sa1100_free_dma(dev->ep[1].dmaregs);
+	sa1100_free_dma(dev->ep[2].dmaregs);
+	free_irq(IRQ_Ser0UDC, dev);
+	dev_set_drvdata(_dev,NULL);
+	the_controller = NULL;
+	return 0;
+}
+
+static struct device_driver udc_driver = {
+	.name		= "sa11x0-udc",
+	.bus		= &platform_bus_type,
+	.probe		= sa1100_udc_probe,
+	.remove		= __exit_p(sa1100_udc_remove),
+//	.suspend	= sa1100_udc_suspend,
+//	.resume		= sa1100_udc_resume,
+	.owner		= THIS_MODULE,
+};
+
+static int __init udc_init(void)
+{
+	printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
+#ifdef NCB_DMA_FIX
+	send_buffer = (char*) kzalloc(SEND_BUFFER_SIZE, GFP_KERNEL | GFP_DMA );
+	receive_buffer = (char*) kzalloc(RECEIVE_BUFFER_SIZE, GFP_KERNEL | GFP_DMA );
+#endif
+	return driver_register(&udc_driver);
+}
+module_init(udc_init);
+
+static void __exit udc_exit(void)
+{
+#ifdef NCB_DMA_FIX
+	if (send_buffer) {
+	    kfree(send_buffer);
+	    send_buffer = NULL;
+	}
+	if (receive_buffer) {
+	    kfree(receive_buffer);
+	    receive_buffer = NULL;
+	}
+#endif
+	driver_unregister(&udc_driver);
+}
+module_exit(udc_exit);
diff --git a/drivers/usb/gadget/sa1100_udc.h b/drivers/usb/gadget/sa1100_udc.h
new file mode 100644
index 0000000..acb665a
--- /dev/null
+++ b/drivers/usb/gadget/sa1100_udc.h
@@ -0,0 +1,94 @@
+/*
+ * internals of "new style" UDC controller
+ * <linux/usb_gadget.h> replaces ARM-specific "sa1100_usb.h".
+ */
+
+struct sa1100_ep {
+	struct usb_ep				ep;
+	struct sa1100_udc			*dev;
+	//unsigned long				irqs;
+
+	const struct usb_endpoint_descriptor	*desc;
+	struct list_head			queue;
+	dma_regs_t 				*dmaregs;
+	unsigned 				stopped : 1;
+};
+
+struct sa1100_request {
+	struct usb_request			req;
+	struct list_head			queue;
+// NCB	unsigned				mapped : 1;
+};
+
+enum ep0_state {
+	EP0_IDLE,
+	EP0_IN_DATA_PHASE,
+	EP0_OUT_DATA_PHASE,
+	EP0_END_XFER,
+	EP0_STALL,
+};
+
+#define EP0_FIFO_SIZE	((unsigned)8)
+#define BULK_FIFO_SIZE	((unsigned)64)
+//#define ISO_FIFO_SIZE	((unsigned)256)
+//#define INT_FIFO_SIZE	((unsigned)8)
+
+struct udc_stats {
+	struct ep0stats {
+		unsigned long		ops;
+		unsigned long		bytes;
+	} read, write;
+	unsigned long			irqs;
+};
+
+struct sa1100_udc {
+	struct usb_gadget			gadget;
+	struct usb_gadget_driver 		*driver;
+	struct device				*dev;
+	enum ep0_state				ep0state;
+	struct udc_stats			stats;
+// NCB	spinlock_t				lock;
+// NCB	dma_regs_t 				*dmaregs_tx, *dmaregs_rx;
+	unsigned				got_irq : 1,
+						vbus : 1,
+						pullup : 1,
+						has_cfr : 1,
+						req_pending : 1,
+						req_std : 1,
+						req_config : 1;
+	struct timer_list			timer;
+	u64 dma_mask;
+	unsigned char				address;
+	struct sa1100_ep			ep[3];
+	int					ep0_req_len;
+};
+
+/*-------------------------------------------------------------------------*/
+
+#define xprintk(dev,level,fmt,args...) \
+	printk(level "%s: " fmt , driver_name , ## args)
+
+#ifdef DEBUG
+#undef DEBUG
+#define DEBUG(dev,fmt,args...) \
+	xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DEBUG(dev,fmt,args...) \
+	do { } while (0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDEBUG DEBUG
+#else
+#define VDEBUG(dev,fmt,args...) \
+	do { } while (0)
+#endif	/* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+	xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+	xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+	xprintk(dev , KERN_INFO , fmt , ## args)
+
+/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index fa019fa..b3699af 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -1,15 +1,9 @@
 /*
- * g_serial.c -- USB gadget serial driver
+ * serial.c -- USB gadget serial driver
  *
- * Copyright 2003 (C) Al Borchers (alborchers@steinerpoint.com)
- *
- * This code is based in part on the Gadget Zero driver, which
- * is Copyright (C) 2003 by David Brownell, all rights reserved.
- *
- * This code also borrows from usbserial.c, which is
- * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
- * Copyright (C) 2000 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2008 by David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
  *
  * This software is distributed under the terms of the GNU General
  * Public License ("GPL") as published by the Free Software Foundation,
@@ -22,2254 +16,237 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 
-#include <linux/usb/ch9.h>
-#include <linux/usb/cdc.h>
-#include <linux/usb/gadget.h>
-
+#include "u_serial.h"
 #include "gadget_chips.h"
 
 
 /* Defines */
 
-#define GS_VERSION_STR			"v2.2"
-#define GS_VERSION_NUM			0x2200
+#define GS_VERSION_STR			"v2.4"
+#define GS_VERSION_NUM			0x2400
 
 #define GS_LONG_NAME			"Gadget Serial"
-#define GS_SHORT_NAME			"g_serial"
-
-#define GS_MAJOR			127
-#define GS_MINOR_START			0
-
-/* REVISIT only one port is supported for now;
- * see gs_{send,recv}_packet() ... no multiplexing,
- * and no support for multiple ACM devices.
- */
-#define GS_NUM_PORTS			1
-
-#define GS_NUM_CONFIGS			1
-#define GS_NO_CONFIG_ID			0
-#define GS_BULK_CONFIG_ID		1
-#define GS_ACM_CONFIG_ID		2
-
-#define GS_MAX_NUM_INTERFACES		2
-#define GS_BULK_INTERFACE_ID		0
-#define GS_CONTROL_INTERFACE_ID		0
-#define GS_DATA_INTERFACE_ID		1
-
-#define GS_MAX_DESC_LEN			256
-
-#define GS_DEFAULT_READ_Q_SIZE		32
-#define GS_DEFAULT_WRITE_Q_SIZE		32
-
-#define GS_DEFAULT_WRITE_BUF_SIZE	8192
-#define GS_TMP_BUF_SIZE			8192
-
-#define GS_CLOSE_TIMEOUT		15
-
-#define GS_DEFAULT_USE_ACM		0
-
-/* 9600-8-N-1 ... matches init_termios.c_cflag and defaults
- * expected by "usbser.sys" on MS-Windows.
- */
-#define GS_DEFAULT_DTE_RATE		9600
-#define GS_DEFAULT_DATA_BITS		8
-#define GS_DEFAULT_PARITY		USB_CDC_NO_PARITY
-#define GS_DEFAULT_CHAR_FORMAT		USB_CDC_1_STOP_BITS
-
-/* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *
-choose_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
-		struct usb_endpoint_descriptor *fs)
-{
-	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
-		return hs;
-	return fs;
-}
-
-
-/* debug settings */
-#ifdef DEBUG
-static int debug = 1;
-#else
-#define	debug 0
-#endif
-
-#define gs_debug(format, arg...) \
-	do { if (debug) pr_debug(format, ## arg); } while (0)
-#define gs_debug_level(level, format, arg...) \
-	do { if (debug >= level) pr_debug(format, ## arg); } while (0)
+#define GS_VERSION_NAME			GS_LONG_NAME " " GS_VERSION_STR
 
+/*-------------------------------------------------------------------------*/
 
 /* Thanks to NetChip Technologies for donating this product ID.
- *
- * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
- * Instead:  allocate your own, using normal USB-IF procedures.
- */
+*
+* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
+* Instead:  allocate your own, using normal USB-IF procedures.
+*/
 #define GS_VENDOR_ID			0x0525	/* NetChip */
 #define GS_PRODUCT_ID			0xa4a6	/* Linux-USB Serial Gadget */
 #define GS_CDC_PRODUCT_ID		0xa4a7	/* ... as CDC-ACM */
 
-#define GS_LOG2_NOTIFY_INTERVAL		5	/* 1 << 5 == 32 msec */
-#define GS_NOTIFY_MAXPACKET		8
+/* string IDs are assigned dynamically */
 
+#define STRING_MANUFACTURER_IDX		0
+#define STRING_PRODUCT_IDX		1
+#define STRING_DESCRIPTION_IDX		2
 
-/* circular buffer */
-struct gs_buf {
-	unsigned int		buf_size;
-	char			*buf_buf;
-	char			*buf_get;
-	char			*buf_put;
-};
+static char manufacturer[50];
 
-/* the port structure holds info for each port, one for each minor number */
-struct gs_port {
-	struct gs_dev		*port_dev;	/* pointer to device struct */
-	struct tty_struct	*port_tty;	/* pointer to tty struct */
-	spinlock_t		port_lock;
-	int			port_num;
-	int			port_open_count;
-	int			port_in_use;	/* open/close in progress */
-	wait_queue_head_t	port_write_wait;/* waiting to write */
-	struct gs_buf		*port_write_buf;
-	struct usb_cdc_line_coding port_line_coding;	/* 8-N-1 etc */
-	u16			port_handshake_bits;
-#define RS232_RTS	(1 << 1)
-#define RS232_DTE	(1 << 0)
+static struct usb_string strings_dev[] = {
+	[STRING_MANUFACTURER_IDX].s = manufacturer,
+	[STRING_PRODUCT_IDX].s = GS_VERSION_NAME,
+	[STRING_DESCRIPTION_IDX].s = NULL /* updated; f(use_acm) */,
+	{  } /* end of list */
 };
 
-/* the device structure holds info for the USB device */
-struct gs_dev {
-	struct usb_gadget	*dev_gadget;	/* gadget device pointer */
-	spinlock_t		dev_lock;	/* lock for set/reset config */
-	int			dev_config;	/* configuration number */
-	struct usb_ep		*dev_notify_ep;	/* address of notify endpoint */
-	struct usb_ep		*dev_in_ep;	/* address of in endpoint */
-	struct usb_ep		*dev_out_ep;	/* address of out endpoint */
-	struct usb_endpoint_descriptor		/* descriptor of notify ep */
-				*dev_notify_ep_desc;
-	struct usb_endpoint_descriptor		/* descriptor of in endpoint */
-				*dev_in_ep_desc;
-	struct usb_endpoint_descriptor		/* descriptor of out endpoint */
-				*dev_out_ep_desc;
-	struct usb_request	*dev_ctrl_req;	/* control request */
-	struct list_head	dev_req_list;	/* list of write requests */
-	int			dev_sched_port;	/* round robin port scheduled */
-	struct gs_port		*dev_port[GS_NUM_PORTS]; /* the ports */
+static struct usb_gadget_strings stringtab_dev = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_dev,
 };
 
-
-/* Functions */
-
-/* tty driver internals */
-static int gs_send(struct gs_dev *dev);
-static int gs_send_packet(struct gs_dev *dev, char *packet,
-	unsigned int size);
-static int gs_recv_packet(struct gs_dev *dev, char *packet,
-	unsigned int size);
-static void gs_read_complete(struct usb_ep *ep, struct usb_request *req);
-static void gs_write_complete(struct usb_ep *ep, struct usb_request *req);
-
-/* gadget driver internals */
-static int gs_set_config(struct gs_dev *dev, unsigned config);
-static void gs_reset_config(struct gs_dev *dev);
-static int gs_build_config_buf(u8 *buf, struct usb_gadget *g,
-		u8 type, unsigned int index, int is_otg);
-
-static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,
-	gfp_t kmalloc_flags);
-static void gs_free_req(struct usb_ep *ep, struct usb_request *req);
-
-static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags);
-static void gs_free_ports(struct gs_dev *dev);
-
-/* circular buffer */
-static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags);
-static void gs_buf_free(struct gs_buf *gb);
-static void gs_buf_clear(struct gs_buf *gb);
-static unsigned int gs_buf_data_avail(struct gs_buf *gb);
-static unsigned int gs_buf_space_avail(struct gs_buf *gb);
-static unsigned int gs_buf_put(struct gs_buf *gb, const char *buf,
-	unsigned int count);
-static unsigned int gs_buf_get(struct gs_buf *gb, char *buf,
-	unsigned int count);
-
-
-/* Globals */
-
-static struct gs_dev *gs_device;
-
-static struct mutex gs_open_close_lock[GS_NUM_PORTS];
-
-
-/*-------------------------------------------------------------------------*/
-
-/* USB descriptors */
-
-#define GS_MANUFACTURER_STR_ID	1
-#define GS_PRODUCT_STR_ID	2
-#define GS_SERIAL_STR_ID	3
-#define GS_BULK_CONFIG_STR_ID	4
-#define GS_ACM_CONFIG_STR_ID	5
-#define GS_CONTROL_STR_ID	6
-#define GS_DATA_STR_ID		7
-
-/* static strings, in UTF-8 */
-static char manufacturer[50];
-static struct usb_string gs_strings[] = {
-	{ GS_MANUFACTURER_STR_ID, manufacturer },
-	{ GS_PRODUCT_STR_ID, GS_LONG_NAME },
-	{ GS_BULK_CONFIG_STR_ID, "Gadget Serial Bulk" },
-	{ GS_ACM_CONFIG_STR_ID, "Gadget Serial CDC ACM" },
-	{ GS_CONTROL_STR_ID, "Gadget Serial Control" },
-	{ GS_DATA_STR_ID, "Gadget Serial Data" },
-	{  } /* end of list */
-};
-
-static struct usb_gadget_strings gs_string_table = {
-	.language =		0x0409,	/* en-us */
-	.strings =		gs_strings,
+static struct usb_gadget_strings *dev_strings[] = {
+	&stringtab_dev,
+	NULL,
 };
 
-static struct usb_device_descriptor gs_device_desc = {
+static struct usb_device_descriptor device_desc = {
 	.bLength =		USB_DT_DEVICE_SIZE,
 	.bDescriptorType =	USB_DT_DEVICE,
 	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	/* .bDeviceClass = f(use_acm) */
 	.bDeviceSubClass =	0,
 	.bDeviceProtocol =	0,
+	/* .bMaxPacketSize0 = f(hardware) */
 	.idVendor =		__constant_cpu_to_le16(GS_VENDOR_ID),
-	.idProduct =		__constant_cpu_to_le16(GS_PRODUCT_ID),
-	.iManufacturer =	GS_MANUFACTURER_STR_ID,
-	.iProduct =		GS_PRODUCT_STR_ID,
-	.bNumConfigurations =	GS_NUM_CONFIGS,
+	/* .idProduct =	f(use_acm) */
+	/* .bcdDevice = f(hardware) */
+	/* .iManufacturer = DYNAMIC */
+	/* .iProduct = DYNAMIC */
+	.bNumConfigurations =	1,
 };
 
-static struct usb_otg_descriptor gs_otg_descriptor = {
-	.bLength =		sizeof(gs_otg_descriptor),
+static struct usb_otg_descriptor otg_descriptor = {
+	.bLength =		sizeof otg_descriptor,
 	.bDescriptorType =	USB_DT_OTG,
-	.bmAttributes =		USB_OTG_SRP,
-};
-
-static struct usb_config_descriptor gs_bulk_config_desc = {
-	.bLength =		USB_DT_CONFIG_SIZE,
-	.bDescriptorType =	USB_DT_CONFIG,
-	/* .wTotalLength computed dynamically */
-	.bNumInterfaces =	1,
-	.bConfigurationValue =	GS_BULK_CONFIG_ID,
-	.iConfiguration =	GS_BULK_CONFIG_STR_ID,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =		1,
-};
-
-static struct usb_config_descriptor gs_acm_config_desc = {
-	.bLength =		USB_DT_CONFIG_SIZE,
-	.bDescriptorType =	USB_DT_CONFIG,
-	/* .wTotalLength computed dynamically */
-	.bNumInterfaces =	2,
-	.bConfigurationValue =	GS_ACM_CONFIG_ID,
-	.iConfiguration =	GS_ACM_CONFIG_STR_ID,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =		1,
-};
-
-static const struct usb_interface_descriptor gs_bulk_interface_desc = {
-	.bLength =		USB_DT_INTERFACE_SIZE,
-	.bDescriptorType =	USB_DT_INTERFACE,
-	.bInterfaceNumber =	GS_BULK_INTERFACE_ID,
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-	.iInterface =		GS_DATA_STR_ID,
-};
-
-static const struct usb_interface_descriptor gs_control_interface_desc = {
-	.bLength =		USB_DT_INTERFACE_SIZE,
-	.bDescriptorType =	USB_DT_INTERFACE,
-	.bInterfaceNumber =	GS_CONTROL_INTERFACE_ID,
-	.bNumEndpoints =	1,
-	.bInterfaceClass =	USB_CLASS_COMM,
-	.bInterfaceSubClass =	USB_CDC_SUBCLASS_ACM,
-	.bInterfaceProtocol =	USB_CDC_ACM_PROTO_AT_V25TER,
-	.iInterface =		GS_CONTROL_STR_ID,
-};
-
-static const struct usb_interface_descriptor gs_data_interface_desc = {
-	.bLength =		USB_DT_INTERFACE_SIZE,
-	.bDescriptorType =	USB_DT_INTERFACE,
-	.bInterfaceNumber =	GS_DATA_INTERFACE_ID,
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_CDC_DATA,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-	.iInterface =		GS_DATA_STR_ID,
-};
-
-static const struct usb_cdc_header_desc gs_header_desc = {
-	.bLength =		sizeof(gs_header_desc),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
-	.bcdCDC =		__constant_cpu_to_le16(0x0110),
-};
-
-static const struct usb_cdc_call_mgmt_descriptor gs_call_mgmt_descriptor = {
-	.bLength =		sizeof(gs_call_mgmt_descriptor),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_CALL_MANAGEMENT_TYPE,
-	.bmCapabilities =	0,
-	.bDataInterface =	1,	/* index of data interface */
-};
-
-static struct usb_cdc_acm_descriptor gs_acm_descriptor = {
-	.bLength =		sizeof(gs_acm_descriptor),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
-	.bmCapabilities =	(1 << 1),
-};
-
-static const struct usb_cdc_union_desc gs_union_desc = {
-	.bLength =		sizeof(gs_union_desc),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
-	.bMasterInterface0 =	0,	/* index of control interface */
-	.bSlaveInterface0 =	1,	/* index of data interface */
-};
-
-static struct usb_endpoint_descriptor gs_fullspeed_notify_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
-	.bInterval =		1 << GS_LOG2_NOTIFY_INTERVAL,
-};
-
-static struct usb_endpoint_descriptor gs_fullspeed_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_endpoint_descriptor gs_fullspeed_out_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	USB_DIR_OUT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static const struct usb_descriptor_header *gs_bulk_fullspeed_function[] = {
-	(struct usb_descriptor_header *) &gs_otg_descriptor,
-	(struct usb_descriptor_header *) &gs_bulk_interface_desc,
-	(struct usb_descriptor_header *) &gs_fullspeed_in_desc,
-	(struct usb_descriptor_header *) &gs_fullspeed_out_desc,
-	NULL,
-};
-
-static const struct usb_descriptor_header *gs_acm_fullspeed_function[] = {
-	(struct usb_descriptor_header *) &gs_otg_descriptor,
-	(struct usb_descriptor_header *) &gs_control_interface_desc,
-	(struct usb_descriptor_header *) &gs_header_desc,
-	(struct usb_descriptor_header *) &gs_call_mgmt_descriptor,
-	(struct usb_descriptor_header *) &gs_acm_descriptor,
-	(struct usb_descriptor_header *) &gs_union_desc,
-	(struct usb_descriptor_header *) &gs_fullspeed_notify_desc,
-	(struct usb_descriptor_header *) &gs_data_interface_desc,
-	(struct usb_descriptor_header *) &gs_fullspeed_in_desc,
-	(struct usb_descriptor_header *) &gs_fullspeed_out_desc,
-	NULL,
-};
 
-static struct usb_endpoint_descriptor gs_highspeed_notify_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
-	.bInterval =		GS_LOG2_NOTIFY_INTERVAL+4,
-};
-
-static struct usb_endpoint_descriptor gs_highspeed_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor gs_highspeed_out_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
-};
-
-static struct usb_qualifier_descriptor gs_qualifier_desc = {
-	.bLength =		sizeof(struct usb_qualifier_descriptor),
-	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
-	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
-	/* assumes ep0 uses the same value for both speeds ... */
-	.bNumConfigurations =	GS_NUM_CONFIGS,
-};
-
-static const struct usb_descriptor_header *gs_bulk_highspeed_function[] = {
-	(struct usb_descriptor_header *) &gs_otg_descriptor,
-	(struct usb_descriptor_header *) &gs_bulk_interface_desc,
-	(struct usb_descriptor_header *) &gs_highspeed_in_desc,
-	(struct usb_descriptor_header *) &gs_highspeed_out_desc,
-	NULL,
+	/* REVISIT SRP-only hardware is possible, although
+	 * it would not be called "OTG" ...
+	 */
+	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
 };
 
-static const struct usb_descriptor_header *gs_acm_highspeed_function[] = {
-	(struct usb_descriptor_header *) &gs_otg_descriptor,
-	(struct usb_descriptor_header *) &gs_control_interface_desc,
-	(struct usb_descriptor_header *) &gs_header_desc,
-	(struct usb_descriptor_header *) &gs_call_mgmt_descriptor,
-	(struct usb_descriptor_header *) &gs_acm_descriptor,
-	(struct usb_descriptor_header *) &gs_union_desc,
-	(struct usb_descriptor_header *) &gs_highspeed_notify_desc,
-	(struct usb_descriptor_header *) &gs_data_interface_desc,
-	(struct usb_descriptor_header *) &gs_highspeed_in_desc,
-	(struct usb_descriptor_header *) &gs_highspeed_out_desc,
+static const struct usb_descriptor_header *otg_desc[] = {
+	(struct usb_descriptor_header *) &otg_descriptor,
 	NULL,
 };
 
-
 /*-------------------------------------------------------------------------*/
 
 /* Module */
-MODULE_DESCRIPTION(GS_LONG_NAME);
+MODULE_DESCRIPTION(GS_VERSION_NAME);
 MODULE_AUTHOR("Al Borchers");
+MODULE_AUTHOR("David Brownell");
 MODULE_LICENSE("GPL");
 
-#ifdef DEBUG
-module_param(debug, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on");
-#endif
-
-static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE;
-module_param(read_q_size, uint, S_IRUGO);
-MODULE_PARM_DESC(read_q_size, "Read request queue size, default=32");
-
-static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE;
-module_param(write_q_size, uint, S_IRUGO);
-MODULE_PARM_DESC(write_q_size, "Write request queue size, default=32");
+static int use_acm = true;
+module_param(use_acm, bool, 0);
+MODULE_PARM_DESC(use_acm, "Use CDC ACM, default=yes");
 
-static unsigned int write_buf_size = GS_DEFAULT_WRITE_BUF_SIZE;
-module_param(write_buf_size, uint, S_IRUGO);
-MODULE_PARM_DESC(write_buf_size, "Write buffer size, default=8192");
-
-static unsigned int use_acm = GS_DEFAULT_USE_ACM;
-module_param(use_acm, uint, S_IRUGO);
-MODULE_PARM_DESC(use_acm, "Use CDC ACM, 0=no, 1=yes, default=no");
+static unsigned n_ports = 1;
+module_param(n_ports, uint, 0);
+MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
 
 /*-------------------------------------------------------------------------*/
 
-/* TTY Driver */
-
-/*
- * gs_open
- */
-static int gs_open(struct tty_struct *tty, struct file *file)
-{
-	int port_num;
-	unsigned long flags;
-	struct gs_port *port;
-	struct gs_dev *dev;
-	struct gs_buf *buf;
-	struct mutex *mtx;
-	int ret;
-
-	port_num = tty->index;
-
-	gs_debug("gs_open: (%d,%p,%p)\n", port_num, tty, file);
-
-	if (port_num < 0 || port_num >= GS_NUM_PORTS) {
-		pr_err("gs_open: (%d,%p,%p) invalid port number\n",
-			port_num, tty, file);
-		return -ENODEV;
-	}
-
-	dev = gs_device;
-
-	if (dev == NULL) {
-		pr_err("gs_open: (%d,%p,%p) NULL device pointer\n",
-			port_num, tty, file);
-		return -ENODEV;
-	}
-
-	mtx = &gs_open_close_lock[port_num];
-	if (mutex_lock_interruptible(mtx)) {
-		pr_err("gs_open: (%d,%p,%p) interrupted waiting for mutex\n",
-			port_num, tty, file);
-		return -ERESTARTSYS;
-	}
-
-	spin_lock_irqsave(&dev->dev_lock, flags);
-
-	if (dev->dev_config == GS_NO_CONFIG_ID) {
-		pr_err("gs_open: (%d,%p,%p) device is not connected\n",
-			port_num, tty, file);
-		ret = -ENODEV;
-		goto exit_unlock_dev;
-	}
-
-	port = dev->dev_port[port_num];
-
-	if (port == NULL) {
-		pr_err("gs_open: (%d,%p,%p) NULL port pointer\n",
-			port_num, tty, file);
-		ret = -ENODEV;
-		goto exit_unlock_dev;
-	}
-
-	spin_lock(&port->port_lock);
-	spin_unlock(&dev->dev_lock);
-
-	if (port->port_dev == NULL) {
-		pr_err("gs_open: (%d,%p,%p) port disconnected (1)\n",
-			port_num, tty, file);
-		ret = -EIO;
-		goto exit_unlock_port;
-	}
-
-	if (port->port_open_count > 0) {
-		++port->port_open_count;
-		gs_debug("gs_open: (%d,%p,%p) already open\n",
-			port_num, tty, file);
-		ret = 0;
-		goto exit_unlock_port;
-	}
-
-	tty->driver_data = NULL;
-
-	/* mark port as in use, we can drop port lock and sleep if necessary */
-	port->port_in_use = 1;
-
-	/* allocate write buffer on first open */
-	if (port->port_write_buf == NULL) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		buf = gs_buf_alloc(write_buf_size, GFP_KERNEL);
-		spin_lock_irqsave(&port->port_lock, flags);
-
-		/* might have been disconnected while asleep, check */
-		if (port->port_dev == NULL) {
-			pr_err("gs_open: (%d,%p,%p) port disconnected (2)\n",
-				port_num, tty, file);
-			port->port_in_use = 0;
-			ret = -EIO;
-			goto exit_unlock_port;
-		}
-
-		if ((port->port_write_buf=buf) == NULL) {
-			pr_err("gs_open: (%d,%p,%p) cannot allocate "
-				"port write buffer\n",
-				port_num, tty, file);
-			port->port_in_use = 0;
-			ret = -ENOMEM;
-			goto exit_unlock_port;
-		}
-
-	}
-
-	/* wait for carrier detect (not implemented) */
-
-	/* might have been disconnected while asleep, check */
-	if (port->port_dev == NULL) {
-		pr_err("gs_open: (%d,%p,%p) port disconnected (3)\n",
-			port_num, tty, file);
-		port->port_in_use = 0;
-		ret = -EIO;
-		goto exit_unlock_port;
-	}
-
-	tty->driver_data = port;
-	port->port_tty = tty;
-	port->port_open_count = 1;
-	port->port_in_use = 0;
-
-	gs_debug("gs_open: (%d,%p,%p) completed\n", port_num, tty, file);
-
-	ret = 0;
-
-exit_unlock_port:
-	spin_unlock_irqrestore(&port->port_lock, flags);
-	mutex_unlock(mtx);
-	return ret;
-
-exit_unlock_dev:
-	spin_unlock_irqrestore(&dev->dev_lock, flags);
-	mutex_unlock(mtx);
-	return ret;
-
-}
-
-/*
- * gs_close
- */
-
-static int gs_write_finished_event_safely(struct gs_port *p)
-{
-	int cond;
-
-	spin_lock_irq(&(p)->port_lock);
-	cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf);
-	spin_unlock_irq(&(p)->port_lock);
-	return cond;
-}
-
-static void gs_close(struct tty_struct *tty, struct file *file)
-{
-	struct gs_port *port = tty->driver_data;
-	struct mutex *mtx;
-
-	if (port == NULL) {
-		pr_err("gs_close: NULL port pointer\n");
-		return;
-	}
-
-	gs_debug("gs_close: (%d,%p,%p)\n", port->port_num, tty, file);
-
-	mtx = &gs_open_close_lock[port->port_num];
-	mutex_lock(mtx);
-
-	spin_lock_irq(&port->port_lock);
-
-	if (port->port_open_count == 0) {
-		pr_err("gs_close: (%d,%p,%p) port is already closed\n",
-			port->port_num, tty, file);
-		goto exit;
-	}
-
-	if (port->port_open_count > 1) {
-		--port->port_open_count;
-		goto exit;
-	}
-
-	/* free disconnected port on final close */
-	if (port->port_dev == NULL) {
-		kfree(port);
-		goto exit;
-	}
-
-	/* mark port as closed but in use, we can drop port lock */
-	/* and sleep if necessary */
-	port->port_in_use = 1;
-	port->port_open_count = 0;
-
-	/* wait for write buffer to drain, or */
-	/* at most GS_CLOSE_TIMEOUT seconds */
-	if (gs_buf_data_avail(port->port_write_buf) > 0) {
-		spin_unlock_irq(&port->port_lock);
-		wait_event_interruptible_timeout(port->port_write_wait,
-					gs_write_finished_event_safely(port),
-					GS_CLOSE_TIMEOUT * HZ);
-		spin_lock_irq(&port->port_lock);
-	}
-
-	/* free disconnected port on final close */
-	/* (might have happened during the above sleep) */
-	if (port->port_dev == NULL) {
-		kfree(port);
-		goto exit;
-	}
-
-	gs_buf_clear(port->port_write_buf);
-
-	tty->driver_data = NULL;
-	port->port_tty = NULL;
-	port->port_in_use = 0;
-
-	gs_debug("gs_close: (%d,%p,%p) completed\n",
-		port->port_num, tty, file);
-
-exit:
-	spin_unlock_irq(&port->port_lock);
-	mutex_unlock(mtx);
-}
-
-/*
- * gs_write
- */
-static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
+static int __init serial_bind_config(struct usb_configuration *c)
 {
-	unsigned long flags;
-	struct gs_port *port = tty->driver_data;
-	int ret;
-
-	if (port == NULL) {
-		pr_err("gs_write: NULL port pointer\n");
-		return -EIO;
-	}
-
-	gs_debug("gs_write: (%d,%p) writing %d bytes\n", port->port_num, tty,
-		count);
-
-	if (count == 0)
-		return 0;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if (port->port_dev == NULL) {
-		pr_err("gs_write: (%d,%p) port is not connected\n",
-			port->port_num, tty);
-		ret = -EIO;
-		goto exit;
-	}
-
-	if (port->port_open_count == 0) {
-		pr_err("gs_write: (%d,%p) port is closed\n",
-			port->port_num, tty);
-		ret = -EBADF;
-		goto exit;
-	}
-
-	count = gs_buf_put(port->port_write_buf, buf, count);
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	gs_send(gs_device);
-
-	gs_debug("gs_write: (%d,%p) wrote %d bytes\n", port->port_num, tty,
-		count);
+	unsigned i;
+	int status = 0;
 
-	return count;
-
-exit:
-	spin_unlock_irqrestore(&port->port_lock, flags);
-	return ret;
-}
-
-/*
- * gs_put_char
- */
-static int gs_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	unsigned long flags;
-	struct gs_port *port = tty->driver_data;
-	int ret = 0;
-
-	if (port == NULL) {
-		pr_err("gs_put_char: NULL port pointer\n");
-		return 0;
-	}
-
-	gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p\n",
-		port->port_num, tty, ch, __builtin_return_address(0));
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if (port->port_dev == NULL) {
-		pr_err("gs_put_char: (%d,%p) port is not connected\n",
-			port->port_num, tty);
-		goto exit;
-	}
-
-	if (port->port_open_count == 0) {
-		pr_err("gs_put_char: (%d,%p) port is closed\n",
-			port->port_num, tty);
-		goto exit;
-	}
-
-	ret = gs_buf_put(port->port_write_buf, &ch, 1);
-
-exit:
-	spin_unlock_irqrestore(&port->port_lock, flags);
-	return ret;
-}
-
-/*
- * gs_flush_chars
- */
-static void gs_flush_chars(struct tty_struct *tty)
-{
-	unsigned long flags;
-	struct gs_port *port = tty->driver_data;
-
-	if (port == NULL) {
-		pr_err("gs_flush_chars: NULL port pointer\n");
-		return;
-	}
-
-	gs_debug("gs_flush_chars: (%d,%p)\n", port->port_num, tty);
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if (port->port_dev == NULL) {
-		pr_err("gs_flush_chars: (%d,%p) port is not connected\n",
-			port->port_num, tty);
-		goto exit;
-	}
-
-	if (port->port_open_count == 0) {
-		pr_err("gs_flush_chars: (%d,%p) port is closed\n",
-			port->port_num, tty);
-		goto exit;
-	}
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	gs_send(gs_device);
-
-	return;
-
-exit:
-	spin_unlock_irqrestore(&port->port_lock, flags);
-}
-
-/*
- * gs_write_room
- */
-static int gs_write_room(struct tty_struct *tty)
-{
-
-	int room = 0;
-	unsigned long flags;
-	struct gs_port *port = tty->driver_data;
-
-
-	if (port == NULL)
-		return 0;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if (port->port_dev != NULL && port->port_open_count > 0
-	&& port->port_write_buf != NULL)
-		room = gs_buf_space_avail(port->port_write_buf);
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	gs_debug("gs_write_room: (%d,%p) room=%d\n",
-		port->port_num, tty, room);
-
-	return room;
-}
-
-/*
- * gs_chars_in_buffer
- */
-static int gs_chars_in_buffer(struct tty_struct *tty)
-{
-	int chars = 0;
-	unsigned long flags;
-	struct gs_port *port = tty->driver_data;
-
-	if (port == NULL)
-		return 0;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if (port->port_dev != NULL && port->port_open_count > 0
-	&& port->port_write_buf != NULL)
-		chars = gs_buf_data_avail(port->port_write_buf);
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	gs_debug("gs_chars_in_buffer: (%d,%p) chars=%d\n",
-		port->port_num, tty, chars);
-
-	return chars;
-}
-
-/*
- * gs_throttle
- */
-static void gs_throttle(struct tty_struct *tty)
-{
-}
-
-/*
- * gs_unthrottle
- */
-static void gs_unthrottle(struct tty_struct *tty)
-{
-}
-
-/*
- * gs_break
- */
-static void gs_break(struct tty_struct *tty, int break_state)
-{
-}
-
-/*
- * gs_ioctl
- */
-static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct gs_port *port = tty->driver_data;
-
-	if (port == NULL) {
-		pr_err("gs_ioctl: NULL port pointer\n");
-		return -EIO;
+	for (i = 0; i < n_ports && status == 0; i++) {
+		if (use_acm)
+			status = acm_bind_config(c, i);
+		else
+			status = gser_bind_config(c, i);
 	}
-
-	gs_debug("gs_ioctl: (%d,%p,%p) cmd=0x%4.4x, arg=%lu\n",
-		port->port_num, tty, file, cmd, arg);
-
-	/* handle ioctls */
-
-	/* could not handle ioctl */
-	return -ENOIOCTLCMD;
-}
-
-/*
- * gs_set_termios
- */
-static void gs_set_termios(struct tty_struct *tty, struct ktermios *old)
-{
+	return status;
 }
 
-static const struct tty_operations gs_tty_ops = {
-	.open =			gs_open,
-	.close =		gs_close,
-	.write =		gs_write,
-	.put_char =		gs_put_char,
-	.flush_chars =		gs_flush_chars,
-	.write_room =		gs_write_room,
-	.ioctl =		gs_ioctl,
-	.set_termios =		gs_set_termios,
-	.throttle =		gs_throttle,
-	.unthrottle =		gs_unthrottle,
-	.break_ctl =		gs_break,
-	.chars_in_buffer =	gs_chars_in_buffer,
+static struct usb_configuration serial_config_driver = {
+	/* .label = f(use_acm) */
+	.bind		= serial_bind_config,
+	/* .bConfigurationValue = f(use_acm) */
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower	= 1,	/* 2 mA, minimal */
 };
 
-/*-------------------------------------------------------------------------*/
-
-/*
-* gs_send
-*
-* This function finds available write requests, calls
-* gs_send_packet to fill these packets with data, and
-* continues until either there are no more write requests
-* available or no more data to send.  This function is
-* run whenever data arrives or write requests are available.
-*/
-static int gs_send(struct gs_dev *dev)
-{
-	int ret,len;
-	unsigned long flags;
-	struct usb_ep *ep;
-	struct usb_request *req;
-
-	if (dev == NULL) {
-		pr_err("gs_send: NULL device pointer\n");
-		return -ENODEV;
-	}
-
-	spin_lock_irqsave(&dev->dev_lock, flags);
-
-	ep = dev->dev_in_ep;
-
-	while(!list_empty(&dev->dev_req_list)) {
-
-		req = list_entry(dev->dev_req_list.next,
-				struct usb_request, list);
-
-		len = gs_send_packet(dev, req->buf, ep->maxpacket);
-
-		if (len > 0) {
-			gs_debug_level(3, "gs_send: len=%d, 0x%2.2x "
-					"0x%2.2x 0x%2.2x ...\n", len,
-					*((unsigned char *)req->buf),
-					*((unsigned char *)req->buf+1),
-					*((unsigned char *)req->buf+2));
-			list_del(&req->list);
-			req->length = len;
-			spin_unlock_irqrestore(&dev->dev_lock, flags);
-			if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
-				pr_err(
-				"gs_send: cannot queue read request, ret=%d\n",
-					ret);
-				spin_lock_irqsave(&dev->dev_lock, flags);
-				break;
-			}
-			spin_lock_irqsave(&dev->dev_lock, flags);
-		} else {
-			break;
-		}
-
-	}
-
-	spin_unlock_irqrestore(&dev->dev_lock, flags);
-
-	return 0;
-}
-
-/*
- * gs_send_packet
- *
- * If there is data to send, a packet is built in the given
- * buffer and the size is returned.  If there is no data to
- * send, 0 is returned.  If there is any error a negative
- * error number is returned.
- *
- * Called during USB completion routine, on interrupt time.
- *
- * We assume that disconnect will not happen until all completion
- * routines have completed, so we can assume that the dev_port
- * array does not change during the lifetime of this function.
- */
-static int gs_send_packet(struct gs_dev *dev, char *packet, unsigned int size)
-{
-	unsigned int len;
-	struct gs_port *port;
-
-	/* TEMPORARY -- only port 0 is supported right now */
-	port = dev->dev_port[0];
-
-	if (port == NULL) {
-		pr_err("gs_send_packet: port=%d, NULL port pointer\n", 0);
-		return -EIO;
-	}
-
-	spin_lock(&port->port_lock);
-
-	len = gs_buf_data_avail(port->port_write_buf);
-	if (len < size)
-		size = len;
-
-	if (size == 0)
-		goto exit;
-
-	size = gs_buf_get(port->port_write_buf, packet, size);
-
-	if (port->port_tty)
-		wake_up_interruptible(&port->port_tty->write_wait);
-
-exit:
-	spin_unlock(&port->port_lock);
-	return size;
-}
-
-/*
- * gs_recv_packet
- *
- * Called for each USB packet received.  Reads the packet
- * header and stuffs the data in the appropriate tty buffer.
- * Returns 0 if successful, or a negative error number.
- *
- * Called during USB completion routine, on interrupt time.
- *
- * We assume that disconnect will not happen until all completion
- * routines have completed, so we can assume that the dev_port
- * array does not change during the lifetime of this function.
- */
-static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
-{
-	unsigned int len;
-	struct gs_port *port;
-	int ret;
-	struct tty_struct *tty;
-
-	/* TEMPORARY -- only port 0 is supported right now */
-	port = dev->dev_port[0];
-
-	if (port == NULL) {
-		pr_err("gs_recv_packet: port=%d, NULL port pointer\n",
-			port->port_num);
-		return -EIO;
-	}
-
-	spin_lock(&port->port_lock);
-
-	if (port->port_open_count == 0) {
-		pr_err("gs_recv_packet: port=%d, port is closed\n",
-			port->port_num);
-		ret = -EIO;
-		goto exit;
-	}
-
-
-	tty = port->port_tty;
-
-	if (tty == NULL) {
-		pr_err("gs_recv_packet: port=%d, NULL tty pointer\n",
-			port->port_num);
-		ret = -EIO;
-		goto exit;
-	}
-
-	if (port->port_tty->magic != TTY_MAGIC) {
-		pr_err("gs_recv_packet: port=%d, bad tty magic\n",
-			port->port_num);
-		ret = -EIO;
-		goto exit;
-	}
-
-	len = tty_buffer_request_room(tty, size);
-	if (len > 0) {
-		tty_insert_flip_string(tty, packet, len);
-		tty_flip_buffer_push(port->port_tty);
-		wake_up_interruptible(&port->port_tty->read_wait);
-	}
-	ret = 0;
-exit:
-	spin_unlock(&port->port_lock);
-	return ret;
-}
-
-/*
-* gs_read_complete
-*/
-static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
+static int __init gs_bind(struct usb_composite_dev *cdev)
 {
-	int ret;
-	struct gs_dev *dev = ep->driver_data;
-
-	if (dev == NULL) {
-		pr_err("gs_read_complete: NULL device pointer\n");
-		return;
-	}
+	int			gcnum;
+	struct usb_gadget	*gadget = cdev->gadget;
+	int			status;
 
-	switch(req->status) {
-	case 0:
-		/* normal completion */
-		gs_recv_packet(dev, req->buf, req->actual);
-requeue:
-		req->length = ep->maxpacket;
-		if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
-			pr_err(
-			"gs_read_complete: cannot queue read request, ret=%d\n",
-				ret);
-		}
-		break;
-
-	case -ESHUTDOWN:
-		/* disconnect */
-		gs_debug("gs_read_complete: shutdown\n");
-		gs_free_req(ep, req);
-		break;
-
-	default:
-		/* unexpected */
-		pr_err(
-		"gs_read_complete: unexpected status error, status=%d\n",
-			req->status);
-		goto requeue;
-		break;
-	}
-}
-
-/*
-* gs_write_complete
-*/
-static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct gs_dev *dev = ep->driver_data;
-
-	if (dev == NULL) {
-		pr_err("gs_write_complete: NULL device pointer\n");
-		return;
-	}
+	status = gserial_setup(cdev->gadget, n_ports);
+	if (status < 0)
+		return status;
 
-	switch(req->status) {
-	case 0:
-		/* normal completion */
-requeue:
-		spin_lock(&dev->dev_lock);
-		list_add(&req->list, &dev->dev_req_list);
-		spin_unlock(&dev->dev_lock);
-
-		gs_send(dev);
-
-		break;
-
-	case -ESHUTDOWN:
-		/* disconnect */
-		gs_debug("gs_write_complete: shutdown\n");
-		gs_free_req(ep, req);
-		break;
-
-	default:
-		pr_err(
-		"gs_write_complete: unexpected status error, status=%d\n",
-			req->status);
-		goto requeue;
-		break;
-	}
-}
+	/* Allocate string descriptor numbers ... note that string
+	 * contents can be overridden by the composite_dev glue.
+	 */
 
-/*-------------------------------------------------------------------------*/
+	/* device description: manufacturer, product */
+	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
+		init_utsname()->sysname, init_utsname()->release,
+		gadget->name);
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail;
+	strings_dev[STRING_MANUFACTURER_IDX].id = status;
 
-/* Gadget Driver */
+	device_desc.iManufacturer = status;
 
-/*
- * gs_unbind
- *
- * Called on module unload.  Frees the control request and device
- * structure.
- */
-static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget)
-{
-	struct gs_dev *dev = get_gadget_data(gadget);
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail;
+	strings_dev[STRING_PRODUCT_IDX].id = status;
 
-	gs_device = NULL;
+	device_desc.iProduct = status;
 
-	/* read/write requests already freed, only control request remains */
-	if (dev != NULL) {
-		if (dev->dev_ctrl_req != NULL) {
-			gs_free_req(gadget->ep0, dev->dev_ctrl_req);
-			dev->dev_ctrl_req = NULL;
-		}
-		gs_reset_config(dev);
-		gs_free_ports(dev);
-		kfree(dev);
-		set_gadget_data(gadget, NULL);
-	}
+	/* config description */
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail;
+	strings_dev[STRING_DESCRIPTION_IDX].id = status;
 
-	pr_info("gs_unbind: %s %s unbound\n", GS_LONG_NAME,
-		GS_VERSION_STR);
-}
-
-/*
- * gs_bind
- *
- * Called on module load.  Allocates and initializes the device
- * structure and a control request.
- */
-static int __init gs_bind(struct usb_gadget *gadget)
-{
-	int ret;
-	struct usb_ep *ep;
-	struct gs_dev *dev;
-	int gcnum;
-
-	/* Some controllers can't support CDC ACM:
-	 * - sh doesn't support multiple interfaces or configs;
-	 * - sa1100 doesn't have a third interrupt endpoint
-	 */
-	if (gadget_is_sh(gadget) || gadget_is_sa1100(gadget))
-		use_acm = 0;
+	serial_config_driver.iConfiguration = status;
 
+	/* set up other descriptors */
 	gcnum = usb_gadget_controller_number(gadget);
 	if (gcnum >= 0)
-		gs_device_desc.bcdDevice =
-				cpu_to_le16(GS_VERSION_NUM | gcnum);
+		device_desc.bcdDevice = cpu_to_le16(GS_VERSION_NUM | gcnum);
 	else {
+		/* this is so simple (for now, no altsettings) that it
+		 * SHOULD NOT have problems with bulk-capable hardware.
+		 * so warn about unrcognized controllers -- don't panic.
+		 *
+		 * things like configuration and altsetting numbering
+		 * can need hardware-specific attention though.
+		 */
 		pr_warning("gs_bind: controller '%s' not recognized\n",
 			gadget->name);
-		/* unrecognized, but safe unless bulk is REALLY quirky */
-		gs_device_desc.bcdDevice =
-			__constant_cpu_to_le16(GS_VERSION_NUM|0x0099);
-	}
-
-	dev = kzalloc(sizeof(struct gs_dev), GFP_KERNEL);
-	if (dev == NULL)
-		return -ENOMEM;
-
-	usb_ep_autoconfig_reset(gadget);
-
-	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc);
-	if (!ep)
-		goto autoconf_fail;
-	dev->dev_in_ep = ep;
-	ep->driver_data = dev;	/* claim the endpoint */
-
-	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc);
-	if (!ep)
-		goto autoconf_fail;
-	dev->dev_out_ep = ep;
-	ep->driver_data = dev;	/* claim the endpoint */
-
-	if (use_acm) {
-		ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc);
-		if (!ep) {
-			pr_err("gs_bind: cannot run ACM on %s\n", gadget->name);
-			goto autoconf_fail;
-		}
-		gs_device_desc.idProduct = __constant_cpu_to_le16(
-						GS_CDC_PRODUCT_ID),
-		dev->dev_notify_ep = ep;
-		ep->driver_data = dev;	/* claim the endpoint */
-	}
-
-	gs_device_desc.bDeviceClass = use_acm
-		? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;
-	gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-
-	if (gadget_is_dualspeed(gadget)) {
-		gs_qualifier_desc.bDeviceClass = use_acm
-			? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;
-		/* assume ep0 uses the same packet size for both speeds */
-		gs_qualifier_desc.bMaxPacketSize0 =
-			gs_device_desc.bMaxPacketSize0;
-		/* assume endpoints are dual-speed */
-		gs_highspeed_notify_desc.bEndpointAddress =
-			gs_fullspeed_notify_desc.bEndpointAddress;
-		gs_highspeed_in_desc.bEndpointAddress =
-			gs_fullspeed_in_desc.bEndpointAddress;
-		gs_highspeed_out_desc.bEndpointAddress =
-			gs_fullspeed_out_desc.bEndpointAddress;
-	}
-
-	usb_gadget_set_selfpowered(gadget);
-
-	if (gadget_is_otg(gadget)) {
-		gs_otg_descriptor.bmAttributes |= USB_OTG_HNP,
-		gs_bulk_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-		gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+		device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM | 0x0099);
 	}
 
-	gs_device = dev;
-
-	snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
-		init_utsname()->sysname, init_utsname()->release,
-		gadget->name);
-
-	dev->dev_gadget = gadget;
-	spin_lock_init(&dev->dev_lock);
-	INIT_LIST_HEAD(&dev->dev_req_list);
-	set_gadget_data(gadget, dev);
-
-	if ((ret=gs_alloc_ports(dev, GFP_KERNEL)) != 0) {
-		pr_err("gs_bind: cannot allocate ports\n");
-		gs_unbind(gadget);
-		return ret;
+	if (gadget_is_otg(cdev->gadget)) {
+		serial_config_driver.descriptors = otg_desc;
+		serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	/* preallocate control response and buffer */
-	dev->dev_ctrl_req = gs_alloc_req(gadget->ep0, GS_MAX_DESC_LEN,
-		GFP_KERNEL);
-	if (dev->dev_ctrl_req == NULL) {
-		gs_unbind(gadget);
-		return -ENOMEM;
-	}
-	gadget->ep0->driver_data = dev;
+	/* register our configuration */
+	status = usb_add_config(cdev, &serial_config_driver);
+	if (status < 0)
+		goto fail;
 
-	pr_info("gs_bind: %s %s bound\n",
-		GS_LONG_NAME, GS_VERSION_STR);
+	INFO(cdev, "%s\n", GS_VERSION_NAME);
 
 	return 0;
 
-autoconf_fail:
-	kfree(dev);
-	pr_err("gs_bind: cannot autoconfigure on %s\n", gadget->name);
-	return -ENODEV;
-}
-
-static int gs_setup_standard(struct usb_gadget *gadget,
-	const struct usb_ctrlrequest *ctrl)
-{
-	int ret = -EOPNOTSUPP;
-	struct gs_dev *dev = get_gadget_data(gadget);
-	struct usb_request *req = dev->dev_ctrl_req;
-	u16 wIndex = le16_to_cpu(ctrl->wIndex);
-	u16 wValue = le16_to_cpu(ctrl->wValue);
-	u16 wLength = le16_to_cpu(ctrl->wLength);
-
-	switch (ctrl->bRequest) {
-	case USB_REQ_GET_DESCRIPTOR:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			break;
-
-		switch (wValue >> 8) {
-		case USB_DT_DEVICE:
-			ret = min(wLength,
-				(u16)sizeof(struct usb_device_descriptor));
-			memcpy(req->buf, &gs_device_desc, ret);
-			break;
-
-		case USB_DT_DEVICE_QUALIFIER:
-			if (!gadget_is_dualspeed(gadget))
-				break;
-			ret = min(wLength,
-				(u16)sizeof(struct usb_qualifier_descriptor));
-			memcpy(req->buf, &gs_qualifier_desc, ret);
-			break;
-
-		case USB_DT_OTHER_SPEED_CONFIG:
-			if (!gadget_is_dualspeed(gadget))
-				break;
-			/* fall through */
-		case USB_DT_CONFIG:
-			ret = gs_build_config_buf(req->buf, gadget,
-				wValue >> 8, wValue & 0xff,
-				gadget_is_otg(gadget));
-			if (ret >= 0)
-				ret = min(wLength, (u16)ret);
-			break;
-
-		case USB_DT_STRING:
-			/* wIndex == language code. */
-			ret = usb_gadget_get_string(&gs_string_table,
-				wValue & 0xff, req->buf);
-			if (ret >= 0)
-				ret = min(wLength, (u16)ret);
-			break;
-		}
-		break;
-
-	case USB_REQ_SET_CONFIGURATION:
-		if (ctrl->bRequestType != 0)
-			break;
-		spin_lock(&dev->dev_lock);
-		ret = gs_set_config(dev, wValue);
-		spin_unlock(&dev->dev_lock);
-		break;
-
-	case USB_REQ_GET_CONFIGURATION:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			break;
-		*(u8 *)req->buf = dev->dev_config;
-		ret = min(wLength, (u16)1);
-		break;
-
-	case USB_REQ_SET_INTERFACE:
-		if (ctrl->bRequestType != USB_RECIP_INTERFACE
-				|| !dev->dev_config
-				|| wIndex >= GS_MAX_NUM_INTERFACES)
-			break;
-		if (dev->dev_config == GS_BULK_CONFIG_ID
-				&& wIndex != GS_BULK_INTERFACE_ID)
-			break;
-		/* no alternate interface settings */
-		if (wValue != 0)
-			break;
-		spin_lock(&dev->dev_lock);
-		/* PXA hardware partially handles SET_INTERFACE;
-		 * we need to kluge around that interference.  */
-		if (gadget_is_pxa(gadget)) {
-			ret = gs_set_config(dev, use_acm ?
-				GS_ACM_CONFIG_ID : GS_BULK_CONFIG_ID);
-			goto set_interface_done;
-		}
-		if (dev->dev_config != GS_BULK_CONFIG_ID
-				&& wIndex == GS_CONTROL_INTERFACE_ID) {
-			if (dev->dev_notify_ep) {
-				usb_ep_disable(dev->dev_notify_ep);
-				usb_ep_enable(dev->dev_notify_ep, dev->dev_notify_ep_desc);
-			}
-		} else {
-			usb_ep_disable(dev->dev_in_ep);
-			usb_ep_disable(dev->dev_out_ep);
-			usb_ep_enable(dev->dev_in_ep, dev->dev_in_ep_desc);
-			usb_ep_enable(dev->dev_out_ep, dev->dev_out_ep_desc);
-		}
-		ret = 0;
-set_interface_done:
-		spin_unlock(&dev->dev_lock);
-		break;
-
-	case USB_REQ_GET_INTERFACE:
-		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)
-		|| dev->dev_config == GS_NO_CONFIG_ID)
-			break;
-		if (wIndex >= GS_MAX_NUM_INTERFACES
-				|| (dev->dev_config == GS_BULK_CONFIG_ID
-				&& wIndex != GS_BULK_INTERFACE_ID)) {
-			ret = -EDOM;
-			break;
-		}
-		/* no alternate interface settings */
-		*(u8 *)req->buf = 0;
-		ret = min(wLength, (u16)1);
-		break;
-
-	default:
-		pr_err("gs_setup: unknown standard request, type=%02x, "
-			"request=%02x, value=%04x, index=%04x, length=%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			wValue, wIndex, wLength);
-		break;
-	}
-
-	return ret;
+fail:
+	gserial_cleanup();
+	return status;
 }
 
-static void gs_setup_complete_set_line_coding(struct usb_ep *ep,
-		struct usb_request *req)
-{
-	struct gs_dev *dev = ep->driver_data;
-	struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */
-
-	switch (req->status) {
-	case 0:
-		/* normal completion */
-		if (req->actual != sizeof(port->port_line_coding))
-			usb_ep_set_halt(ep);
-		else if (port) {
-			struct usb_cdc_line_coding	*value = req->buf;
-
-			/* REVISIT:  we currently just remember this data.
-			 * If we change that, (a) validate it first, then
-			 * (b) update whatever hardware needs updating.
-			 */
-			spin_lock(&port->port_lock);
-			port->port_line_coding = *value;
-			spin_unlock(&port->port_lock);
-		}
-		break;
-
-	case -ESHUTDOWN:
-		/* disconnect */
-		gs_free_req(ep, req);
-		break;
-
-	default:
-		/* unexpected */
-		break;
-	}
-	return;
-}
-
-static int gs_setup_class(struct usb_gadget *gadget,
-	const struct usb_ctrlrequest *ctrl)
-{
-	int ret = -EOPNOTSUPP;
-	struct gs_dev *dev = get_gadget_data(gadget);
-	struct gs_port *port = dev->dev_port[0];	/* ACM only has one port */
-	struct usb_request *req = dev->dev_ctrl_req;
-	u16 wIndex = le16_to_cpu(ctrl->wIndex);
-	u16 wValue = le16_to_cpu(ctrl->wValue);
-	u16 wLength = le16_to_cpu(ctrl->wLength);
-
-	switch (ctrl->bRequest) {
-	case USB_CDC_REQ_SET_LINE_CODING:
-		if (wLength != sizeof(struct usb_cdc_line_coding))
-			break;
-		ret = wLength;
-		req->complete = gs_setup_complete_set_line_coding;
-		break;
-
-	case USB_CDC_REQ_GET_LINE_CODING:
-		ret = min_t(int, wLength, sizeof(struct usb_cdc_line_coding));
-		if (port) {
-			spin_lock(&port->port_lock);
-			memcpy(req->buf, &port->port_line_coding, ret);
-			spin_unlock(&port->port_lock);
-		}
-		break;
-
-	case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
-		if (wLength != 0)
-			break;
-		ret = 0;
-		if (port) {
-			/* REVISIT:  we currently just remember this data.
-			 * If we change that, update whatever hardware needs
-			 * updating.
-			 */
-			spin_lock(&port->port_lock);
-			port->port_handshake_bits = wValue;
-			spin_unlock(&port->port_lock);
-		}
-		break;
-
-	default:
-		/* NOTE:  strictly speaking, we should accept AT-commands
-		 * using SEND_ENCPSULATED_COMMAND/GET_ENCAPSULATED_RESPONSE.
-		 * But our call management descriptor says we don't handle
-		 * call management, so we should be able to get by without
-		 * handling those "required" commands (except by stalling).
-		 */
-		pr_err("gs_setup: unknown class request, "
-				"type=%02x, request=%02x, value=%04x, "
-				"index=%04x, length=%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			wValue, wIndex, wLength);
-		break;
-	}
-
-	return ret;
-}
-
-/*
- * gs_setup_complete
- */
-static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	if (req->status || req->actual != req->length) {
-		pr_err("gs_setup_complete: status error, status=%d, "
-			"actual=%d, length=%d\n",
-			req->status, req->actual, req->length);
-	}
-}
-
-/*
- * gs_setup
- *
- * Implements all the control endpoint functionality that's not
- * handled in hardware or the hardware driver.
- *
- * Returns the size of the data sent to the host, or a negative
- * error number.
- */
-static int gs_setup(struct usb_gadget *gadget,
-	const struct usb_ctrlrequest *ctrl)
-{
-	int		ret = -EOPNOTSUPP;
-	struct gs_dev	*dev = get_gadget_data(gadget);
-	struct usb_request *req = dev->dev_ctrl_req;
-	u16		wIndex = le16_to_cpu(ctrl->wIndex);
-	u16		wValue = le16_to_cpu(ctrl->wValue);
-	u16		wLength = le16_to_cpu(ctrl->wLength);
-
-	req->complete = gs_setup_complete;
-
-	switch (ctrl->bRequestType & USB_TYPE_MASK) {
-	case USB_TYPE_STANDARD:
-		ret = gs_setup_standard(gadget, ctrl);
-		break;
-
-	case USB_TYPE_CLASS:
-		ret = gs_setup_class(gadget, ctrl);
-		break;
-
-	default:
-		pr_err("gs_setup: unknown request, type=%02x, request=%02x, "
-			"value=%04x, index=%04x, length=%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			wValue, wIndex, wLength);
-		break;
-	}
-
-	/* respond with data transfer before status phase? */
-	if (ret >= 0) {
-		req->length = ret;
-		req->zero = ret < wLength
-				&& (ret % gadget->ep0->maxpacket) == 0;
-		ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
-		if (ret < 0) {
-			pr_err("gs_setup: cannot queue response, ret=%d\n",
-				ret);
-			req->status = 0;
-			gs_setup_complete(gadget->ep0, req);
-		}
-	}
-
-	/* device either stalls (ret < 0) or reports success */
-	return ret;
-}
-
-/*
- * gs_disconnect
- *
- * Called when the device is disconnected.  Frees the closed
- * ports and disconnects open ports.  Open ports will be freed
- * on close.  Then reallocates the ports for the next connection.
- */
-static void gs_disconnect(struct usb_gadget *gadget)
-{
-	unsigned long flags;
-	struct gs_dev *dev = get_gadget_data(gadget);
-
-	spin_lock_irqsave(&dev->dev_lock, flags);
-
-	gs_reset_config(dev);
-
-	/* free closed ports and disconnect open ports */
-	/* (open ports will be freed when closed) */
-	gs_free_ports(dev);
-
-	/* re-allocate ports for the next connection */
-	if (gs_alloc_ports(dev, GFP_ATOMIC) != 0)
-		pr_err("gs_disconnect: cannot re-allocate ports\n");
-
-	spin_unlock_irqrestore(&dev->dev_lock, flags);
-
-	pr_info("gs_disconnect: %s disconnected\n", GS_LONG_NAME);
-}
-
-static struct usb_gadget_driver gs_gadget_driver = {
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-	.speed =		USB_SPEED_HIGH,
-#else
-	.speed =		USB_SPEED_FULL,
-#endif /* CONFIG_USB_GADGET_DUALSPEED */
-	.function =		GS_LONG_NAME,
-	.bind =			gs_bind,
-	.unbind =		gs_unbind,
-	.setup =		gs_setup,
-	.disconnect =		gs_disconnect,
-	.driver = {
-		.name =		GS_SHORT_NAME,
-		.owner =	THIS_MODULE,
-	},
+static struct usb_composite_driver gserial_driver = {
+	.name		= "g_serial",
+	.dev		= &device_desc,
+	.strings	= dev_strings,
+	.bind		= gs_bind,
 };
 
-/*
- * gs_set_config
- *
- * Configures the device by enabling device specific
- * optimizations, setting up the endpoints, allocating
- * read and write requests and queuing read requests.
- *
- * The device lock must be held when calling this function.
- */
-static int gs_set_config(struct gs_dev *dev, unsigned config)
+static int __init init(void)
 {
-	int i;
-	int ret = 0;
-	struct usb_gadget *gadget = dev->dev_gadget;
-	struct usb_ep *ep;
-	struct usb_endpoint_descriptor *out, *in, *notify;
-	struct usb_request *req;
-
-	if (dev == NULL) {
-		pr_err("gs_set_config: NULL device pointer\n");
-		return 0;
-	}
-
-	if (config == dev->dev_config)
-		return 0;
-
-	gs_reset_config(dev);
-
-	switch (config) {
-	case GS_NO_CONFIG_ID:
-		return 0;
-	case GS_BULK_CONFIG_ID:
-		if (use_acm)
-			return -EINVAL;
-		break;
-	case GS_ACM_CONFIG_ID:
-		if (!use_acm)
-			return -EINVAL;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	in = choose_ep_desc(gadget,
-			&gs_highspeed_in_desc,
-			&gs_fullspeed_in_desc);
-	out = choose_ep_desc(gadget,
-			&gs_highspeed_out_desc,
-			&gs_fullspeed_out_desc);
-	notify = dev->dev_notify_ep
-		? choose_ep_desc(gadget,
-				&gs_highspeed_notify_desc,
-				&gs_fullspeed_notify_desc)
-		: NULL;
-
-	ret = usb_ep_enable(dev->dev_in_ep, in);
-	if (ret == 0) {
-		dev->dev_in_ep_desc = in;
-	} else {
-		pr_debug("%s: cannot enable %s %s, ret=%d\n",
-			__func__, "IN", dev->dev_in_ep->name, ret);
-		return ret;
-	}
-
-	ret = usb_ep_enable(dev->dev_out_ep, out);
-	if (ret == 0) {
-		dev->dev_out_ep_desc = out;
-	} else {
-		pr_debug("%s: cannot enable %s %s, ret=%d\n",
-			__func__, "OUT", dev->dev_out_ep->name, ret);
-fail0:
-		usb_ep_disable(dev->dev_in_ep);
-		return ret;
-	}
-
-	if (notify) {
-		ret = usb_ep_enable(dev->dev_notify_ep, notify);
-		if (ret == 0) {
-			dev->dev_notify_ep_desc = notify;
-		} else {
-			pr_debug("%s: cannot enable %s %s, ret=%d\n",
-				__func__, "NOTIFY",
-				dev->dev_notify_ep->name, ret);
-			usb_ep_disable(dev->dev_out_ep);
-			goto fail0;
-		}
-	}
-
-	dev->dev_config = config;
-
-	/* allocate and queue read requests */
-	ep = dev->dev_out_ep;
-	for (i=0; i<read_q_size && ret == 0; i++) {
-		if ((req=gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC))) {
-			req->complete = gs_read_complete;
-			if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
-				pr_err("gs_set_config: cannot queue read "
-					"request, ret=%d\n", ret);
-			}
-		} else {
-			pr_err("gs_set_config: cannot allocate "
-					"read requests\n");
-			ret = -ENOMEM;
-			goto exit_reset_config;
-		}
-	}
-
-	/* allocate write requests, and put on free list */
-	ep = dev->dev_in_ep;
-	for (i=0; i<write_q_size; i++) {
-		req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC);
-		if (req) {
-			req->complete = gs_write_complete;
-			list_add(&req->list, &dev->dev_req_list);
-		} else {
-			pr_err("gs_set_config: cannot allocate "
-					"write requests\n");
-			ret = -ENOMEM;
-			goto exit_reset_config;
-		}
-	}
-
-	/* REVISIT the ACM mode should be able to actually *issue* some
-	 * notifications, for at least serial state change events if
-	 * not also for network connection; say so in bmCapabilities.
+	/* We *could* export two configs; that'd be much cleaner...
+	 * but neither of these product IDs was defined that way.
 	 */
-
-	pr_info("gs_set_config: %s configured, %s speed %s config\n",
-		GS_LONG_NAME,
-		gadget->speed == USB_SPEED_HIGH ? "high" : "full",
-		config == GS_BULK_CONFIG_ID ? "BULK" : "CDC-ACM");
-
-	return 0;
-
-exit_reset_config:
-	gs_reset_config(dev);
-	return ret;
-}
-
-/*
- * gs_reset_config
- *
- * Mark the device as not configured, disable all endpoints,
- * which forces completion of pending I/O and frees queued
- * requests, and free the remaining write requests on the
- * free list.
- *
- * The device lock must be held when calling this function.
- */
-static void gs_reset_config(struct gs_dev *dev)
-{
-	struct usb_request *req;
-
-	if (dev == NULL) {
-		pr_err("gs_reset_config: NULL device pointer\n");
-		return;
-	}
-
-	if (dev->dev_config == GS_NO_CONFIG_ID)
-		return;
-
-	dev->dev_config = GS_NO_CONFIG_ID;
-
-	/* free write requests on the free list */
-	while(!list_empty(&dev->dev_req_list)) {
-		req = list_entry(dev->dev_req_list.next,
-				struct usb_request, list);
-		list_del(&req->list);
-		gs_free_req(dev->dev_in_ep, req);
-	}
-
-	/* disable endpoints, forcing completion of pending i/o; */
-	/* completion handlers free their requests in this case */
-	if (dev->dev_notify_ep)
-		usb_ep_disable(dev->dev_notify_ep);
-	usb_ep_disable(dev->dev_in_ep);
-	usb_ep_disable(dev->dev_out_ep);
-}
-
-/*
- * gs_build_config_buf
- *
- * Builds the config descriptors in the given buffer and returns the
- * length, or a negative error number.
- */
-static int gs_build_config_buf(u8 *buf, struct usb_gadget *g,
-	u8 type, unsigned int index, int is_otg)
-{
-	int len;
-	int high_speed = 0;
-	const struct usb_config_descriptor *config_desc;
-	const struct usb_descriptor_header **function;
-
-	if (index >= gs_device_desc.bNumConfigurations)
-		return -EINVAL;
-
-	/* other speed switches high and full speed */
-	if (gadget_is_dualspeed(g)) {
-		high_speed = (g->speed == USB_SPEED_HIGH);
-		if (type == USB_DT_OTHER_SPEED_CONFIG)
-			high_speed = !high_speed;
-	}
-
 	if (use_acm) {
-		config_desc = &gs_acm_config_desc;
-		function = high_speed
-			? gs_acm_highspeed_function
-			: gs_acm_fullspeed_function;
+		serial_config_driver.label = "CDC ACM config";
+		serial_config_driver.bConfigurationValue = 2;
+		device_desc.bDeviceClass = USB_CLASS_COMM;
+		device_desc.idProduct =
+				__constant_cpu_to_le16(GS_CDC_PRODUCT_ID);
 	} else {
-		config_desc = &gs_bulk_config_desc;
-		function = high_speed
-			? gs_bulk_highspeed_function
-			: gs_bulk_fullspeed_function;
-	}
-
-	/* for now, don't advertise srp-only devices */
-	if (!is_otg)
-		function++;
-
-	len = usb_gadget_config_buf(config_desc, buf, GS_MAX_DESC_LEN, function);
-	if (len < 0)
-		return len;
-
-	((struct usb_config_descriptor *)buf)->bDescriptorType = type;
-
-	return len;
-}
-
-/*
- * gs_alloc_req
- *
- * Allocate a usb_request and its buffer.  Returns a pointer to the
- * usb_request or NULL if there is an error.
- */
-static struct usb_request *
-gs_alloc_req(struct usb_ep *ep, unsigned int len, gfp_t kmalloc_flags)
-{
-	struct usb_request *req;
-
-	if (ep == NULL)
-		return NULL;
-
-	req = usb_ep_alloc_request(ep, kmalloc_flags);
-
-	if (req != NULL) {
-		req->length = len;
-		req->buf = kmalloc(len, kmalloc_flags);
-		if (req->buf == NULL) {
-			usb_ep_free_request(ep, req);
-			return NULL;
-		}
+		serial_config_driver.label = "Generic Serial config";
+		serial_config_driver.bConfigurationValue = 1;
+		device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
+		device_desc.idProduct =
+				__constant_cpu_to_le16(GS_PRODUCT_ID);
 	}
+	strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
 
-	return req;
+	return usb_composite_register(&gserial_driver);
 }
+module_init(init);
 
-/*
- * gs_free_req
- *
- * Free a usb_request and its buffer.
- */
-static void gs_free_req(struct usb_ep *ep, struct usb_request *req)
+static void __exit cleanup(void)
 {
-	if (ep != NULL && req != NULL) {
-		kfree(req->buf);
-		usb_ep_free_request(ep, req);
-	}
-}
-
-/*
- * gs_alloc_ports
- *
- * Allocate all ports and set the gs_dev struct to point to them.
- * Return 0 if successful, or a negative error number.
- *
- * The device lock is normally held when calling this function.
- */
-static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags)
-{
-	int i;
-	struct gs_port *port;
-
-	if (dev == NULL)
-		return -EIO;
-
-	for (i=0; i<GS_NUM_PORTS; i++) {
-		if ((port=kzalloc(sizeof(struct gs_port), kmalloc_flags)) == NULL)
-			return -ENOMEM;
-
-		port->port_dev = dev;
-		port->port_num = i;
-		port->port_line_coding.dwDTERate = cpu_to_le32(GS_DEFAULT_DTE_RATE);
-		port->port_line_coding.bCharFormat = GS_DEFAULT_CHAR_FORMAT;
-		port->port_line_coding.bParityType = GS_DEFAULT_PARITY;
-		port->port_line_coding.bDataBits = GS_DEFAULT_DATA_BITS;
-		spin_lock_init(&port->port_lock);
-		init_waitqueue_head(&port->port_write_wait);
-
-		dev->dev_port[i] = port;
-	}
-
-	return 0;
-}
-
-/*
- * gs_free_ports
- *
- * Free all closed ports.  Open ports are disconnected by
- * freeing their write buffers, setting their device pointers
- * and the pointers to them in the device to NULL.  These
- * ports will be freed when closed.
- *
- * The device lock is normally held when calling this function.
- */
-static void gs_free_ports(struct gs_dev *dev)
-{
-	int i;
-	unsigned long flags;
-	struct gs_port *port;
-
-	if (dev == NULL)
-		return;
-
-	for (i=0; i<GS_NUM_PORTS; i++) {
-		if ((port=dev->dev_port[i]) != NULL) {
-			dev->dev_port[i] = NULL;
-
-			spin_lock_irqsave(&port->port_lock, flags);
-
-			if (port->port_write_buf != NULL) {
-				gs_buf_free(port->port_write_buf);
-				port->port_write_buf = NULL;
-			}
-
-			if (port->port_open_count > 0 || port->port_in_use) {
-				port->port_dev = NULL;
-				wake_up_interruptible(&port->port_write_wait);
-				if (port->port_tty) {
-					tty_hangup(port->port_tty);
-				}
-				spin_unlock_irqrestore(&port->port_lock, flags);
-			} else {
-				spin_unlock_irqrestore(&port->port_lock, flags);
-				kfree(port);
-			}
-
-		}
-	}
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Circular Buffer */
-
-/*
- * gs_buf_alloc
- *
- * Allocate a circular buffer and all associated memory.
- */
-static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags)
-{
-	struct gs_buf *gb;
-
-	if (size == 0)
-		return NULL;
-
-	gb = kmalloc(sizeof(struct gs_buf), kmalloc_flags);
-	if (gb == NULL)
-		return NULL;
-
-	gb->buf_buf = kmalloc(size, kmalloc_flags);
-	if (gb->buf_buf == NULL) {
-		kfree(gb);
-		return NULL;
-	}
-
-	gb->buf_size = size;
-	gb->buf_get = gb->buf_put = gb->buf_buf;
-
-	return gb;
-}
-
-/*
- * gs_buf_free
- *
- * Free the buffer and all associated memory.
- */
-static void gs_buf_free(struct gs_buf *gb)
-{
-	if (gb) {
-		kfree(gb->buf_buf);
-		kfree(gb);
-	}
-}
-
-/*
- * gs_buf_clear
- *
- * Clear out all data in the circular buffer.
- */
-static void gs_buf_clear(struct gs_buf *gb)
-{
-	if (gb != NULL)
-		gb->buf_get = gb->buf_put;
-		/* equivalent to a get of all data available */
-}
-
-/*
- * gs_buf_data_avail
- *
- * Return the number of bytes of data available in the circular
- * buffer.
- */
-static unsigned int gs_buf_data_avail(struct gs_buf *gb)
-{
-	if (gb != NULL)
-		return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
-	else
-		return 0;
-}
-
-/*
- * gs_buf_space_avail
- *
- * Return the number of bytes of space available in the circular
- * buffer.
- */
-static unsigned int gs_buf_space_avail(struct gs_buf *gb)
-{
-	if (gb != NULL)
-		return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
-	else
-		return 0;
-}
-
-/*
- * gs_buf_put
- *
- * Copy data data from a user buffer and put it into the circular buffer.
- * Restrict to the amount of space available.
- *
- * Return the number of bytes copied.
- */
-static unsigned int
-gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
-{
-	unsigned int len;
-
-	if (gb == NULL)
-		return 0;
-
-	len  = gs_buf_space_avail(gb);
-	if (count > len)
-		count = len;
-
-	if (count == 0)
-		return 0;
-
-	len = gb->buf_buf + gb->buf_size - gb->buf_put;
-	if (count > len) {
-		memcpy(gb->buf_put, buf, len);
-		memcpy(gb->buf_buf, buf+len, count - len);
-		gb->buf_put = gb->buf_buf + count - len;
-	} else {
-		memcpy(gb->buf_put, buf, count);
-		if (count < len)
-			gb->buf_put += count;
-		else /* count == len */
-			gb->buf_put = gb->buf_buf;
-	}
-
-	return count;
-}
-
-/*
- * gs_buf_get
- *
- * Get data from the circular buffer and copy to the given buffer.
- * Restrict to the amount of data available.
- *
- * Return the number of bytes copied.
- */
-static unsigned int
-gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count)
-{
-	unsigned int len;
-
-	if (gb == NULL)
-		return 0;
-
-	len = gs_buf_data_avail(gb);
-	if (count > len)
-		count = len;
-
-	if (count == 0)
-		return 0;
-
-	len = gb->buf_buf + gb->buf_size - gb->buf_get;
-	if (count > len) {
-		memcpy(buf, gb->buf_get, len);
-		memcpy(buf+len, gb->buf_buf, count - len);
-		gb->buf_get = gb->buf_buf + count - len;
-	} else {
-		memcpy(buf, gb->buf_get, count);
-		if (count < len)
-			gb->buf_get += count;
-		else /* count == len */
-			gb->buf_get = gb->buf_buf;
-	}
-
-	return count;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct tty_driver *gs_tty_driver;
-
-/*
- *  gs_module_init
- *
- *  Register as a USB gadget driver and a tty driver.
- */
-static int __init gs_module_init(void)
-{
-	int i;
-	int retval;
-
-	retval = usb_gadget_register_driver(&gs_gadget_driver);
-	if (retval) {
-		pr_err("gs_module_init: cannot register gadget driver, "
-			"ret=%d\n", retval);
-		return retval;
-	}
-
-	gs_tty_driver = alloc_tty_driver(GS_NUM_PORTS);
-	if (!gs_tty_driver)
-		return -ENOMEM;
-	gs_tty_driver->owner = THIS_MODULE;
-	gs_tty_driver->driver_name = GS_SHORT_NAME;
-	gs_tty_driver->name = "ttygs";
-	gs_tty_driver->major = GS_MAJOR;
-	gs_tty_driver->minor_start = GS_MINOR_START;
-	gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
-	gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	gs_tty_driver->init_termios = tty_std_termios;
-	/* must match GS_DEFAULT_DTE_RATE and friends */
-	gs_tty_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	gs_tty_driver->init_termios.c_ispeed = GS_DEFAULT_DTE_RATE;
-	gs_tty_driver->init_termios.c_ospeed = GS_DEFAULT_DTE_RATE;
-	tty_set_operations(gs_tty_driver, &gs_tty_ops);
-
-	for (i = 0; i < GS_NUM_PORTS; i++)
-		mutex_init(&gs_open_close_lock[i]);
-
-	retval = tty_register_driver(gs_tty_driver);
-	if (retval) {
-		usb_gadget_unregister_driver(&gs_gadget_driver);
-		put_tty_driver(gs_tty_driver);
-		pr_err("gs_module_init: cannot register tty driver, "
-				"ret=%d\n", retval);
-		return retval;
-	}
-
-	pr_info("gs_module_init: %s %s loaded\n",
-			GS_LONG_NAME, GS_VERSION_STR);
-	return 0;
-}
-module_init(gs_module_init);
-
-/*
- * gs_module_exit
- *
- * Unregister as a tty driver and a USB gadget driver.
- */
-static void __exit gs_module_exit(void)
-{
-	tty_unregister_driver(gs_tty_driver);
-	put_tty_driver(gs_tty_driver);
-	usb_gadget_unregister_driver(&gs_gadget_driver);
-
-	pr_info("gs_module_exit: %s %s unloaded\n",
-			GS_LONG_NAME, GS_VERSION_STR);
+	usb_composite_unregister(&gserial_driver);
+	gserial_cleanup();
 }
-module_exit(gs_module_exit);
+module_exit(cleanup);
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
new file mode 100644
index 0000000..3791e62
--- /dev/null
+++ b/drivers/usb/gadget/u_ether.c
@@ -0,0 +1,964 @@
+/*
+ * u_ether.c -- Ethernet-over-USB link layer utilities for Gadget stack
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+#include <linux/ctype.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+
+#include "u_ether.h"
+
+
+/*
+ * This component encapsulates the Ethernet link glue needed to provide
+ * one (!) network link through the USB gadget stack, normally "usb0".
+ *
+ * The control and data models are handled by the function driver which
+ * connects to this code; such as CDC Ethernet, "CDC Subset", or RNDIS.
+ * That includes all descriptor and endpoint management.
+ *
+ * Link level addressing is handled by this component using module
+ * parameters; if no such parameters are provided, random link level
+ * addresses are used.  Each end of the link uses one address.  The
+ * host end address is exported in various ways, and is often recorded
+ * in configuration databases.
+ *
+ * The driver which assembles each configuration using such a link is
+ * responsible for ensuring that each configuration includes at most one
+ * instance of is network link.  (The network layer provides ways for
+ * this single "physical" link to be used by multiple virtual links.)
+ */
+
+#define DRIVER_VERSION	"29-May-2008"
+
+struct eth_dev {
+	/* lock is held while accessing port_usb
+	 * or updating its backlink port_usb->ioport
+	 */
+	spinlock_t		lock;
+	struct gether		*port_usb;
+
+	struct net_device	*net;
+	struct usb_gadget	*gadget;
+
+	spinlock_t		req_lock;	/* guard {rx,tx}_reqs */
+	struct list_head	tx_reqs, rx_reqs;
+	atomic_t		tx_qlen;
+
+	unsigned		header_len;
+	struct sk_buff		*(*wrap)(struct sk_buff *skb);
+	int			(*unwrap)(struct sk_buff *skb);
+
+	struct work_struct	work;
+
+	unsigned long		todo;
+#define	WORK_RX_MEMORY		0
+
+	bool			zlp;
+	u8			host_mac[ETH_ALEN];
+};
+
+/*-------------------------------------------------------------------------*/
+
+#define RX_EXTRA	20	/* bytes guarding against rx overflows */
+
+#define DEFAULT_QLEN	2	/* double buffering by default */
+
+
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+
+static unsigned qmult = 5;
+module_param(qmult, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(qmult, "queue length multiplier at high speed");
+
+#else	/* full speed (low speed doesn't do bulk) */
+#define qmult		1
+#endif
+
+/* for dual-speed hardware, use deeper queues at highspeed */
+static inline int qlen(struct usb_gadget *gadget)
+{
+	if (gadget_is_dualspeed(gadget) && gadget->speed == USB_SPEED_HIGH)
+		return qmult * DEFAULT_QLEN;
+	else
+		return DEFAULT_QLEN;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* REVISIT there must be a better way than having two sets
+ * of debug calls ...
+ */
+
+#undef DBG
+#undef VDBG
+#undef ERROR
+#undef INFO
+
+#define xprintk(d, level, fmt, args...) \
+	printk(level "%s: " fmt , (d)->net->name , ## args)
+
+#ifdef DEBUG
+#undef DEBUG
+#define DBG(dev, fmt, args...) \
+	xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev, fmt, args...) \
+	do { } while (0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE_DEBUG
+#define VDBG	DBG
+#else
+#define VDBG(dev, fmt, args...) \
+	do { } while (0)
+#endif /* DEBUG */
+
+#define ERROR(dev, fmt, args...) \
+	xprintk(dev , KERN_ERR , fmt , ## args)
+#define INFO(dev, fmt, args...) \
+	xprintk(dev , KERN_INFO , fmt , ## args)
+
+/*-------------------------------------------------------------------------*/
+
+/* NETWORK DRIVER HOOKUP (to the layer above this driver) */
+
+static int eth_change_mtu(struct net_device *net, int new_mtu)
+{
+	struct eth_dev	*dev = netdev_priv(net);
+	unsigned long	flags;
+	int		status = 0;
+
+	/* don't change MTU on "live" link (peer won't know) */
+	spin_lock_irqsave(&dev->lock, flags);
+	if (dev->port_usb)
+		status = -EBUSY;
+	else if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN)
+		status = -ERANGE;
+	else
+		net->mtu = new_mtu;
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return status;
+}
+
+static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
+{
+	struct eth_dev	*dev = netdev_priv(net);
+
+	strlcpy(p->driver, "g_ether", sizeof p->driver);
+	strlcpy(p->version, DRIVER_VERSION, sizeof p->version);
+	strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version);
+	strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info);
+}
+
+static u32 eth_get_link(struct net_device *net)
+{
+	struct eth_dev	*dev = netdev_priv(net);
+	return dev->gadget->speed != USB_SPEED_UNKNOWN;
+}
+
+/* REVISIT can also support:
+ *   - WOL (by tracking suspends and issuing remote wakeup)
+ *   - msglevel (implies updated messaging)
+ *   - ... probably more ethtool ops
+ */
+
+static struct ethtool_ops ops = {
+	.get_drvinfo = eth_get_drvinfo,
+	.get_link = eth_get_link
+};
+
+static void defer_kevent(struct eth_dev *dev, int flag)
+{
+	if (test_and_set_bit(flag, &dev->todo))
+		return;
+	if (!schedule_work(&dev->work))
+		ERROR(dev, "kevent %d may have been dropped\n", flag);
+	else
+		DBG(dev, "kevent %d scheduled\n", flag);
+}
+
+static void rx_complete(struct usb_ep *ep, struct usb_request *req);
+
+static int
+rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
+{
+	struct sk_buff	*skb;
+	int		retval = -ENOMEM;
+	size_t		size = 0;
+	struct usb_ep	*out;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	if (dev->port_usb)
+		out = dev->port_usb->out_ep;
+	else
+		out = NULL;
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	if (!out)
+		return -ENOTCONN;
+
+
+	/* Padding up to RX_EXTRA handles minor disagreements with host.
+	 * Normally we use the USB "terminate on short read" convention;
+	 * so allow up to (N*maxpacket), since that memory is normally
+	 * already allocated.  Some hardware doesn't deal well with short
+	 * reads (e.g. DMA must be N*maxpacket), so for now don't trim a
+	 * byte off the end (to force hardware errors on overflow).
+	 *
+	 * RNDIS uses internal framing, and explicitly allows senders to
+	 * pad to end-of-packet.  That's potentially nice for speed, but
+	 * means receivers can't recover lost synch on their own (because
+	 * new packets don't only start after a short RX).
+	 */
+	size += sizeof(struct ethhdr) + dev->net->mtu + RX_EXTRA;
+	size += dev->port_usb->header_len;
+	size += out->maxpacket - 1;
+	size -= size % out->maxpacket;
+
+	skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
+	if (skb == NULL) {
+		DBG(dev, "no rx skb\n");
+		goto enomem;
+	}
+
+	/* Some platforms perform better when IP packets are aligned,
+	 * but on at least one, checksumming fails otherwise.  Note:
+	 * RNDIS headers involve variable numbers of LE32 values.
+	 */
+	skb_reserve(skb, NET_IP_ALIGN);
+
+	req->buf = skb->data;
+	req->length = size;
+	req->complete = rx_complete;
+	req->context = skb;
+
+	retval = usb_ep_queue(out, req, gfp_flags);
+	if (retval == -ENOMEM)
+enomem:
+		defer_kevent(dev, WORK_RX_MEMORY);
+	if (retval) {
+		DBG(dev, "rx submit --> %d\n", retval);
+		if (skb)
+			dev_kfree_skb_any(skb);
+		spin_lock_irqsave(&dev->req_lock, flags);
+		list_add(&req->list, &dev->rx_reqs);
+		spin_unlock_irqrestore(&dev->req_lock, flags);
+	}
+	return retval;
+}
+
+static void rx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct sk_buff	*skb = req->context;
+	struct eth_dev	*dev = ep->driver_data;
+	int		status = req->status;
+
+	switch (status) {
+
+	/* normal completion */
+	case 0:
+		skb_put(skb, req->actual);
+		if (dev->unwrap)
+			status = dev->unwrap(skb);
+		if (status < 0
+				|| ETH_HLEN > skb->len
+				|| skb->len > ETH_FRAME_LEN) {
+			dev->net->stats.rx_errors++;
+			dev->net->stats.rx_length_errors++;
+			DBG(dev, "rx length %d\n", skb->len);
+			break;
+		}
+
+		skb->protocol = eth_type_trans(skb, dev->net);
+		dev->net->stats.rx_packets++;
+		dev->net->stats.rx_bytes += skb->len;
+
+		/* no buffer copies needed, unless hardware can't
+		 * use skb buffers.
+		 */
+		status = netif_rx(skb);
+		skb = NULL;
+		break;
+
+	/* software-driven interface shutdown */
+	case -ECONNRESET:		/* unlink */
+	case -ESHUTDOWN:		/* disconnect etc */
+		VDBG(dev, "rx shutdown, code %d\n", status);
+		goto quiesce;
+
+	/* for hardware automagic (such as pxa) */
+	case -ECONNABORTED:		/* endpoint reset */
+		DBG(dev, "rx %s reset\n", ep->name);
+		defer_kevent(dev, WORK_RX_MEMORY);
+quiesce:
+		dev_kfree_skb_any(skb);
+		goto clean;
+
+	/* data overrun */
+	case -EOVERFLOW:
+		dev->net->stats.rx_over_errors++;
+		/* FALLTHROUGH */
+
+	default:
+		dev->net->stats.rx_errors++;
+		DBG(dev, "rx status %d\n", status);
+		break;
+	}
+
+	if (skb)
+		dev_kfree_skb_any(skb);
+	if (!netif_running(dev->net)) {
+clean:
+		spin_lock(&dev->req_lock);
+		list_add(&req->list, &dev->rx_reqs);
+		spin_unlock(&dev->req_lock);
+		req = NULL;
+	}
+	if (req)
+		rx_submit(dev, req, GFP_ATOMIC);
+}
+
+static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n)
+{
+	unsigned		i;
+	struct usb_request	*req;
+
+	if (!n)
+		return -ENOMEM;
+
+	/* queue/recycle up to N requests */
+	i = n;
+	list_for_each_entry(req, list, list) {
+		if (i-- == 0)
+			goto extra;
+	}
+	while (i--) {
+		req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+		if (!req)
+			return list_empty(list) ? -ENOMEM : 0;
+		list_add(&req->list, list);
+	}
+	return 0;
+
+extra:
+	/* free extras */
+	for (;;) {
+		struct list_head	*next;
+
+		next = req->list.next;
+		list_del(&req->list);
+		usb_ep_free_request(ep, req);
+
+		if (next == list)
+			break;
+
+		req = container_of(next, struct usb_request, list);
+	}
+	return 0;
+}
+
+static int alloc_requests(struct eth_dev *dev, struct gether *link, unsigned n)
+{
+	int	status;
+
+	spin_lock(&dev->req_lock);
+	status = prealloc(&dev->tx_reqs, link->in_ep, n);
+	if (status < 0)
+		goto fail;
+	status = prealloc(&dev->rx_reqs, link->out_ep, n);
+	if (status < 0)
+		goto fail;
+	goto done;
+fail:
+	DBG(dev, "can't alloc requests\n");
+done:
+	spin_unlock(&dev->req_lock);
+	return status;
+}
+
+static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)
+{
+	struct usb_request	*req;
+	unsigned long		flags;
+
+	/* fill unused rxq slots with some skb */
+	spin_lock_irqsave(&dev->req_lock, flags);
+	while (!list_empty(&dev->rx_reqs)) {
+		req = container_of(dev->rx_reqs.next,
+				struct usb_request, list);
+		list_del_init(&req->list);
+		spin_unlock_irqrestore(&dev->req_lock, flags);
+
+		if (rx_submit(dev, req, gfp_flags) < 0) {
+			defer_kevent(dev, WORK_RX_MEMORY);
+			return;
+		}
+
+		spin_lock_irqsave(&dev->req_lock, flags);
+	}
+	spin_unlock_irqrestore(&dev->req_lock, flags);
+}
+
+static void eth_work(struct work_struct *work)
+{
+	struct eth_dev	*dev = container_of(work, struct eth_dev, work);
+
+	if (test_and_clear_bit(WORK_RX_MEMORY, &dev->todo)) {
+		if (netif_running(dev->net))
+			rx_fill(dev, GFP_KERNEL);
+	}
+
+	if (dev->todo)
+		DBG(dev, "work done, flags = 0x%lx\n", dev->todo);
+}
+
+static void tx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct sk_buff	*skb = req->context;
+	struct eth_dev	*dev = ep->driver_data;
+
+	switch (req->status) {
+	default:
+		dev->net->stats.tx_errors++;
+		VDBG(dev, "tx err %d\n", req->status);
+		/* FALLTHROUGH */
+	case -ECONNRESET:		/* unlink */
+	case -ESHUTDOWN:		/* disconnect etc */
+		break;
+	case 0:
+		dev->net->stats.tx_bytes += skb->len;
+	}
+	dev->net->stats.tx_packets++;
+
+	spin_lock(&dev->req_lock);
+	list_add(&req->list, &dev->tx_reqs);
+	spin_unlock(&dev->req_lock);
+	dev_kfree_skb_any(skb);
+
+	atomic_dec(&dev->tx_qlen);
+	if (netif_carrier_ok(dev->net))
+		netif_wake_queue(dev->net);
+}
+
+static inline int is_promisc(u16 cdc_filter)
+{
+	return cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
+}
+
+static int eth_start_xmit(struct sk_buff *skb, struct net_device *net)
+{
+	struct eth_dev		*dev = netdev_priv(net);
+	int			length = skb->len;
+	int			retval;
+	struct usb_request	*req = NULL;
+	unsigned long		flags;
+	struct usb_ep		*in;
+	u16			cdc_filter;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	if (dev->port_usb) {
+		in = dev->port_usb->in_ep;
+		cdc_filter = dev->port_usb->cdc_filter;
+	} else {
+		in = NULL;
+		cdc_filter = 0;
+	}
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	if (!in) {
+		dev_kfree_skb_any(skb);
+		return 0;
+	}
+
+	/* apply outgoing CDC or RNDIS filters */
+	if (!is_promisc(cdc_filter)) {
+		u8		*dest = skb->data;
+
+		if (is_multicast_ether_addr(dest)) {
+			u16	type;
+
+			/* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
+			 * SET_ETHERNET_MULTICAST_FILTERS requests
+			 */
+			if (is_broadcast_ether_addr(dest))
+				type = USB_CDC_PACKET_TYPE_BROADCAST;
+			else
+				type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
+			if (!(cdc_filter & type)) {
+				dev_kfree_skb_any(skb);
+				return 0;
+			}
+		}
+		/* ignores USB_CDC_PACKET_TYPE_DIRECTED */
+	}
+
+	spin_lock_irqsave(&dev->req_lock, flags);
+	/*
+	 * this freelist can be empty if an interrupt triggered disconnect()
+	 * and reconfigured the gadget (shutting down this queue) after the
+	 * network stack decided to xmit but before we got the spinlock.
+	 */
+	if (list_empty(&dev->tx_reqs)) {
+		spin_unlock_irqrestore(&dev->req_lock, flags);
+		return 1;
+	}
+
+	req = container_of(dev->tx_reqs.next, struct usb_request, list);
+	list_del(&req->list);
+
+	/* temporarily stop TX queue when the freelist empties */
+	if (list_empty(&dev->tx_reqs))
+		netif_stop_queue(net);
+	spin_unlock_irqrestore(&dev->req_lock, flags);
+
+	/* no buffer copies needed, unless the network stack did it
+	 * or the hardware can't use skb buffers.
+	 * or there's not enough space for extra headers we need
+	 */
+	if (dev->wrap) {
+		struct sk_buff	*skb_new;
+
+		skb_new = dev->wrap(skb);
+		if (!skb_new)
+			goto drop;
+
+		dev_kfree_skb_any(skb);
+		skb = skb_new;
+		length = skb->len;
+	}
+	req->buf = skb->data;
+	req->context = skb;
+	req->complete = tx_complete;
+
+	/* use zlp framing on tx for strict CDC-Ether conformance,
+	 * though any robust network rx path ignores extra padding.
+	 * and some hardware doesn't like to write zlps.
+	 */
+	req->zero = 1;
+	if (!dev->zlp && (length % in->maxpacket) == 0)
+		length++;
+
+	req->length = length;
+
+	/* throttle highspeed IRQ rate back slightly */
+	if (gadget_is_dualspeed(dev->gadget))
+		req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
+			? ((atomic_read(&dev->tx_qlen) % qmult) != 0)
+			: 0;
+
+	retval = usb_ep_queue(in, req, GFP_ATOMIC);
+	switch (retval) {
+	default:
+		DBG(dev, "tx queue err %d\n", retval);
+		break;
+	case 0:
+		net->trans_start = jiffies;
+		atomic_inc(&dev->tx_qlen);
+	}
+
+	if (retval) {
+drop:
+		dev->net->stats.tx_dropped++;
+		dev_kfree_skb_any(skb);
+		spin_lock_irqsave(&dev->req_lock, flags);
+		if (list_empty(&dev->tx_reqs))
+			netif_start_queue(net);
+		list_add(&req->list, &dev->tx_reqs);
+		spin_unlock_irqrestore(&dev->req_lock, flags);
+	}
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void eth_start(struct eth_dev *dev, gfp_t gfp_flags)
+{
+	DBG(dev, "%s\n", __func__);
+
+	/* fill the rx queue */
+	rx_fill(dev, gfp_flags);
+
+	/* and open the tx floodgates */
+	atomic_set(&dev->tx_qlen, 0);
+	netif_wake_queue(dev->net);
+}
+
+static int eth_open(struct net_device *net)
+{
+	struct eth_dev	*dev = netdev_priv(net);
+	struct gether	*link;
+
+	DBG(dev, "%s\n", __func__);
+	if (netif_carrier_ok(dev->net))
+		eth_start(dev, GFP_KERNEL);
+
+	spin_lock_irq(&dev->lock);
+	link = dev->port_usb;
+	if (link && link->open)
+		link->open(link);
+	spin_unlock_irq(&dev->lock);
+
+	return 0;
+}
+
+static int eth_stop(struct net_device *net)
+{
+	struct eth_dev	*dev = netdev_priv(net);
+	unsigned long	flags;
+
+	VDBG(dev, "%s\n", __func__);
+	netif_stop_queue(net);
+
+	DBG(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
+		dev->net->stats.rx_packets, dev->net->stats.tx_packets,
+		dev->net->stats.rx_errors, dev->net->stats.tx_errors
+		);
+
+	/* ensure there are no more active requests */
+	spin_lock_irqsave(&dev->lock, flags);
+	if (dev->port_usb) {
+		struct gether	*link = dev->port_usb;
+
+		if (link->close)
+			link->close(link);
+
+		/* NOTE:  we have no abort-queue primitive we could use
+		 * to cancel all pending I/O.  Instead, we disable then
+		 * reenable the endpoints ... this idiom may leave toggle
+		 * wrong, but that's a self-correcting error.
+		 *
+		 * REVISIT:  we *COULD* just let the transfers complete at
+		 * their own pace; the network stack can handle old packets.
+		 * For the moment we leave this here, since it works.
+		 */
+		usb_ep_disable(link->in_ep);
+		usb_ep_disable(link->out_ep);
+		if (netif_carrier_ok(net)) {
+			DBG(dev, "host still using in/out endpoints\n");
+			usb_ep_enable(link->in_ep, link->in);
+			usb_ep_enable(link->out_ep, link->out);
+		}
+	}
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
+static char *dev_addr;
+module_param(dev_addr, charp, S_IRUGO);
+MODULE_PARM_DESC(dev_addr, "Device Ethernet Address");
+
+/* this address is invisible to ifconfig */
+static char *host_addr;
+module_param(host_addr, charp, S_IRUGO);
+MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
+
+
+static u8 __init nibble(unsigned char c)
+{
+	if (isdigit(c))
+		return c - '0';
+	c = toupper(c);
+	if (isxdigit(c))
+		return 10 + c - 'A';
+	return 0;
+}
+
+static int __init get_ether_addr(const char *str, u8 *dev_addr)
+{
+	if (str) {
+		unsigned	i;
+
+		for (i = 0; i < 6; i++) {
+			unsigned char num;
+
+			if ((*str == '.') || (*str == ':'))
+				str++;
+			num = nibble(*str++) << 4;
+			num |= (nibble(*str++));
+			dev_addr [i] = num;
+		}
+		if (is_valid_ether_addr(dev_addr))
+			return 0;
+	}
+	random_ether_addr(dev_addr);
+	return 1;
+}
+
+static struct eth_dev *the_dev;
+
+
+/**
+ * gether_setup - initialize one ethernet-over-usb link
+ * @g: gadget to associated with these links
+ * @ethaddr: NULL, or a buffer in which the ethernet address of the
+ *	host side of the link is recorded
+ * Context: may sleep
+ *
+ * This sets up the single network link that may be exported by a
+ * gadget driver using this framework.  The link layer addresses are
+ * set up using module parameters.
+ *
+ * Returns negative errno, or zero on success
+ */
+int __init gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
+{
+	struct eth_dev		*dev;
+	struct net_device	*net;
+	int			status;
+
+	if (the_dev)
+		return -EBUSY;
+
+	net = alloc_etherdev(sizeof *dev);
+	if (!net)
+		return -ENOMEM;
+
+	dev = netdev_priv(net);
+	spin_lock_init(&dev->lock);
+	spin_lock_init(&dev->req_lock);
+	INIT_WORK(&dev->work, eth_work);
+	INIT_LIST_HEAD(&dev->tx_reqs);
+	INIT_LIST_HEAD(&dev->rx_reqs);
+
+	/* network device setup */
+	dev->net = net;
+	strcpy(net->name, "usb%d");
+
+	if (get_ether_addr(dev_addr, net->dev_addr))
+		dev_warn(&g->dev,
+			"using random %s ethernet address\n", "self");
+	if (get_ether_addr(host_addr, dev->host_mac))
+		dev_warn(&g->dev,
+			"using random %s ethernet address\n", "host");
+
+	if (ethaddr)
+		memcpy(ethaddr, dev->host_mac, ETH_ALEN);
+
+	net->change_mtu = eth_change_mtu;
+	net->hard_start_xmit = eth_start_xmit;
+	net->open = eth_open;
+	net->stop = eth_stop;
+	/* watchdog_timeo, tx_timeout ... */
+	/* set_multicast_list */
+	SET_ETHTOOL_OPS(net, &ops);
+
+	/* two kinds of host-initiated state changes:
+	 *  - iff DATA transfer is active, carrier is "on"
+	 *  - tx queueing enabled if open *and* carrier is "on"
+	 */
+	netif_stop_queue(net);
+	netif_carrier_off(net);
+
+	dev->gadget = g;
+	SET_NETDEV_DEV(net, &g->dev);
+
+	status = register_netdev(net);
+	if (status < 0) {
+		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
+		free_netdev(net);
+	} else {
+		DECLARE_MAC_BUF(tmp);
+
+		INFO(dev, "MAC %s\n", print_mac(tmp, net->dev_addr));
+		INFO(dev, "HOST MAC %s\n", print_mac(tmp, dev->host_mac));
+
+		the_dev = dev;
+	}
+
+	return status;
+}
+
+/**
+ * gether_cleanup - remove Ethernet-over-USB device
+ * Context: may sleep
+ *
+ * This is called to free all resources allocated by @gether_setup().
+ */
+void gether_cleanup(void)
+{
+	if (!the_dev)
+		return;
+
+	unregister_netdev(the_dev->net);
+	free_netdev(the_dev->net);
+
+	/* assuming we used keventd, it must quiesce too */
+	flush_scheduled_work();
+
+	the_dev = NULL;
+}
+
+
+/**
+ * gether_connect - notify network layer that USB link is active
+ * @link: the USB link, set up with endpoints, descriptors matching
+ *	current device speed, and any framing wrapper(s) set up.
+ * Context: irqs blocked
+ *
+ * This is called to activate endpoints and let the network layer know
+ * the connection is active ("carrier detect").  It may cause the I/O
+ * queues to open and start letting network packets flow, but will in
+ * any case activate the endpoints so that they respond properly to the
+ * USB host.
+ *
+ * Verify net_device pointer returned using IS_ERR().  If it doesn't
+ * indicate some error code (negative errno), ep->driver_data values
+ * have been overwritten.
+ */
+struct net_device *gether_connect(struct gether *link)
+{
+	struct eth_dev		*dev = the_dev;
+	int			result = 0;
+
+	if (!dev)
+		return ERR_PTR(-EINVAL);
+
+	link->in_ep->driver_data = dev;
+	result = usb_ep_enable(link->in_ep, link->in);
+	if (result != 0) {
+		DBG(dev, "enable %s --> %d\n",
+			link->in_ep->name, result);
+		goto fail0;
+	}
+
+	link->out_ep->driver_data = dev;
+	result = usb_ep_enable(link->out_ep, link->out);
+	if (result != 0) {
+		DBG(dev, "enable %s --> %d\n",
+			link->out_ep->name, result);
+		goto fail1;
+	}
+
+	if (result == 0)
+		result = alloc_requests(dev, link, qlen(dev->gadget));
+
+	if (result == 0) {
+		dev->zlp = link->is_zlp_ok;
+		DBG(dev, "qlen %d\n", qlen(dev->gadget));
+
+		dev->header_len = link->header_len;
+		dev->unwrap = link->unwrap;
+		dev->wrap = link->wrap;
+
+		spin_lock(&dev->lock);
+		dev->port_usb = link;
+		link->ioport = dev;
+		spin_unlock(&dev->lock);
+
+		netif_carrier_on(dev->net);
+		if (netif_running(dev->net))
+			eth_start(dev, GFP_ATOMIC);
+
+	/* on error, disable any endpoints  */
+	} else {
+		(void) usb_ep_disable(link->out_ep);
+fail1:
+		(void) usb_ep_disable(link->in_ep);
+	}
+fail0:
+	/* caller is responsible for cleanup on error */
+	if (result < 0)
+		return ERR_PTR(result);
+	return dev->net;
+}
+
+/**
+ * gether_disconnect - notify network layer that USB link is inactive
+ * @link: the USB link, on which gether_connect() was called
+ * Context: irqs blocked
+ *
+ * This is called to deactivate endpoints and let the network layer know
+ * the connection went inactive ("no carrier").
+ *
+ * On return, the state is as if gether_connect() had never been called.
+ * The endpoints are inactive, and accordingly without active USB I/O.
+ * Pointers to endpoint descriptors and endpoint private data are nulled.
+ */
+void gether_disconnect(struct gether *link)
+{
+	struct eth_dev		*dev = link->ioport;
+	struct usb_request	*req;
+
+	WARN_ON(!dev);
+	if (!dev)
+		return;
+
+	DBG(dev, "%s\n", __func__);
+
+	netif_stop_queue(dev->net);
+	netif_carrier_off(dev->net);
+
+	/* disable endpoints, forcing (synchronous) completion
+	 * of all pending i/o.  then free the request objects
+	 * and forget about the endpoints.
+	 */
+	usb_ep_disable(link->in_ep);
+	spin_lock(&dev->req_lock);
+	while (!list_empty(&dev->tx_reqs)) {
+		req = container_of(dev->tx_reqs.next,
+					struct usb_request, list);
+		list_del(&req->list);
+
+		spin_unlock(&dev->req_lock);
+		usb_ep_free_request(link->in_ep, req);
+		spin_lock(&dev->req_lock);
+	}
+	spin_unlock(&dev->req_lock);
+	link->in_ep->driver_data = NULL;
+	link->in = NULL;
+
+	usb_ep_disable(link->out_ep);
+	spin_lock(&dev->req_lock);
+	while (!list_empty(&dev->rx_reqs)) {
+		req = container_of(dev->rx_reqs.next,
+					struct usb_request, list);
+		list_del(&req->list);
+
+		spin_unlock(&dev->req_lock);
+		usb_ep_free_request(link->out_ep, req);
+		spin_lock(&dev->req_lock);
+	}
+	spin_unlock(&dev->req_lock);
+	link->out_ep->driver_data = NULL;
+	link->out = NULL;
+
+	/* finish forgetting about this USB link episode */
+	dev->header_len = 0;
+	dev->unwrap = NULL;
+	dev->wrap = NULL;
+
+	spin_lock(&dev->lock);
+	dev->port_usb = NULL;
+	link->ioport = NULL;
+	spin_unlock(&dev->lock);
+}
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
new file mode 100644
index 0000000..0d1f7ae
--- /dev/null
+++ b/drivers/usb/gadget/u_ether.h
@@ -0,0 +1,127 @@
+/*
+ * u_ether.h -- interface to USB gadget "ethernet link" utilities
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __U_ETHER_H
+#define __U_ETHER_H
+
+#include <linux/err.h>
+#include <linux/if_ether.h>
+#include <linux/usb/composite.h>
+#include <linux/usb/cdc.h>
+
+#include "gadget_chips.h"
+
+
+/*
+ * This represents the USB side of an "ethernet" link, managed by a USB
+ * function which provides control and (maybe) framing.  Two functions
+ * in different configurations could share the same ethernet link/netdev,
+ * using different host interaction models.
+ *
+ * There is a current limitation that only one instance of this link may
+ * be present in any given configuration.  When that's a problem, network
+ * layer facilities can be used to package multiple logical links on this
+ * single "physical" one.
+ */
+struct gether {
+	struct usb_function		func;
+
+	/* updated by gether_{connect,disconnect} */
+	struct eth_dev			*ioport;
+
+	/* endpoints handle full and/or high speeds */
+	struct usb_ep			*in_ep;
+	struct usb_ep			*out_ep;
+
+	/* descriptors match device speed at gether_connect() time */
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+
+	bool				is_zlp_ok;
+
+	u16				cdc_filter;
+
+	/* hooks for added framing, as needed for RNDIS and EEM.
+	 * we currently don't support multiple frames per SKB.
+	 */
+	u32				header_len;
+	struct sk_buff			*(*wrap)(struct sk_buff *skb);
+	int				(*unwrap)(struct sk_buff *skb);
+
+	/* called on network open/close */
+	void				(*open)(struct gether *);
+	void				(*close)(struct gether *);
+};
+
+#define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
+			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+			|USB_CDC_PACKET_TYPE_PROMISCUOUS \
+			|USB_CDC_PACKET_TYPE_DIRECTED)
+
+
+/* netdev setup/teardown as directed by the gadget driver */
+int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]);
+void gether_cleanup(void);
+
+/* connect/disconnect is handled by individual functions */
+struct net_device *gether_connect(struct gether *);
+void gether_disconnect(struct gether *);
+
+/* Some controllers can't support CDC Ethernet (ECM) ... */
+static inline bool can_support_ecm(struct usb_gadget *gadget)
+{
+	if (!gadget_supports_altsettings(gadget))
+		return false;
+
+	/* SA1100 can do ECM, *without* status endpoint ... but we'll
+	 * only use it in non-ECM mode for backwards compatibility
+	 * (and since we currently require a status endpoint)
+	 */
+	if (gadget_is_sa1100(gadget))
+		return false;
+
+	/* Everything else is *presumably* fine ... but this is a bit
+	 * chancy, so be **CERTAIN** there are no hardware issues with
+	 * your controller.  Add it above if it can't handle CDC.
+	 */
+	return true;
+}
+
+/* each configuration may bind one instance of an ethernet link */
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+
+#ifdef CONFIG_USB_ETH_RNDIS
+
+int rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+
+#else
+
+static inline int
+rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+	return 0;
+}
+
+#endif
+
+#endif /* __U_ETHER_H */
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
new file mode 100644
index 0000000..53d5928
--- /dev/null
+++ b/drivers/usb/gadget/u_serial.c
@@ -0,0 +1,1330 @@
+/*
+ * u_serial.c - utilities for USB gadget "serial port"/TTY support
+ *
+ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This code also borrows from usbserial.c, which is
+ * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
+ * Copyright (C) 2000 Al Borchers (alborchers@steinerpoint.com)
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of that License or (at your option) any later version.
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+#include "u_serial.h"
+
+
+/*
+ * This component encapsulates the TTY layer glue needed to provide basic
+ * "serial port" functionality through the USB gadget stack.  Each such
+ * port is exposed through a /dev/ttyGS* node.
+ *
+ * After initialization (gserial_setup), these TTY port devices stay
+ * available until they are removed (gserial_cleanup).  Each one may be
+ * connected to a USB function (gserial_connect), or disconnected (with
+ * gserial_disconnect) when the USB host issues a config change event.
+ * Data can only flow when the port is connected to the host.
+ *
+ * A given TTY port can be made available in multiple configurations.
+ * For example, each one might expose a ttyGS0 node which provides a
+ * login application.  In one case that might use CDC ACM interface 0,
+ * while another configuration might use interface 3 for that.  The
+ * work to handle that (including descriptor management) is not part
+ * of this component.
+ *
+ * Configurations may expose more than one TTY port.  For example, if
+ * ttyGS0 provides login service, then ttyGS1 might provide dialer access
+ * for a telephone or fax link.  And ttyGS2 might be something that just
+ * needs a simple byte stream interface for some messaging protocol that
+ * is managed in userspace ... OBEX, PTP, and MTP have been mentioned.
+ */
+
+#define PREFIX	"ttyGS"
+
+/*
+ * gserial is the lifecycle interface, used by USB functions
+ * gs_port is the I/O nexus, used by the tty driver
+ * tty_struct links to the tty/filesystem framework
+ *
+ * gserial <---> gs_port ... links will be null when the USB link is
+ * inactive; managed by gserial_{connect,disconnect}().  each gserial
+ * instance can wrap its own USB control protocol.
+ *	gserial->ioport == usb_ep->driver_data ... gs_port
+ *	gs_port->port_usb ... gserial
+ *
+ * gs_port <---> tty_struct ... links will be null when the TTY file
+ * isn't opened; managed by gs_open()/gs_close()
+ *	gserial->port_tty ... tty_struct
+ *	tty_struct->driver_data ... gserial
+ */
+
+/* RX and TX queues can buffer QUEUE_SIZE packets before they hit the
+ * next layer of buffering.  For TX that's a circular buffer; for RX
+ * consider it a NOP.  A third layer is provided by the TTY code.
+ */
+#define QUEUE_SIZE		16
+#define WRITE_BUF_SIZE		8192		/* TX only */
+
+/* circular buffer */
+struct gs_buf {
+	unsigned		buf_size;
+	char			*buf_buf;
+	char			*buf_get;
+	char			*buf_put;
+};
+
+/*
+ * The port structure holds info for each port, one for each minor number
+ * (and thus for each /dev/ node).
+ */
+struct gs_port {
+	spinlock_t		port_lock;	/* guard port_* access */
+
+	struct gserial		*port_usb;
+	struct tty_struct	*port_tty;
+
+	unsigned		open_count;
+	bool			openclose;	/* open/close in progress */
+	u8			port_num;
+
+	wait_queue_head_t	close_wait;	/* wait for last close */
+
+	struct list_head	read_pool;
+	struct list_head	read_queue;
+	unsigned		n_read;
+	struct tasklet_struct	push;
+
+	struct list_head	write_pool;
+	struct gs_buf		port_write_buf;
+	wait_queue_head_t	drain_wait;	/* wait while writes drain */
+
+	/* REVISIT this state ... */
+	struct usb_cdc_line_coding port_line_coding;	/* 8-N-1 etc */
+};
+
+/* increase N_PORTS if you need more */
+#define N_PORTS		4
+static struct portmaster {
+	struct mutex	lock;			/* protect open/close */
+	struct gs_port	*port;
+} ports[N_PORTS];
+static unsigned	n_ports;
+
+#define GS_CLOSE_TIMEOUT		15		/* seconds */
+
+
+
+#ifdef VERBOSE_DEBUG
+#define pr_vdebug(fmt, arg...) \
+	pr_debug(fmt, ##arg)
+#else
+#define pr_vdebug(fmt, arg...) \
+	({ if (0) pr_debug(fmt, ##arg); })
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* Circular Buffer */
+
+/*
+ * gs_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+static int gs_buf_alloc(struct gs_buf *gb, unsigned size)
+{
+	gb->buf_buf = kmalloc(size, GFP_KERNEL);
+	if (gb->buf_buf == NULL)
+		return -ENOMEM;
+
+	gb->buf_size = size;
+	gb->buf_put = gb->buf_buf;
+	gb->buf_get = gb->buf_buf;
+
+	return 0;
+}
+
+/*
+ * gs_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+static void gs_buf_free(struct gs_buf *gb)
+{
+	kfree(gb->buf_buf);
+	gb->buf_buf = NULL;
+}
+
+/*
+ * gs_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+static void gs_buf_clear(struct gs_buf *gb)
+{
+	gb->buf_get = gb->buf_put;
+	/* equivalent to a get of all data available */
+}
+
+/*
+ * gs_buf_data_avail
+ *
+ * Return the number of bytes of data written into the circular
+ * buffer.
+ */
+static unsigned gs_buf_data_avail(struct gs_buf *gb)
+{
+	return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
+}
+
+/*
+ * gs_buf_space_avail
+ *
+ * Return the number of bytes of space available in the circular
+ * buffer.
+ */
+static unsigned gs_buf_space_avail(struct gs_buf *gb)
+{
+	return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
+}
+
+/*
+ * gs_buf_put
+ *
+ * Copy data data from a user buffer and put it into the circular buffer.
+ * Restrict to the amount of space available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned
+gs_buf_put(struct gs_buf *gb, const char *buf, unsigned count)
+{
+	unsigned len;
+
+	len  = gs_buf_space_avail(gb);
+	if (count > len)
+		count = len;
+
+	if (count == 0)
+		return 0;
+
+	len = gb->buf_buf + gb->buf_size - gb->buf_put;
+	if (count > len) {
+		memcpy(gb->buf_put, buf, len);
+		memcpy(gb->buf_buf, buf+len, count - len);
+		gb->buf_put = gb->buf_buf + count - len;
+	} else {
+		memcpy(gb->buf_put, buf, count);
+		if (count < len)
+			gb->buf_put += count;
+		else /* count == len */
+			gb->buf_put = gb->buf_buf;
+	}
+
+	return count;
+}
+
+/*
+ * gs_buf_get
+ *
+ * Get data from the circular buffer and copy to the given buffer.
+ * Restrict to the amount of data available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned
+gs_buf_get(struct gs_buf *gb, char *buf, unsigned count)
+{
+	unsigned len;
+
+	len = gs_buf_data_avail(gb);
+	if (count > len)
+		count = len;
+
+	if (count == 0)
+		return 0;
+
+	len = gb->buf_buf + gb->buf_size - gb->buf_get;
+	if (count > len) {
+		memcpy(buf, gb->buf_get, len);
+		memcpy(buf+len, gb->buf_buf, count - len);
+		gb->buf_get = gb->buf_buf + count - len;
+	} else {
+		memcpy(buf, gb->buf_get, count);
+		if (count < len)
+			gb->buf_get += count;
+		else /* count == len */
+			gb->buf_get = gb->buf_buf;
+	}
+
+	return count;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* I/O glue between TTY (upper) and USB function (lower) driver layers */
+
+/*
+ * gs_alloc_req
+ *
+ * Allocate a usb_request and its buffer.  Returns a pointer to the
+ * usb_request or NULL if there is an error.
+ */
+struct usb_request *
+gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
+{
+	struct usb_request *req;
+
+	req = usb_ep_alloc_request(ep, kmalloc_flags);
+
+	if (req != NULL) {
+		req->length = len;
+		req->buf = kmalloc(len, kmalloc_flags);
+		if (req->buf == NULL) {
+			usb_ep_free_request(ep, req);
+			return NULL;
+		}
+	}
+
+	return req;
+}
+
+/*
+ * gs_free_req
+ *
+ * Free a usb_request and its buffer.
+ */
+void gs_free_req(struct usb_ep *ep, struct usb_request *req)
+{
+	kfree(req->buf);
+	usb_ep_free_request(ep, req);
+}
+
+/*
+ * gs_send_packet
+ *
+ * If there is data to send, a packet is built in the given
+ * buffer and the size is returned.  If there is no data to
+ * send, 0 is returned.
+ *
+ * Called with port_lock held.
+ */
+static unsigned
+gs_send_packet(struct gs_port *port, char *packet, unsigned size)
+{
+	unsigned len;
+
+	len = gs_buf_data_avail(&port->port_write_buf);
+	if (len < size)
+		size = len;
+	if (size != 0)
+		size = gs_buf_get(&port->port_write_buf, packet, size);
+	return size;
+}
+
+/*
+ * gs_start_tx
+ *
+ * This function finds available write requests, calls
+ * gs_send_packet to fill these packets with data, and
+ * continues until either there are no more write requests
+ * available or no more data to send.  This function is
+ * run whenever data arrives or write requests are available.
+ *
+ * Context: caller owns port_lock; port_usb is non-null.
+ */
+static int gs_start_tx(struct gs_port *port)
+/*
+__releases(&port->port_lock)
+__acquires(&port->port_lock)
+*/
+{
+	struct list_head	*pool = &port->write_pool;
+	struct usb_ep		*in = port->port_usb->in;
+	int			status = 0;
+	bool			do_tty_wake = false;
+
+	while (!list_empty(pool)) {
+		struct usb_request	*req;
+		int			len;
+
+		req = list_entry(pool->next, struct usb_request, list);
+		len = gs_send_packet(port, req->buf, in->maxpacket);
+		if (len == 0) {
+			wake_up_interruptible(&port->drain_wait);
+			break;
+		}
+		do_tty_wake = true;
+
+		req->length = len;
+		list_del(&req->list);
+
+		pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
+				port->port_num, len, *((u8 *)req->buf),
+				*((u8 *)req->buf+1), *((u8 *)req->buf+2));
+
+		/* Drop lock while we call out of driver; completions
+		 * could be issued while we do so.  Disconnection may
+		 * happen too; maybe immediately before we queue this!
+		 *
+		 * NOTE that we may keep sending data for a while after
+		 * the TTY closed (dev->ioport->port_tty is NULL).
+		 */
+		spin_unlock(&port->port_lock);
+		status = usb_ep_queue(in, req, GFP_ATOMIC);
+		spin_lock(&port->port_lock);
+
+		if (status) {
+			pr_debug("%s: %s %s err %d\n",
+					__func__, "queue", in->name, status);
+			list_add(&req->list, pool);
+			break;
+		}
+
+		/* abort immediately after disconnect */
+		if (!port->port_usb)
+			break;
+	}
+
+	if (do_tty_wake && port->port_tty)
+		tty_wakeup(port->port_tty);
+	return status;
+}
+
+/*
+ * Context: caller owns port_lock, and port_usb is set
+ */
+static unsigned gs_start_rx(struct gs_port *port)
+/*
+__releases(&port->port_lock)
+__acquires(&port->port_lock)
+*/
+{
+	struct list_head	*pool = &port->read_pool;
+	struct usb_ep		*out = port->port_usb->out;
+	unsigned		started = 0;
+
+	while (!list_empty(pool)) {
+		struct usb_request	*req;
+		int			status;
+		struct tty_struct	*tty;
+
+		/* no more rx if closed */
+		tty = port->port_tty;
+		if (!tty)
+			break;
+
+		req = list_entry(pool->next, struct usb_request, list);
+		list_del(&req->list);
+		req->length = out->maxpacket;
+
+		/* drop lock while we call out; the controller driver
+		 * may need to call us back (e.g. for disconnect)
+		 */
+		spin_unlock(&port->port_lock);
+		status = usb_ep_queue(out, req, GFP_ATOMIC);
+		spin_lock(&port->port_lock);
+
+		if (status) {
+			pr_debug("%s: %s %s err %d\n",
+					__func__, "queue", out->name, status);
+			list_add(&req->list, pool);
+			break;
+		}
+		started++;
+
+		/* abort immediately after disconnect */
+		if (!port->port_usb)
+			break;
+	}
+	return started;
+}
+
+/*
+ * RX tasklet takes data out of the RX queue and hands it up to the TTY
+ * layer until it refuses to take any more data (or is throttled back).
+ * Then it issues reads for any further data.
+ *
+ * If the RX queue becomes full enough that no usb_request is queued,
+ * the OUT endpoint may begin NAKing as soon as its FIFO fills up.
+ * So QUEUE_SIZE packets plus however many the FIFO holds (usually two)
+ * can be buffered before the TTY layer's buffers (currently 64 KB).
+ */
+static void gs_rx_push(unsigned long _port)
+{
+	struct gs_port		*port = (void *)_port;
+	struct tty_struct	*tty;
+	struct list_head	*queue = &port->read_queue;
+	bool			disconnect = false;
+	bool			do_push = false;
+
+	/* hand any queued data to the tty */
+	spin_lock_irq(&port->port_lock);
+	tty = port->port_tty;
+	while (!list_empty(queue)) {
+		struct usb_request	*req;
+
+		req = list_first_entry(queue, struct usb_request, list);
+
+		/* discard data if tty was closed */
+		if (!tty)
+			goto recycle;
+
+		/* leave data queued if tty was rx throttled */
+		if (test_bit(TTY_THROTTLED, &tty->flags))
+			break;
+
+		switch (req->status) {
+		case -ESHUTDOWN:
+			disconnect = true;
+			pr_vdebug(PREFIX "%d: shutdown\n", port->port_num);
+			break;
+
+		default:
+			/* presumably a transient fault */
+			pr_warning(PREFIX "%d: unexpected RX status %d\n",
+					port->port_num, req->status);
+			/* FALLTHROUGH */
+		case 0:
+			/* normal completion */
+			break;
+		}
+
+		/* push data to (open) tty */
+		if (req->actual) {
+			char		*packet = req->buf;
+			unsigned	size = req->actual;
+			unsigned	n;
+			int		count;
+
+			/* we may have pushed part of this packet already... */
+			n = port->n_read;
+			if (n) {
+				packet += n;
+				size -= n;
+			}
+
+			count = tty_insert_flip_string(tty, packet, size);
+			if (count)
+				do_push = true;
+			if (count != size) {
+				/* stop pushing; TTY layer can't handle more */
+				port->n_read += count;
+				pr_vdebug(PREFIX "%d: rx block %d/%d\n",
+						port->port_num,
+						count, req->actual);
+				break;
+			}
+			port->n_read = 0;
+		}
+recycle:
+		list_move(&req->list, &port->read_pool);
+	}
+
+	/* Push from tty to ldisc; this is immediate with low_latency, and
+	 * may trigger callbacks to this driver ... so drop the spinlock.
+	 */
+	if (tty && do_push) {
+		spin_unlock_irq(&port->port_lock);
+		tty_flip_buffer_push(tty);
+		wake_up_interruptible(&tty->read_wait);
+		spin_lock_irq(&port->port_lock);
+
+		/* tty may have been closed */
+		tty = port->port_tty;
+	}
+
+
+	/* We want our data queue to become empty ASAP, keeping data
+	 * in the tty and ldisc (not here).  If we couldn't push any
+	 * this time around, there may be trouble unless there's an
+	 * implicit tty_unthrottle() call on its way...
+	 *
+	 * REVISIT we should probably add a timer to keep the tasklet
+	 * from starving ... but it's not clear that case ever happens.
+	 */
+	if (!list_empty(queue) && tty) {
+		if (!test_bit(TTY_THROTTLED, &tty->flags)) {
+			if (do_push)
+				tasklet_schedule(&port->push);
+			else
+				pr_warning(PREFIX "%d: RX not scheduled?\n",
+					port->port_num);
+		}
+	}
+
+	/* If we're still connected, refill the USB RX queue. */
+	if (!disconnect && port->port_usb)
+		gs_start_rx(port);
+
+	spin_unlock_irq(&port->port_lock);
+}
+
+static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct gs_port	*port = ep->driver_data;
+
+	/* Queue all received data until the tty layer is ready for it. */
+	spin_lock(&port->port_lock);
+	list_add_tail(&req->list, &port->read_queue);
+	tasklet_schedule(&port->push);
+	spin_unlock(&port->port_lock);
+}
+
+static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct gs_port	*port = ep->driver_data;
+
+	spin_lock(&port->port_lock);
+	list_add(&req->list, &port->write_pool);
+
+	switch (req->status) {
+	default:
+		/* presumably a transient fault */
+		pr_warning("%s: unexpected %s status %d\n",
+				__func__, ep->name, req->status);
+		/* FALL THROUGH */
+	case 0:
+		/* normal completion */
+		gs_start_tx(port);
+		break;
+
+	case -ESHUTDOWN:
+		/* disconnect */
+		pr_vdebug("%s: %s shutdown\n", __func__, ep->name);
+		break;
+	}
+
+	spin_unlock(&port->port_lock);
+}
+
+static void gs_free_requests(struct usb_ep *ep, struct list_head *head)
+{
+	struct usb_request	*req;
+
+	while (!list_empty(head)) {
+		req = list_entry(head->next, struct usb_request, list);
+		list_del(&req->list);
+		gs_free_req(ep, req);
+	}
+}
+
+static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head,
+		void (*fn)(struct usb_ep *, struct usb_request *))
+{
+	int			i;
+	struct usb_request	*req;
+
+	/* Pre-allocate up to QUEUE_SIZE transfers, but if we can't
+	 * do quite that many this time, don't fail ... we just won't
+	 * be as speedy as we might otherwise be.
+	 */
+	for (i = 0; i < QUEUE_SIZE; i++) {
+		req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC);
+		if (!req)
+			return list_empty(head) ? -ENOMEM : 0;
+		req->complete = fn;
+		list_add_tail(&req->list, head);
+	}
+	return 0;
+}
+
+/**
+ * gs_start_io - start USB I/O streams
+ * @dev: encapsulates endpoints to use
+ * Context: holding port_lock; port_tty and port_usb are non-null
+ *
+ * We only start I/O when something is connected to both sides of
+ * this port.  If nothing is listening on the host side, we may
+ * be pointlessly filling up our TX buffers and FIFO.
+ */
+static int gs_start_io(struct gs_port *port)
+{
+	struct list_head	*head = &port->read_pool;
+	struct usb_ep		*ep = port->port_usb->out;
+	int			status;
+	unsigned		started;
+
+	/* Allocate RX and TX I/O buffers.  We can't easily do this much
+	 * earlier (with GFP_KERNEL) because the requests are coupled to
+	 * endpoints, as are the packet sizes we'll be using.  Different
+	 * configurations may use different endpoints with a given port;
+	 * and high speed vs full speed changes packet sizes too.
+	 */
+	status = gs_alloc_requests(ep, head, gs_read_complete);
+	if (status)
+		return status;
+
+	status = gs_alloc_requests(port->port_usb->in, &port->write_pool,
+			gs_write_complete);
+	if (status) {
+		gs_free_requests(ep, head);
+		return status;
+	}
+
+	/* queue read requests */
+	port->n_read = 0;
+	started = gs_start_rx(port);
+
+	/* unblock any pending writes into our circular buffer */
+	if (started) {
+		tty_wakeup(port->port_tty);
+	} else {
+		gs_free_requests(ep, head);
+		gs_free_requests(port->port_usb->in, &port->write_pool);
+		status = -EIO;
+	}
+
+	return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* TTY Driver */
+
+/*
+ * gs_open sets up the link between a gs_port and its associated TTY.
+ * That link is broken *only* by TTY close(), and all driver methods
+ * know that.
+ */
+static int gs_open(struct tty_struct *tty, struct file *file)
+{
+	int		port_num = tty->index;
+	struct gs_port	*port;
+	int		status;
+
+	if (port_num < 0 || port_num >= n_ports)
+		return -ENXIO;
+
+	do {
+		mutex_lock(&ports[port_num].lock);
+		port = ports[port_num].port;
+		if (!port)
+			status = -ENODEV;
+		else {
+			spin_lock_irq(&port->port_lock);
+
+			/* already open?  Great. */
+			if (port->open_count) {
+				status = 0;
+				port->open_count++;
+
+			/* currently opening/closing? wait ... */
+			} else if (port->openclose) {
+				status = -EBUSY;
+
+			/* ... else we do the work */
+			} else {
+				status = -EAGAIN;
+				port->openclose = true;
+			}
+			spin_unlock_irq(&port->port_lock);
+		}
+		mutex_unlock(&ports[port_num].lock);
+
+		switch (status) {
+		default:
+			/* fully handled */
+			return status;
+		case -EAGAIN:
+			/* must do the work */
+			break;
+		case -EBUSY:
+			/* wait for EAGAIN task to finish */
+			msleep(1);
+			/* REVISIT could have a waitchannel here, if
+			 * concurrent open performance is important
+			 */
+			break;
+		}
+	} while (status != -EAGAIN);
+
+	/* Do the "real open" */
+	spin_lock_irq(&port->port_lock);
+
+	/* allocate circular buffer on first open */
+	if (port->port_write_buf.buf_buf == NULL) {
+
+		spin_unlock_irq(&port->port_lock);
+		status = gs_buf_alloc(&port->port_write_buf, WRITE_BUF_SIZE);
+		spin_lock_irq(&port->port_lock);
+
+		if (status) {
+			pr_debug("gs_open: ttyGS%d (%p,%p) no buffer\n",
+				port->port_num, tty, file);
+			port->openclose = false;
+			goto exit_unlock_port;
+		}
+	}
+
+	/* REVISIT if REMOVED (ports[].port NULL), abort the open
+	 * to let rmmod work faster (but this way isn't wrong).
+	 */
+
+	/* REVISIT maybe wait for "carrier detect" */
+
+	tty->driver_data = port;
+	port->port_tty = tty;
+
+	port->open_count = 1;
+	port->openclose = false;
+
+	/* low_latency means ldiscs work in tasklet context, without
+	 * needing a workqueue schedule ... easier to keep up.
+	 */
+	tty->low_latency = 1;
+
+	/* if connected, start the I/O stream */
+	if (port->port_usb) {
+		struct gserial	*gser = port->port_usb;
+
+		pr_debug("gs_open: start ttyGS%d\n", port->port_num);
+		gs_start_io(port);
+
+		if (gser->connect)
+			gser->connect(gser);
+	}
+
+	pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file);
+
+	status = 0;
+
+exit_unlock_port:
+	spin_unlock_irq(&port->port_lock);
+	return status;
+}
+
+static int gs_writes_finished(struct gs_port *p)
+{
+	int cond;
+
+	/* return true on disconnect or empty buffer */
+	spin_lock_irq(&p->port_lock);
+	cond = (p->port_usb == NULL) || !gs_buf_data_avail(&p->port_write_buf);
+	spin_unlock_irq(&p->port_lock);
+
+	return cond;
+}
+
+static void gs_close(struct tty_struct *tty, struct file *file)
+{
+	struct gs_port *port = tty->driver_data;
+	struct gserial	*gser;
+
+	spin_lock_irq(&port->port_lock);
+
+	if (port->open_count != 1) {
+		if (port->open_count == 0)
+			WARN_ON(1);
+		else
+			--port->open_count;
+		goto exit;
+	}
+
+	pr_debug("gs_close: ttyGS%d (%p,%p) ...\n", port->port_num, tty, file);
+
+	/* mark port as closing but in use; we can drop port lock
+	 * and sleep if necessary
+	 */
+	port->openclose = true;
+	port->open_count = 0;
+
+	gser = port->port_usb;
+	if (gser && gser->disconnect)
+		gser->disconnect(gser);
+
+	/* wait for circular write buffer to drain, disconnect, or at
+	 * most GS_CLOSE_TIMEOUT seconds; then discard the rest
+	 */
+	if (gs_buf_data_avail(&port->port_write_buf) > 0 && gser) {
+		spin_unlock_irq(&port->port_lock);
+		wait_event_interruptible_timeout(port->drain_wait,
+					gs_writes_finished(port),
+					GS_CLOSE_TIMEOUT * HZ);
+		spin_lock_irq(&port->port_lock);
+		gser = port->port_usb;
+	}
+
+	/* Iff we're disconnected, there can be no I/O in flight so it's
+	 * ok to free the circular buffer; else just scrub it.  And don't
+	 * let the push tasklet fire again until we're re-opened.
+	 */
+	if (gser == NULL)
+		gs_buf_free(&port->port_write_buf);
+	else
+		gs_buf_clear(&port->port_write_buf);
+
+	tty->driver_data = NULL;
+	port->port_tty = NULL;
+
+	port->openclose = false;
+
+	pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
+			port->port_num, tty, file);
+
+	wake_up_interruptible(&port->close_wait);
+exit:
+	spin_unlock_irq(&port->port_lock);
+}
+
+static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+	struct gs_port	*port = tty->driver_data;
+	unsigned long	flags;
+	int		status;
+
+	pr_vdebug("gs_write: ttyGS%d (%p) writing %d bytes\n",
+			port->port_num, tty, count);
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (count)
+		count = gs_buf_put(&port->port_write_buf, buf, count);
+	/* treat count == 0 as flush_chars() */
+	if (port->port_usb)
+		status = gs_start_tx(port);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	return count;
+}
+
+static int gs_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct gs_port	*port = tty->driver_data;
+	unsigned long	flags;
+	int		status;
+
+	pr_vdebug("gs_put_char: (%d,%p) char=0x%x, called from %p\n",
+		port->port_num, tty, ch, __builtin_return_address(0));
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	status = gs_buf_put(&port->port_write_buf, &ch, 1);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	return status;
+}
+
+static void gs_flush_chars(struct tty_struct *tty)
+{
+	struct gs_port	*port = tty->driver_data;
+	unsigned long	flags;
+
+	pr_vdebug("gs_flush_chars: (%d,%p)\n", port->port_num, tty);
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (port->port_usb)
+		gs_start_tx(port);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+}
+
+static int gs_write_room(struct tty_struct *tty)
+{
+	struct gs_port	*port = tty->driver_data;
+	unsigned long	flags;
+	int		room = 0;
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (port->port_usb)
+		room = gs_buf_space_avail(&port->port_write_buf);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	pr_vdebug("gs_write_room: (%d,%p) room=%d\n",
+		port->port_num, tty, room);
+
+	return room;
+}
+
+static int gs_chars_in_buffer(struct tty_struct *tty)
+{
+	struct gs_port	*port = tty->driver_data;
+	unsigned long	flags;
+	int		chars = 0;
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	chars = gs_buf_data_avail(&port->port_write_buf);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	pr_vdebug("gs_chars_in_buffer: (%d,%p) chars=%d\n",
+		port->port_num, tty, chars);
+
+	return chars;
+}
+
+/* undo side effects of setting TTY_THROTTLED */
+static void gs_unthrottle(struct tty_struct *tty)
+{
+	struct gs_port		*port = tty->driver_data;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (port->port_usb) {
+		/* Kickstart read queue processing.  We don't do xon/xoff,
+		 * rts/cts, or other handshaking with the host, but if the
+		 * read queue backs up enough we'll be NAKing OUT packets.
+		 */
+		tasklet_schedule(&port->push);
+		pr_vdebug(PREFIX "%d: unthrottle\n", port->port_num);
+	}
+	spin_unlock_irqrestore(&port->port_lock, flags);
+}
+
+static int gs_break_ctl(struct tty_struct *tty, int duration)
+{
+	struct gs_port	*port = tty->driver_data;
+	int		status = 0;
+	struct gserial	*gser;
+
+	pr_vdebug("gs_break_ctl: ttyGS%d, send break (%d) \n",
+			port->port_num, duration);
+
+	spin_lock_irq(&port->port_lock);
+	gser = port->port_usb;
+	if (gser && gser->send_break)
+		status = gser->send_break(gser, duration);
+	spin_unlock_irq(&port->port_lock);
+
+	return status;
+}
+
+static const struct tty_operations gs_tty_ops = {
+	.open =			gs_open,
+	.close =		gs_close,
+	.write =		gs_write,
+	.put_char =		gs_put_char,
+	.flush_chars =		gs_flush_chars,
+	.write_room =		gs_write_room,
+	.chars_in_buffer =	gs_chars_in_buffer,
+	.unthrottle =		gs_unthrottle,
+	.break_ctl =		gs_break_ctl,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static struct tty_driver *gs_tty_driver;
+
+static int __init
+gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
+{
+	struct gs_port	*port;
+
+	port = kzalloc(sizeof(struct gs_port), GFP_KERNEL);
+	if (port == NULL)
+		return -ENOMEM;
+
+	spin_lock_init(&port->port_lock);
+	init_waitqueue_head(&port->close_wait);
+	init_waitqueue_head(&port->drain_wait);
+
+	tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
+
+	INIT_LIST_HEAD(&port->read_pool);
+	INIT_LIST_HEAD(&port->read_queue);
+	INIT_LIST_HEAD(&port->write_pool);
+
+	port->port_num = port_num;
+	port->port_line_coding = *coding;
+
+	ports[port_num].port = port;
+
+	return 0;
+}
+
+/**
+ * gserial_setup - initialize TTY driver for one or more ports
+ * @g: gadget to associate with these ports
+ * @count: how many ports to support
+ * Context: may sleep
+ *
+ * The TTY stack needs to know in advance how many devices it should
+ * plan to manage.  Use this call to set up the ports you will be
+ * exporting through USB.  Later, connect them to functions based
+ * on what configuration is activated by the USB host; and disconnect
+ * them as appropriate.
+ *
+ * An example would be a two-configuration device in which both
+ * configurations expose port 0, but through different functions.
+ * One configuration could even expose port 1 while the other
+ * one doesn't.
+ *
+ * Returns negative errno or zero.
+ */
+int __init gserial_setup(struct usb_gadget *g, unsigned count)
+{
+	unsigned			i;
+	struct usb_cdc_line_coding	coding;
+	int				status;
+
+	if (count == 0 || count > N_PORTS)
+		return -EINVAL;
+
+	gs_tty_driver = alloc_tty_driver(count);
+	if (!gs_tty_driver)
+		return -ENOMEM;
+
+	gs_tty_driver->owner = THIS_MODULE;
+	gs_tty_driver->driver_name = "g_serial";
+	gs_tty_driver->name = PREFIX;
+	/* uses dynamically assigned dev_t values */
+
+	gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
+	gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	gs_tty_driver->init_termios = tty_std_termios;
+
+	/* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
+	 * MS-Windows.  Otherwise, most of these flags shouldn't affect
+	 * anything unless we were to actually hook up to a serial line.
+	 */
+	gs_tty_driver->init_termios.c_cflag =
+			B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	gs_tty_driver->init_termios.c_ispeed = 9600;
+	gs_tty_driver->init_termios.c_ospeed = 9600;
+
+	coding.dwDTERate = __constant_cpu_to_le32(9600);
+	coding.bCharFormat = 8;
+	coding.bParityType = USB_CDC_NO_PARITY;
+	coding.bDataBits = USB_CDC_1_STOP_BITS;
+
+	tty_set_operations(gs_tty_driver, &gs_tty_ops);
+
+	/* make devices be openable */
+	for (i = 0; i < count; i++) {
+		mutex_init(&ports[i].lock);
+		status = gs_port_alloc(i, &coding);
+		if (status) {
+			count = i;
+			goto fail;
+		}
+	}
+	n_ports = count;
+
+	/* export the driver ... */
+	status = tty_register_driver(gs_tty_driver);
+	if (status) {
+		put_tty_driver(gs_tty_driver);
+		pr_err("%s: cannot register, err %d\n",
+				__func__, status);
+		goto fail;
+	}
+
+	/* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
+	for (i = 0; i < count; i++) {
+		struct device	*tty_dev;
+
+		tty_dev = tty_register_device(gs_tty_driver, i, &g->dev);
+		if (IS_ERR(tty_dev))
+			pr_warning("%s: no classdev for port %d, err %ld\n",
+				__func__, i, PTR_ERR(tty_dev));
+	}
+
+	pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
+			count, (count == 1) ? "" : "s");
+
+	return status;
+fail:
+	while (count--)
+		kfree(ports[count].port);
+	put_tty_driver(gs_tty_driver);
+	gs_tty_driver = NULL;
+	return status;
+}
+
+static int gs_closed(struct gs_port *port)
+{
+	int cond;
+
+	spin_lock_irq(&port->port_lock);
+	cond = (port->open_count == 0) && !port->openclose;
+	spin_unlock_irq(&port->port_lock);
+	return cond;
+}
+
+/**
+ * gserial_cleanup - remove TTY-over-USB driver and devices
+ * Context: may sleep
+ *
+ * This is called to free all resources allocated by @gserial_setup().
+ * Accordingly, it may need to wait until some open /dev/ files have
+ * closed.
+ *
+ * The caller must have issued @gserial_disconnect() for any ports
+ * that had previously been connected, so that there is never any
+ * I/O pending when it's called.
+ */
+void gserial_cleanup(void)
+{
+	unsigned	i;
+	struct gs_port	*port;
+
+	if (!gs_tty_driver)
+		return;
+
+	/* start sysfs and /dev/ttyGS* node removal */
+	for (i = 0; i < n_ports; i++)
+		tty_unregister_device(gs_tty_driver, i);
+
+	for (i = 0; i < n_ports; i++) {
+		/* prevent new opens */
+		mutex_lock(&ports[i].lock);
+		port = ports[i].port;
+		ports[i].port = NULL;
+		mutex_unlock(&ports[i].lock);
+
+		tasklet_kill(&port->push);
+
+		/* wait for old opens to finish */
+		wait_event(port->close_wait, gs_closed(port));
+
+		WARN_ON(port->port_usb != NULL);
+
+		kfree(port);
+	}
+	n_ports = 0;
+
+	tty_unregister_driver(gs_tty_driver);
+	gs_tty_driver = NULL;
+
+	pr_debug("%s: cleaned up ttyGS* support\n", __func__);
+}
+
+/**
+ * gserial_connect - notify TTY I/O glue that USB link is active
+ * @gser: the function, set up with endpoints and descriptors
+ * @port_num: which port is active
+ * Context: any (usually from irq)
+ *
+ * This is called activate endpoints and let the TTY layer know that
+ * the connection is active ... not unlike "carrier detect".  It won't
+ * necessarily start I/O queues; unless the TTY is held open by any
+ * task, there would be no point.  However, the endpoints will be
+ * activated so the USB host can perform I/O, subject to basic USB
+ * hardware flow control.
+ *
+ * Caller needs to have set up the endpoints and USB function in @dev
+ * before calling this, as well as the appropriate (speed-specific)
+ * endpoint descriptors, and also have set up the TTY driver by calling
+ * @gserial_setup().
+ *
+ * Returns negative errno or zero.
+ * On success, ep->driver_data will be overwritten.
+ */
+int gserial_connect(struct gserial *gser, u8 port_num)
+{
+	struct gs_port	*port;
+	unsigned long	flags;
+	int		status;
+
+	if (!gs_tty_driver || port_num >= n_ports)
+		return -ENXIO;
+
+	/* we "know" gserial_cleanup() hasn't been called */
+	port = ports[port_num].port;
+
+	/* activate the endpoints */
+	status = usb_ep_enable(gser->in, gser->in_desc);
+	if (status < 0)
+		return status;
+	gser->in->driver_data = port;
+
+	status = usb_ep_enable(gser->out, gser->out_desc);
+	if (status < 0)
+		goto fail_out;
+	gser->out->driver_data = port;
+
+	/* then tell the tty glue that I/O can work */
+	spin_lock_irqsave(&port->port_lock, flags);
+	gser->ioport = port;
+	port->port_usb = gser;
+
+	/* REVISIT unclear how best to handle this state...
+	 * we don't really couple it with the Linux TTY.
+	 */
+	gser->port_line_coding = port->port_line_coding;
+
+	/* REVISIT if waiting on "carrier detect", signal. */
+
+	/* if it's already open, start I/O ... and notify the serial
+	 * protocol about open/close status (connect/disconnect).
+	 */
+	if (port->open_count) {
+		pr_debug("gserial_connect: start ttyGS%d\n", port->port_num);
+		gs_start_io(port);
+		if (gser->connect)
+			gser->connect(gser);
+	} else {
+		if (gser->disconnect)
+			gser->disconnect(gser);
+	}
+
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	return status;
+
+fail_out:
+	usb_ep_disable(gser->in);
+	gser->in->driver_data = NULL;
+	return status;
+}
+
+/**
+ * gserial_disconnect - notify TTY I/O glue that USB link is inactive
+ * @gser: the function, on which gserial_connect() was called
+ * Context: any (usually from irq)
+ *
+ * This is called to deactivate endpoints and let the TTY layer know
+ * that the connection went inactive ... not unlike "hangup".
+ *
+ * On return, the state is as if gserial_connect() had never been called;
+ * there is no active USB I/O on these endpoints.
+ */
+void gserial_disconnect(struct gserial *gser)
+{
+	struct gs_port	*port = gser->ioport;
+	unsigned long	flags;
+
+	if (!port)
+		return;
+
+	/* tell the TTY glue not to do I/O here any more */
+	spin_lock_irqsave(&port->port_lock, flags);
+
+	/* REVISIT as above: how best to track this? */
+	port->port_line_coding = gser->port_line_coding;
+
+	port->port_usb = NULL;
+	gser->ioport = NULL;
+	if (port->open_count > 0 || port->openclose) {
+		wake_up_interruptible(&port->drain_wait);
+		if (port->port_tty)
+			tty_hangup(port->port_tty);
+	}
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	/* disable endpoints, aborting down any active I/O */
+	usb_ep_disable(gser->out);
+	gser->out->driver_data = NULL;
+
+	usb_ep_disable(gser->in);
+	gser->in->driver_data = NULL;
+
+	/* finally, free any unused/unusable I/O buffers */
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (port->open_count == 0 && !port->openclose)
+		gs_buf_free(&port->port_write_buf);
+	gs_free_requests(gser->out, &port->read_pool);
+	gs_free_requests(gser->out, &port->read_queue);
+	gs_free_requests(gser->in, &port->write_pool);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+}
diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h
new file mode 100644
index 0000000..af3910d
--- /dev/null
+++ b/drivers/usb/gadget/u_serial.h
@@ -0,0 +1,66 @@
+/*
+ * u_serial.h - interface to USB gadget "serial port"/TTY utilities
+ *
+ * Copyright (C) 2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of that License or (at your option) any later version.
+ */
+
+#ifndef __U_SERIAL_H
+#define __U_SERIAL_H
+
+#include <linux/usb/composite.h>
+#include <linux/usb/cdc.h>
+
+/*
+ * One non-multiplexed "serial" I/O port ... there can be several of these
+ * on any given USB peripheral device, if it provides enough endpoints.
+ *
+ * The "u_serial" utility component exists to do one thing:  manage TTY
+ * style I/O using the USB peripheral endpoints listed here, including
+ * hookups to sysfs and /dev for each logical "tty" device.
+ *
+ * REVISIT at least ACM could support tiocmget() if needed.
+ *
+ * REVISIT someday, allow multiplexing several TTYs over these endpoints.
+ */
+struct gserial {
+	struct usb_function		func;
+
+	/* port is managed by gserial_{connect,disconnect} */
+	struct gs_port			*ioport;
+
+	struct usb_ep			*in;
+	struct usb_ep			*out;
+	struct usb_endpoint_descriptor	*in_desc;
+	struct usb_endpoint_descriptor	*out_desc;
+
+	/* REVISIT avoid this CDC-ACM support harder ... */
+	struct usb_cdc_line_coding port_line_coding;	/* 9600-8-N-1 etc */
+
+	/* notification callbacks */
+	void (*connect)(struct gserial *p);
+	void (*disconnect)(struct gserial *p);
+	int (*send_break)(struct gserial *p, int duration);
+};
+
+/* utilities to allocate/free request and buffer */
+struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags);
+void gs_free_req(struct usb_ep *, struct usb_request *req);
+
+/* port setup/teardown is handled by gadget driver */
+int gserial_setup(struct usb_gadget *g, unsigned n_ports);
+void gserial_cleanup(void);
+
+/* connect/disconnect is handled by individual functions */
+int gserial_connect(struct gserial *, u8 port_num);
+void gserial_disconnect(struct gserial *);
+
+/* functions are bound to configurations by a config or gadget driver */
+int acm_bind_config(struct usb_configuration *c, u8 port_num);
+int gser_bind_config(struct usb_configuration *c, u8 port_num);
+
+#endif /* __U_SERIAL_H */
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index fce4924..aa0bd4f 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -1,8 +1,8 @@
 /*
  * zero.c -- Gadget Zero, for USB development
  *
- * Copyright (C) 2003-2007 David Brownell
- * All rights reserved.
+ * Copyright (C) 2003-2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -30,12 +30,7 @@
  *
  * It supports two similar configurations.  One sinks whatever the usb host
  * writes, and in return sources zeroes.  The other loops whatever the host
- * writes back, so the host can read it.  Module options include:
- *
- *   buflen=N		default N=4096, buffer size used
- *   qlen=N		default N=32, how many buffers in the loopback queue
- *   loopdefault	default false, list loopback config first
- *   autoresume=N	default N=0, seconds before triggering remote wakeup
+ * writes back, so the host can read it.
  *
  * Many drivers will only have one configuration, letting them be much
  * simpler if they also don't support high speed operation (like this
@@ -47,94 +42,35 @@
  * work with low capability USB controllers without four bulk endpoints.
  */
 
+/*
+ * driver assumes self-powered hardware, and
+ * has no way for users to trigger remote wakeup.
+ */
+
 /* #define VERBOSE_DEBUG */
 
 #include <linux/kernel.h>
 #include <linux/utsname.h>
 #include <linux/device.h>
 
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
+#include "g_zero.h"
 #include "gadget_chips.h"
 
 
 /*-------------------------------------------------------------------------*/
 
-#define DRIVER_VERSION		"Earth Day 2008"
+#define DRIVER_VERSION		"Cinco de Mayo 2008"
 
-static const char shortname[] = "zero";
 static const char longname[] = "Gadget Zero";
 
-static const char source_sink[] = "source and sink data";
-static const char loopback[] = "loop input to output";
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * driver assumes self-powered hardware, and
- * has no way for users to trigger remote wakeup.
- *
- * this version autoconfigures as much as possible,
- * which is reasonable for most "bulk-only" drivers.
- */
-static const char *EP_IN_NAME;		/* source */
-static const char *EP_OUT_NAME;		/* sink */
-
-/*-------------------------------------------------------------------------*/
-
-/* big enough to hold our biggest descriptor */
-#define USB_BUFSIZ	256
-
-struct zero_dev {
-	spinlock_t		lock;
-	struct usb_gadget	*gadget;
-	struct usb_request	*req;		/* for control responses */
-
-	/* when configured, we have one of two configs:
-	 * - source data (in to host) and sink it (out from host)
-	 * - or loop it back (out from host back in to host)
-	 */
-	u8			config;
-	struct usb_ep		*in_ep, *out_ep;
-
-	/* autoresume timer */
-	struct timer_list	resume;
-};
-
-#define DBG(d, fmt, args...) \
-	dev_dbg(&(d)->gadget->dev , fmt , ## args)
-#define VDBG(d, fmt, args...) \
-	dev_vdbg(&(d)->gadget->dev , fmt , ## args)
-#define ERROR(d, fmt, args...) \
-	dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARN(d, fmt, args...) \
-	dev_warn(&(d)->gadget->dev , fmt , ## args)
-#define INFO(d, fmt, args...) \
-	dev_info(&(d)->gadget->dev , fmt , ## args)
-
-/*-------------------------------------------------------------------------*/
-
-static unsigned buflen = 4096;
-static unsigned qlen = 32;
-static unsigned pattern = 0;
-
-module_param(buflen, uint, S_IRUGO);
-module_param(qlen, uint, S_IRUGO);
-module_param(pattern, uint, S_IRUGO|S_IWUSR);
-
-/*
- * if it's nonzero, autoresume says how many seconds to wait
- * before trying to wake up the host after suspend.
- */
-static unsigned autoresume = 0;
-module_param(autoresume, uint, 0);
+unsigned buflen = 4096;
+module_param(buflen, uint, 0);
 
 /*
  * Normally the "loopback" configuration is second (index 1) so
  * it's not the default.  Here's where to change that order, to
- * work better with hosts where config changes are problematic.
- * Or controllers (like superh) that only support one config.
+ * work better with hosts where config changes are problematic or
+ * controllers (like original superh) that only support one config.
  */
 static int loopdefault = 0;
 module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
@@ -156,24 +92,6 @@ module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * DESCRIPTORS ... most are static, but strings and (full)
- * configuration descriptors are built on demand.
- */
-
-#define STRING_MANUFACTURER		25
-#define STRING_PRODUCT			42
-#define STRING_SERIAL			101
-#define STRING_SOURCE_SINK		250
-#define STRING_LOOPBACK			251
-
-/*
- * This device advertises two configurations; these numbers work
- * on a pxa250 as well as more flexible hardware.
- */
-#define	CONFIG_SOURCE_SINK	3
-#define	CONFIG_LOOPBACK		2
-
 static struct usb_device_descriptor device_desc = {
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
@@ -183,248 +101,64 @@ static struct usb_device_descriptor device_desc = {
 
 	.idVendor =		__constant_cpu_to_le16(DRIVER_VENDOR_NUM),
 	.idProduct =		__constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
-	.iManufacturer =	STRING_MANUFACTURER,
-	.iProduct =		STRING_PRODUCT,
-	.iSerialNumber =	STRING_SERIAL,
 	.bNumConfigurations =	2,
 };
 
-static struct usb_config_descriptor source_sink_config = {
-	.bLength =		sizeof source_sink_config,
-	.bDescriptorType =	USB_DT_CONFIG,
-
-	/* compute wTotalLength on the fly */
-	.bNumInterfaces =	1,
-	.bConfigurationValue =	CONFIG_SOURCE_SINK,
-	.iConfiguration =	STRING_SOURCE_SINK,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =		1,	/* self-powered */
-};
-
-static struct usb_config_descriptor loopback_config = {
-	.bLength =		sizeof loopback_config,
-	.bDescriptorType =	USB_DT_CONFIG,
-
-	/* compute wTotalLength on the fly */
-	.bNumInterfaces =	1,
-	.bConfigurationValue =	CONFIG_LOOPBACK,
-	.iConfiguration =	STRING_LOOPBACK,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =		1,	/* self-powered */
-};
-
+#ifdef CONFIG_USB_OTG
 static struct usb_otg_descriptor otg_descriptor = {
 	.bLength =		sizeof otg_descriptor,
 	.bDescriptorType =	USB_DT_OTG,
 
-	.bmAttributes =		USB_OTG_SRP,
-};
-
-/* one interface in each configuration */
-
-static const struct usb_interface_descriptor source_sink_intf = {
-	.bLength =		sizeof source_sink_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
-	.iInterface =		STRING_SOURCE_SINK,
-};
-
-static const struct usb_interface_descriptor loopback_intf = {
-	.bLength =		sizeof loopback_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
-	.iInterface =		STRING_LOOPBACK,
-};
-
-/* two full speed bulk endpoints; their use is config-dependent */
-
-static struct usb_endpoint_descriptor fs_source_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_endpoint_descriptor fs_sink_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_OUT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static const struct usb_descriptor_header *fs_source_sink_function[] = {
-	(struct usb_descriptor_header *) &otg_descriptor,
-	(struct usb_descriptor_header *) &source_sink_intf,
-	(struct usb_descriptor_header *) &fs_sink_desc,
-	(struct usb_descriptor_header *) &fs_source_desc,
-	NULL,
-};
-
-static const struct usb_descriptor_header *fs_loopback_function[] = {
-	(struct usb_descriptor_header *) &otg_descriptor,
-	(struct usb_descriptor_header *) &loopback_intf,
-	(struct usb_descriptor_header *) &fs_sink_desc,
-	(struct usb_descriptor_header *) &fs_source_desc,
-	NULL,
-};
-
-/*
- * usb 2.0 devices need to expose both high speed and full speed
- * descriptors, unless they only run at full speed.
- *
- * that means alternate endpoint descriptors (bigger packets)
- * and a "device qualifier" ... plus more construction options
- * for the config descriptor.
- */
-
-static struct usb_endpoint_descriptor hs_source_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor hs_sink_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
-};
-
-static struct usb_qualifier_descriptor dev_qualifier = {
-	.bLength =		sizeof dev_qualifier,
-	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
-
-	.bcdUSB =		__constant_cpu_to_le16(0x0200),
-	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
-
-	.bNumConfigurations =	2,
+	/* REVISIT SRP-only hardware is possible, although
+	 * it would not be called "OTG" ...
+	 */
+	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
 };
 
-static const struct usb_descriptor_header *hs_source_sink_function[] = {
+const struct usb_descriptor_header *otg_desc[] = {
 	(struct usb_descriptor_header *) &otg_descriptor,
-	(struct usb_descriptor_header *) &source_sink_intf,
-	(struct usb_descriptor_header *) &hs_source_desc,
-	(struct usb_descriptor_header *) &hs_sink_desc,
 	NULL,
 };
+#endif
 
-static const struct usb_descriptor_header *hs_loopback_function[] = {
-	(struct usb_descriptor_header *) &otg_descriptor,
-	(struct usb_descriptor_header *) &loopback_intf,
-	(struct usb_descriptor_header *) &hs_source_desc,
-	(struct usb_descriptor_header *) &hs_sink_desc,
-	NULL,
-};
+/* string IDs are assigned dynamically */
 
-/* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *
-ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
-		struct usb_endpoint_descriptor *fs)
-{
-	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
-		return hs;
-	return fs;
-}
+#define STRING_MANUFACTURER_IDX		0
+#define STRING_PRODUCT_IDX		1
+#define STRING_SERIAL_IDX		2
 
 static char manufacturer[50];
 
 /* default serial number takes at least two packets */
 static char serial[] = "0123456789.0123456789.0123456789";
 
-
-/* static strings, in UTF-8 */
-static struct usb_string strings[] = {
-	{ STRING_MANUFACTURER, manufacturer, },
-	{ STRING_PRODUCT, longname, },
-	{ STRING_SERIAL, serial, },
-	{ STRING_LOOPBACK, loopback, },
-	{ STRING_SOURCE_SINK, source_sink, },
+static struct usb_string strings_dev[] = {
+	[STRING_MANUFACTURER_IDX].s = manufacturer,
+	[STRING_PRODUCT_IDX].s = longname,
+	[STRING_SERIAL_IDX].s = serial,
 	{  }			/* end of list */
 };
 
-static struct usb_gadget_strings stringtab = {
+static struct usb_gadget_strings stringtab_dev = {
 	.language	= 0x0409,	/* en-us */
-	.strings	= strings,
+	.strings	= strings_dev,
 };
 
-/*
- * config descriptors are also handcrafted.  these must agree with code
- * that sets configurations, and with code managing interfaces and their
- * altsettings.  other complexity may come from:
- *
- *  - high speed support, including "other speed config" rules
- *  - multiple configurations
- *  - interfaces with alternate settings
- *  - embedded class or vendor-specific descriptors
- *
- * this handles high speed, and has a second config that could as easily
- * have been an alternate interface setting (on most hardware).
- *
- * NOTE:  to demonstrate (and test) more USB capabilities, this driver
- * should include an altsetting to test interrupt transfers, including
- * high bandwidth modes at high speed.  (Maybe work like Intel's test
- * device?)
- */
-static int config_buf(struct usb_gadget *gadget,
-		u8 *buf, u8 type, unsigned index)
-{
-	int				is_source_sink;
-	int				len;
-	const struct usb_descriptor_header **function;
-	int				hs = 0;
-
-	/* two configurations will always be index 0 and index 1 */
-	if (index > 1)
-		return -EINVAL;
-	is_source_sink = loopdefault ? (index == 1) : (index == 0);
-
-	if (gadget_is_dualspeed(gadget)) {
-		hs = (gadget->speed == USB_SPEED_HIGH);
-		if (type == USB_DT_OTHER_SPEED_CONFIG)
-			hs = !hs;
-	}
-	if (hs)
-		function = is_source_sink
-			? hs_source_sink_function
-			: hs_loopback_function;
-	else
-		function = is_source_sink
-			? fs_source_sink_function
-			: fs_loopback_function;
-
-	/* for now, don't advertise srp-only devices */
-	if (!gadget_is_otg(gadget))
-		function++;
-
-	len = usb_gadget_config_buf(is_source_sink
-					? &source_sink_config
-					: &loopback_config,
-			buf, USB_BUFSIZ, function);
-	if (len < 0)
-		return len;
-	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
-	return len;
-}
+static struct usb_gadget_strings *dev_strings[] = {
+	&stringtab_dev,
+	NULL,
+};
 
 /*-------------------------------------------------------------------------*/
 
-static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
+struct usb_request *alloc_ep_req(struct usb_ep *ep)
 {
 	struct usb_request	*req;
 
 	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
 	if (req) {
-		req->length = length;
-		req->buf = kmalloc(length, GFP_ATOMIC);
+		req->length = buflen;
+		req->buf = kmalloc(buflen, GFP_ATOMIC);
 		if (!req->buf) {
 			usb_ep_free_request(ep, req);
 			req = NULL;
@@ -433,681 +167,73 @@ static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
 	return req;
 }
 
-static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
+void free_ep_req(struct usb_ep *ep, struct usb_request *req)
 {
 	kfree(req->buf);
 	usb_ep_free_request(ep, req);
 }
 
-/*-------------------------------------------------------------------------*/
-
-/*
- * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripherals,
- * this just sinks bulk packets OUT to the peripheral and sources them IN
- * to the host, optionally with specific data patterns.
- *
- * In terms of control messaging, this supports all the standard requests
- * plus two that support control-OUT tests.
- *
- * Note that because this doesn't queue more than one request at a time,
- * some other function must be used to test queueing logic.  The network
- * link (g_ether) is probably the best option for that.
- */
-
-/* optionally require specific source/sink data patterns  */
-
-static int
-check_read_data(
-	struct zero_dev		*dev,
-	struct usb_ep		*ep,
-	struct usb_request	*req
-)
+static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
 {
-	unsigned	i;
-	u8		*buf = req->buf;
-
-	for (i = 0; i < req->actual; i++, buf++) {
-		switch (pattern) {
-		/* all-zeroes has no synchronization issues */
-		case 0:
-			if (*buf == 0)
-				continue;
-			break;
-		/* mod63 stays in sync with short-terminated transfers,
-		 * or otherwise when host and gadget agree on how large
-		 * each usb transfer request should be.  resync is done
-		 * with set_interface or set_config.
-		 */
-		case 1:
-			if (*buf == (u8)(i % 63))
-				continue;
-			break;
-		}
-		ERROR(dev, "bad OUT byte, buf[%d] = %d\n", i, *buf);
-		usb_ep_set_halt(ep);
-		return -EINVAL;
+	int			value;
+
+	if (ep->driver_data) {
+		value = usb_ep_disable(ep);
+		if (value < 0)
+			DBG(cdev, "disable %s --> %d\n",
+					ep->name, value);
+		ep->driver_data = NULL;
 	}
-	return 0;
 }
 
-static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
+void disable_endpoints(struct usb_composite_dev *cdev,
+		struct usb_ep *in, struct usb_ep *out)
 {
-	unsigned	i;
-	u8		*buf = req->buf;
-
-	switch (pattern) {
-	case 0:
-		memset(req->buf, 0, req->length);
-		break;
-	case 1:
-		for  (i = 0; i < req->length; i++)
-			*buf++ = (u8) (i % 63);
-		break;
-	}
-}
-
-/* if there is only one request in the queue, there'll always be an
- * irq delay between end of one request and start of the next.
- * that prevents using hardware dma queues.
- */
-static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct zero_dev	*dev = ep->driver_data;
-	int		status = req->status;
-
-	switch (status) {
-
-	case 0:				/* normal completion? */
-		if (ep == dev->out_ep) {
-			check_read_data(dev, ep, req);
-			memset(req->buf, 0x55, req->length);
-		} else
-			reinit_write_data(ep, req);
-		break;
-
-	/* this endpoint is normally active while we're configured */
-	case -ECONNABORTED:		/* hardware forced ep reset */
-	case -ECONNRESET:		/* request dequeued */
-	case -ESHUTDOWN:		/* disconnect from host */
-		VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status,
-				req->actual, req->length);
-		if (ep == dev->out_ep)
-			check_read_data(dev, ep, req);
-		free_ep_req(ep, req);
-		return;
-
-	case -EOVERFLOW:		/* buffer overrun on read means that
-					 * we didn't provide a big enough
-					 * buffer.
-					 */
-	default:
-#if 1
-		DBG(dev, "%s complete --> %d, %d/%d\n", ep->name,
-				status, req->actual, req->length);
-#endif
-	case -EREMOTEIO:		/* short read */
-		break;
-	}
-
-	status = usb_ep_queue(ep, req, GFP_ATOMIC);
-	if (status) {
-		ERROR(dev, "kill %s:  resubmit %d bytes --> %d\n",
-				ep->name, req->length, status);
-		usb_ep_set_halt(ep);
-		/* FIXME recover later ... somehow */
-	}
-}
-
-static struct usb_request *source_sink_start_ep(struct usb_ep *ep)
-{
-	struct usb_request	*req;
-	int			status;
-
-	req = alloc_ep_req(ep, buflen);
-	if (!req)
-		return NULL;
-
-	memset(req->buf, 0, req->length);
-	req->complete = source_sink_complete;
-
-	if (strcmp(ep->name, EP_IN_NAME) == 0)
-		reinit_write_data(ep, req);
-	else
-		memset(req->buf, 0x55, req->length);
-
-	status = usb_ep_queue(ep, req, GFP_ATOMIC);
-	if (status) {
-		struct zero_dev	*dev = ep->driver_data;
-
-		ERROR(dev, "start %s --> %d\n", ep->name, status);
-		free_ep_req(ep, req);
-		req = NULL;
-	}
-
-	return req;
-}
-
-static int set_source_sink_config(struct zero_dev *dev)
-{
-	int			result = 0;
-	struct usb_ep		*ep;
-	struct usb_gadget	*gadget = dev->gadget;
-
-	gadget_for_each_ep(ep, gadget) {
-		const struct usb_endpoint_descriptor	*d;
-
-		/* one endpoint writes (sources) zeroes in (to the host) */
-		if (strcmp(ep->name, EP_IN_NAME) == 0) {
-			d = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
-			result = usb_ep_enable(ep, d);
-			if (result == 0) {
-				ep->driver_data = dev;
-				if (source_sink_start_ep(ep) != NULL) {
-					dev->in_ep = ep;
-					continue;
-				}
-				usb_ep_disable(ep);
-				result = -EIO;
-			}
-
-		/* one endpoint reads (sinks) anything out (from the host) */
-		} else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
-			d = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
-			result = usb_ep_enable(ep, d);
-			if (result == 0) {
-				ep->driver_data = dev;
-				if (source_sink_start_ep(ep) != NULL) {
-					dev->out_ep = ep;
-					continue;
-				}
-				usb_ep_disable(ep);
-				result = -EIO;
-			}
-
-		/* ignore any other endpoints */
-		} else
-			continue;
-
-		/* stop on error */
-		ERROR(dev, "can't start %s, result %d\n", ep->name, result);
-		break;
-	}
-	if (result == 0)
-		DBG(dev, "buflen %d\n", buflen);
-
-	/* caller is responsible for cleanup on error */
-	return result;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct zero_dev	*dev = ep->driver_data;
-	int		status = req->status;
-
-	switch (status) {
-
-	case 0:				/* normal completion? */
-		if (ep == dev->out_ep) {
-			/* loop this OUT packet back IN to the host */
-			req->zero = (req->actual < req->length);
-			req->length = req->actual;
-			status = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC);
-			if (status == 0)
-				return;
-
-			/* "should never get here" */
-			ERROR(dev, "can't loop %s to %s: %d\n",
-				ep->name, dev->in_ep->name,
-				status);
-		}
-
-		/* queue the buffer for some later OUT packet */
-		req->length = buflen;
-		status = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
-		if (status == 0)
-			return;
-
-		/* "should never get here" */
-		/* FALLTHROUGH */
-
-	default:
-		ERROR(dev, "%s loop complete --> %d, %d/%d\n", ep->name,
-				status, req->actual, req->length);
-		/* FALLTHROUGH */
-
-	/* NOTE:  since this driver doesn't maintain an explicit record
-	 * of requests it submitted (just maintains qlen count), we
-	 * rely on the hardware driver to clean up on disconnect or
-	 * endpoint disable.
-	 */
-	case -ECONNABORTED:		/* hardware forced ep reset */
-	case -ECONNRESET:		/* request dequeued */
-	case -ESHUTDOWN:		/* disconnect from host */
-		free_ep_req(ep, req);
-		return;
-	}
-}
-
-static int set_loopback_config(struct zero_dev *dev)
-{
-	int			result = 0;
-	struct usb_ep		*ep;
-	struct usb_gadget	*gadget = dev->gadget;
-
-	gadget_for_each_ep(ep, gadget) {
-		const struct usb_endpoint_descriptor	*d;
-
-		/* one endpoint writes data back IN to the host */
-		if (strcmp(ep->name, EP_IN_NAME) == 0) {
-			d = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
-			result = usb_ep_enable(ep, d);
-			if (result == 0) {
-				ep->driver_data = dev;
-				dev->in_ep = ep;
-				continue;
-			}
-
-		/* one endpoint just reads OUT packets */
-		} else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
-			d = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
-			result = usb_ep_enable(ep, d);
-			if (result == 0) {
-				ep->driver_data = dev;
-				dev->out_ep = ep;
-				continue;
-			}
-
-		/* ignore any other endpoints */
-		} else
-			continue;
-
-		/* stop on error */
-		ERROR(dev, "can't enable %s, result %d\n", ep->name, result);
-		break;
-	}
-
-	/* allocate a bunch of read buffers and queue them all at once.
-	 * we buffer at most 'qlen' transfers; fewer if any need more
-	 * than 'buflen' bytes each.
-	 */
-	if (result == 0) {
-		struct usb_request	*req;
-		unsigned		i;
-
-		ep = dev->out_ep;
-		for (i = 0; i < qlen && result == 0; i++) {
-			req = alloc_ep_req(ep, buflen);
-			if (req) {
-				req->complete = loopback_complete;
-				result = usb_ep_queue(ep, req, GFP_ATOMIC);
-				if (result)
-					DBG(dev, "%s queue req --> %d\n",
-							ep->name, result);
-			} else
-				result = -ENOMEM;
-		}
-	}
-	if (result == 0)
-		DBG(dev, "qlen %d, buflen %d\n", qlen, buflen);
-
-	/* caller is responsible for cleanup on error */
-	return result;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void zero_reset_config(struct zero_dev *dev)
-{
-	if (dev->config == 0)
-		return;
-
-	DBG(dev, "reset config\n");
-
-	/* just disable endpoints, forcing completion of pending i/o.
-	 * all our completion handlers free their requests in this case.
-	 */
-	if (dev->in_ep) {
-		usb_ep_disable(dev->in_ep);
-		dev->in_ep = NULL;
-	}
-	if (dev->out_ep) {
-		usb_ep_disable(dev->out_ep);
-		dev->out_ep = NULL;
-	}
-	dev->config = 0;
-	del_timer(&dev->resume);
-}
-
-/* change our operational config.  this code must agree with the code
- * that returns config descriptors, and altsetting code.
- *
- * it's also responsible for power management interactions. some
- * configurations might not work with our current power sources.
- *
- * note that some device controller hardware will constrain what this
- * code can do, perhaps by disallowing more than one configuration or
- * by limiting configuration choices (like the pxa2xx).
- */
-static int zero_set_config(struct zero_dev *dev, unsigned number)
-{
-	int			result = 0;
-	struct usb_gadget	*gadget = dev->gadget;
-
-	if (number == dev->config)
-		return 0;
-
-	if (gadget_is_sa1100(gadget) && dev->config) {
-		/* tx fifo is full, but we can't clear it...*/
-		ERROR(dev, "can't change configurations\n");
-		return -ESPIPE;
-	}
-	zero_reset_config(dev);
-
-	switch (number) {
-	case CONFIG_SOURCE_SINK:
-		result = set_source_sink_config(dev);
-		break;
-	case CONFIG_LOOPBACK:
-		result = set_loopback_config(dev);
-		break;
-	default:
-		result = -EINVAL;
-		/* FALL THROUGH */
-	case 0:
-		return result;
-	}
-
-	if (!result && (!dev->in_ep || !dev->out_ep))
-		result = -ENODEV;
-	if (result)
-		zero_reset_config(dev);
-	else {
-		char *speed;
-
-		switch (gadget->speed) {
-		case USB_SPEED_LOW:	speed = "low"; break;
-		case USB_SPEED_FULL:	speed = "full"; break;
-		case USB_SPEED_HIGH:	speed = "high"; break;
-		default:		speed = "?"; break;
-		}
-
-		dev->config = number;
-		INFO(dev, "%s speed config #%d: %s\n", speed, number,
-				(number == CONFIG_SOURCE_SINK)
-					? source_sink : loopback);
-	}
-	return result;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void zero_setup_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	if (req->status || req->actual != req->length)
-		DBG((struct zero_dev *) ep->driver_data,
-				"setup complete --> %d, %d/%d\n",
-				req->status, req->actual, req->length);
-}
-
-/*
- * The setup() callback implements all the ep0 functionality that's
- * not handled lower down, in hardware or the hardware driver (like
- * device and endpoint feature flags, and their status).  It's all
- * housekeeping for the gadget function we're implementing.  Most of
- * the work is in config-specific setup.
- */
-static int
-zero_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
-{
-	struct zero_dev		*dev = get_gadget_data(gadget);
-	struct usb_request	*req = dev->req;
-	int			value = -EOPNOTSUPP;
-	u16			w_index = le16_to_cpu(ctrl->wIndex);
-	u16			w_value = le16_to_cpu(ctrl->wValue);
-	u16			w_length = le16_to_cpu(ctrl->wLength);
-
-	/* usually this stores reply data in the pre-allocated ep0 buffer,
-	 * but config change events will reconfigure hardware.
-	 */
-	req->zero = 0;
-	switch (ctrl->bRequest) {
-
-	case USB_REQ_GET_DESCRIPTOR:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			goto unknown;
-		switch (w_value >> 8) {
-
-		case USB_DT_DEVICE:
-			value = min(w_length, (u16) sizeof device_desc);
-			memcpy(req->buf, &device_desc, value);
-			break;
-		case USB_DT_DEVICE_QUALIFIER:
-			if (!gadget_is_dualspeed(gadget))
-				break;
-			value = min(w_length, (u16) sizeof dev_qualifier);
-			memcpy(req->buf, &dev_qualifier, value);
-			break;
-
-		case USB_DT_OTHER_SPEED_CONFIG:
-			if (!gadget_is_dualspeed(gadget))
-				break;
-			// FALLTHROUGH
-		case USB_DT_CONFIG:
-			value = config_buf(gadget, req->buf,
-					w_value >> 8,
-					w_value & 0xff);
-			if (value >= 0)
-				value = min(w_length, (u16) value);
-			break;
-
-		case USB_DT_STRING:
-			/* wIndex == language code.
-			 * this driver only handles one language, you can
-			 * add string tables for other languages, using
-			 * any UTF-8 characters
-			 */
-			value = usb_gadget_get_string(&stringtab,
-					w_value & 0xff, req->buf);
-			if (value >= 0)
-				value = min(w_length, (u16) value);
-			break;
-		}
-		break;
-
-	/* currently two configs, two speeds */
-	case USB_REQ_SET_CONFIGURATION:
-		if (ctrl->bRequestType != 0)
-			goto unknown;
-		if (gadget->a_hnp_support)
-			DBG(dev, "HNP available\n");
-		else if (gadget->a_alt_hnp_support)
-			DBG(dev, "HNP needs a different root port\n");
-		else
-			VDBG(dev, "HNP inactive\n");
-		spin_lock(&dev->lock);
-		value = zero_set_config(dev, w_value);
-		spin_unlock(&dev->lock);
-		break;
-	case USB_REQ_GET_CONFIGURATION:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			goto unknown;
-		*(u8 *)req->buf = dev->config;
-		value = min(w_length, (u16) 1);
-		break;
-
-	/* until we add altsetting support, or other interfaces,
-	 * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)
-	 * and already killed pending endpoint I/O.
-	 */
-	case USB_REQ_SET_INTERFACE:
-		if (ctrl->bRequestType != USB_RECIP_INTERFACE)
-			goto unknown;
-		spin_lock(&dev->lock);
-		if (dev->config && w_index == 0 && w_value == 0) {
-			u8		config = dev->config;
-
-			/* resets interface configuration, forgets about
-			 * previous transaction state (queued bufs, etc)
-			 * and re-inits endpoint state (toggle etc)
-			 * no response queued, just zero status == success.
-			 * if we had more than one interface we couldn't
-			 * use this "reset the config" shortcut.
-			 */
-			zero_reset_config(dev);
-			zero_set_config(dev, config);
-			value = 0;
-		}
-		spin_unlock(&dev->lock);
-		break;
-	case USB_REQ_GET_INTERFACE:
-		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
-			goto unknown;
-		if (!dev->config)
-			break;
-		if (w_index != 0) {
-			value = -EDOM;
-			break;
-		}
-		*(u8 *)req->buf = 0;
-		value = min(w_length, (u16) 1);
-		break;
-
-	/*
-	 * These are the same vendor-specific requests supported by
-	 * Intel's USB 2.0 compliance test devices.  We exceed that
-	 * device spec by allowing multiple-packet requests.
-	 */
-	case 0x5b:	/* control WRITE test -- fill the buffer */
-		if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
-			goto unknown;
-		if (w_value || w_index)
-			break;
-		/* just read that many bytes into the buffer */
-		if (w_length > USB_BUFSIZ)
-			break;
-		value = w_length;
-		break;
-	case 0x5c:	/* control READ test -- return the buffer */
-		if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
-			goto unknown;
-		if (w_value || w_index)
-			break;
-		/* expect those bytes are still in the buffer; send back */
-		if (w_length > USB_BUFSIZ
-				|| w_length != req->length)
-			break;
-		value = w_length;
-		break;
-
-	default:
-unknown:
-		VDBG(dev,
-			"unknown control req%02x.%02x v%04x i%04x l%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			w_value, w_index, w_length);
-	}
-
-	/* respond with data transfer before status phase? */
-	if (value >= 0) {
-		req->length = value;
-		req->zero = value < w_length;
-		value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
-		if (value < 0) {
-			DBG(dev, "ep_queue --> %d\n", value);
-			req->status = 0;
-			zero_setup_complete(gadget->ep0, req);
-		}
-	}
-
-	/* device either stalls (value < 0) or reports success */
-	return value;
-}
-
-static void zero_disconnect(struct usb_gadget *gadget)
-{
-	struct zero_dev		*dev = get_gadget_data(gadget);
-	unsigned long		flags;
-
-	spin_lock_irqsave(&dev->lock, flags);
-	zero_reset_config(dev);
-
-	/* a more significant application might have some non-usb
-	 * activities to quiesce here, saving resources like power
-	 * or pushing the notification up a network stack.
-	 */
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	/* next we may get setup() calls to enumerate new connections;
-	 * or an unbind() during shutdown (including removing module).
-	 */
-}
-
-static void zero_autoresume(unsigned long _dev)
-{
-	struct zero_dev	*dev = (struct zero_dev *) _dev;
-	int		status;
-
-	/* normally the host would be woken up for something
-	 * more significant than just a timer firing...
-	 */
-	if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
-		status = usb_gadget_wakeup(dev->gadget);
-		DBG(dev, "wakeup --> %d\n", status);
-	}
+	disable_ep(cdev, in);
+	disable_ep(cdev, out);
 }
 
 /*-------------------------------------------------------------------------*/
 
-static void zero_unbind(struct usb_gadget *gadget)
+static int __init zero_bind(struct usb_composite_dev *cdev)
 {
-	struct zero_dev		*dev = get_gadget_data(gadget);
-
-	DBG(dev, "unbind\n");
-
-	/* we've already been disconnected ... no i/o is active */
-	if (dev->req) {
-		dev->req->length = USB_BUFSIZ;
-		free_ep_req(gadget->ep0, dev->req);
-	}
-	del_timer_sync(&dev->resume);
-	kfree(dev);
-	set_gadget_data(gadget, NULL);
-}
-
-static int __init zero_bind(struct usb_gadget *gadget)
-{
-	struct zero_dev		*dev;
-	struct usb_ep		*ep;
 	int			gcnum;
+	struct usb_gadget	*gadget = cdev->gadget;
+	int			id;
 
-	/* FIXME this can't yet work right with SH ... it has only
-	 * one configuration, numbered one.
+	/* Allocate string descriptor numbers ... note that string
+	 * contents can be overridden by the composite_dev glue.
 	 */
-	if (gadget_is_sh(gadget))
-		return -ENODEV;
-
-	/* Bulk-only drivers like this one SHOULD be able to
-	 * autoconfigure on any sane usb controller driver,
-	 * but there may also be important quirks to address.
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+	strings_dev[STRING_MANUFACTURER_IDX].id = id;
+	device_desc.iManufacturer = id;
+
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+	strings_dev[STRING_PRODUCT_IDX].id = id;
+	device_desc.iProduct = id;
+
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+	strings_dev[STRING_SERIAL_IDX].id = id;
+	device_desc.iSerialNumber = id;
+
+	/* Register primary, then secondary configuration.  Note that
+	 * SH3 only allows one config...
 	 */
-	usb_ep_autoconfig_reset(gadget);
-	ep = usb_ep_autoconfig(gadget, &fs_source_desc);
-	if (!ep) {
-autoconf_fail:
-		pr_err("%s: can't autoconfigure on %s\n",
-			shortname, gadget->name);
-		return -ENODEV;
+	if (loopdefault) {
+		loopback_add(cdev);
+		if (!gadget_is_sh(gadget))
+			sourcesink_add(cdev);
+	} else {
+		sourcesink_add(cdev);
+		if (!gadget_is_sh(gadget))
+			loopback_add(cdev);
 	}
-	EP_IN_NAME = ep->name;
-	ep->driver_data = ep;	/* claim */
-
-	ep = usb_ep_autoconfig(gadget, &fs_sink_desc);
-	if (!ep)
-		goto autoconf_fail;
-	EP_OUT_NAME = ep->name;
-	ep->driver_data = ep;	/* claim */
 
 	gcnum = usb_gadget_controller_number(gadget);
 	if (gcnum >= 0)
@@ -1115,144 +241,44 @@ autoconf_fail:
 	else {
 		/* gadget zero is so simple (for now, no altsettings) that
 		 * it SHOULD NOT have problems with bulk-capable hardware.
-		 * so warn about unrcognized controllers, don't panic.
+		 * so just warn about unrcognized controllers -- don't panic.
 		 *
 		 * things like configuration and altsetting numbering
 		 * can need hardware-specific attention though.
 		 */
 		pr_warning("%s: controller '%s' not recognized\n",
-			shortname, gadget->name);
+			longname, gadget->name);
 		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
 	}
 
 
-	/* ok, we made sense of the hardware ... */
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return -ENOMEM;
-	spin_lock_init(&dev->lock);
-	dev->gadget = gadget;
-	set_gadget_data(gadget, dev);
-
-	init_timer(&dev->resume);
-	dev->resume.function = zero_autoresume;
-	dev->resume.data = (unsigned long) dev;
-
-	/* preallocate control response and buffer */
-	dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
-	if (!dev->req)
-		goto enomem;
-	dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
-	if (!dev->req->buf)
-		goto enomem;
-
-	dev->req->complete = zero_setup_complete;
-
-	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-
-	if (gadget_is_dualspeed(gadget)) {
-		/* assume ep0 uses the same value for both speeds ... */
-		dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
-
-		/* and that all endpoints are dual-speed */
-		hs_source_desc.bEndpointAddress =
-				fs_source_desc.bEndpointAddress;
-		hs_sink_desc.bEndpointAddress =
-				fs_sink_desc.bEndpointAddress;
-	}
-
-	if (gadget_is_otg(gadget)) {
-		otg_descriptor.bmAttributes |= USB_OTG_HNP,
-		source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-		loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-	}
-
-	usb_gadget_set_selfpowered(gadget);
-
-	if (autoresume) {
-		source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-		loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-	}
-
-	gadget->ep0->driver_data = dev;
-
-	INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname);
-	INFO(dev, "using %s, OUT %s IN %s\n", gadget->name,
-		EP_OUT_NAME, EP_IN_NAME);
+	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);
 
 	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
 		init_utsname()->sysname, init_utsname()->release,
 		gadget->name);
 
 	return 0;
-
-enomem:
-	zero_unbind(gadget);
-	return -ENOMEM;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static void zero_suspend(struct usb_gadget *gadget)
-{
-	struct zero_dev		*dev = get_gadget_data(gadget);
-
-	if (gadget->speed == USB_SPEED_UNKNOWN)
-		return;
-
-	if (autoresume) {
-		mod_timer(&dev->resume, jiffies + (HZ * autoresume));
-		DBG(dev, "suspend, wakeup in %d seconds\n", autoresume);
-	} else
-		DBG(dev, "suspend\n");
-}
-
-static void zero_resume(struct usb_gadget *gadget)
-{
-	struct zero_dev		*dev = get_gadget_data(gadget);
-
-	DBG(dev, "resume\n");
-	del_timer(&dev->resume);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_gadget_driver zero_driver = {
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-	.speed		= USB_SPEED_HIGH,
-#else
-	.speed		= USB_SPEED_FULL,
-#endif
-	.function	= (char *) longname,
+static struct usb_composite_driver zero_driver = {
+	.name		= "zero",
+	.dev		= &device_desc,
+	.strings	= dev_strings,
 	.bind		= zero_bind,
-	.unbind		= __exit_p(zero_unbind),
-
-	.setup		= zero_setup,
-	.disconnect	= zero_disconnect,
-
-	.suspend	= zero_suspend,
-	.resume		= zero_resume,
-
-	.driver		= {
-		.name		= (char *) shortname,
-		.owner		= THIS_MODULE,
-	},
 };
 
 MODULE_AUTHOR("David Brownell");
 MODULE_LICENSE("GPL");
 
-
 static int __init init(void)
 {
-	return usb_gadget_register_driver(&zero_driver);
+	return usb_composite_register(&zero_driver);
 }
 module_init(init);
 
 static void __exit cleanup(void)
 {
-	usb_gadget_unregister_driver(&zero_driver);
+	usb_composite_unregister(&zero_driver);
 }
 module_exit(cleanup);
-
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
new file mode 100644
index 0000000..c932390
--- /dev/null
+++ b/include/linux/usb/composite.h
@@ -0,0 +1,338 @@
+/*
+ * composite.h -- framework for usb gadgets which are composite devices
+ *
+ * Copyright (C) 2006-2008 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+#ifndef	__LINUX_USB_COMPOSITE_H
+#define	__LINUX_USB_COMPOSITE_H
+
+/*
+ * This framework is an optional layer on top of the USB Gadget interface,
+ * making it easier to build (a) Composite devices, supporting multiple
+ * functions within any single configuration, and (b) Multi-configuration
+ * devices, also supporting multiple functions but without necessarily
+ * having more than one function per configuration.
+ *
+ * Example:  a device with a single configuration supporting both network
+ * link and mass storage functions is a composite device.  Those functions
+ * might alternatively be packaged in individual configurations, but in
+ * the composite model the host can use both functions at the same time.
+ */
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+
+struct usb_configuration;
+
+/**
+ * struct usb_function - describes one function of a configuration
+ * @name: For diagnostics, identifies the function.
+ * @strings: tables of strings, keyed by identifiers assigned during bind()
+ *	and by language IDs provided in control requests
+ * @descriptors: Table of full (or low) speed descriptors, using interface and
+ *	string identifiers assigned during @bind().  If this pointer is null,
+ *	the function will not be available at full speed (or at low speed).
+ * @hs_descriptors: Table of high speed descriptors, using interface and
+ *	string identifiers assigned during @bind().  If this pointer is null,
+ *	the function will not be available at high speed.
+ * @config: assigned when @usb_add_function() is called; this is the
+ *	configuration with which this function is associated.
+ * @bind: Before the gadget can register, all of its functions bind() to the
+ *	available resources including string and interface identifiers used
+ *	in interface or class descriptors; endpoints; I/O buffers; and so on.
+ * @unbind: Reverses @bind; called as a side effect of unregistering the
+ *	driver which added this function.
+ * @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may
+ *	initialize usb_ep.driver data at this time (when it is used).
+ *	Note that setting an interface to its current altsetting resets
+ *	interface state, and that all interfaces have a disabled state.
+ * @get_alt: Returns the active altsetting.  If this is not provided,
+ *	then only altsetting zero is supported.
+ * @disable: (REQUIRED) Indicates the function should be disabled.  Reasons
+ *	include host resetting or reconfiguring the gadget, and disconnection.
+ * @setup: Used for interface-specific control requests.
+ * @suspend: Notifies functions when the host stops sending USB traffic.
+ * @resume: Notifies functions when the host restarts USB traffic.
+ *
+ * A single USB function uses one or more interfaces, and should in most
+ * cases support operation at both full and high speeds.  Each function is
+ * associated by @usb_add_function() with a one configuration; that function
+ * causes @bind() to be called so resources can be allocated as part of
+ * setting up a gadget driver.  Those resources include endpoints, which
+ * should be allocated using @usb_ep_autoconfig().
+ *
+ * To support dual speed operation, a function driver provides descriptors
+ * for both high and full speed operation.  Except in rare cases that don't
+ * involve bulk endpoints, each speed needs different endpoint descriptors.
+ *
+ * Function drivers choose their own strategies for managing instance data.
+ * The simplest strategy just declares it "static', which means the function
+ * can only be activated once.  If the function needs to be exposed in more
+ * than one configuration at a given speed, it needs to support multiple
+ * usb_function structures (one for each configuration).
+ *
+ * A more complex strategy might encapsulate a @usb_function structure inside
+ * a driver-specific instance structure to allows multiple activations.  An
+ * example of multiple activations might be a CDC ACM function that supports
+ * two or more distinct instances within the same configuration, providing
+ * several independent logical data links to a USB host.
+ */
+struct usb_function {
+	const char			*name;
+	struct usb_gadget_strings	**strings;
+	struct usb_descriptor_header	**descriptors;
+	struct usb_descriptor_header	**hs_descriptors;
+
+	struct usb_configuration	*config;
+
+	/* REVISIT:  bind() functions can be marked __init, which
+	 * makes trouble for section mismatch analysis.  See if
+	 * we can't restructure things to avoid mismatching.
+	 * Related:  unbind() may kfree() but bind() won't...
+	 */
+
+	/* configuration management:  bind/unbind */
+	int			(*bind)(struct usb_configuration *,
+					struct usb_function *);
+	void			(*unbind)(struct usb_configuration *,
+					struct usb_function *);
+
+	/* runtime state management */
+	int			(*set_alt)(struct usb_function *,
+					unsigned interface, unsigned alt);
+	int			(*get_alt)(struct usb_function *,
+					unsigned interface);
+	void			(*disable)(struct usb_function *);
+	int			(*setup)(struct usb_function *,
+					const struct usb_ctrlrequest *);
+	void			(*suspend)(struct usb_function *);
+	void			(*resume)(struct usb_function *);
+
+	/* internals */
+	struct list_head		list;
+};
+
+int usb_add_function(struct usb_configuration *, struct usb_function *);
+
+int usb_interface_id(struct usb_configuration *, struct usb_function *);
+
+/**
+ * ep_choose - select descriptor endpoint at current device speed
+ * @g: gadget, connected and running at some speed
+ * @hs: descriptor to use for high speed operation
+ * @fs: descriptor to use for full or low speed operation
+ */
+static inline struct usb_endpoint_descriptor *
+ep_choose(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
+		struct usb_endpoint_descriptor *fs)
+{
+	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+		return hs;
+	return fs;
+}
+
+#define	MAX_CONFIG_INTERFACES		16	/* arbitrary; max 255 */
+
+/**
+ * struct usb_configuration - represents one gadget configuration
+ * @label: For diagnostics, describes the configuration.
+ * @strings: Tables of strings, keyed by identifiers assigned during @bind()
+ *	and by language IDs provided in control requests.
+ * @descriptors: Table of descriptors preceding all function descriptors.
+ *	Examples include OTG and vendor-specific descriptors.
+ * @bind: Called from @usb_add_config() to allocate resources unique to this
+ *	configuration and to call @usb_add_function() for each function used.
+ * @unbind: Reverses @bind; called as a side effect of unregistering the
+ *	driver which added this configuration.
+ * @setup: Used to delegate control requests that aren't handled by standard
+ *	device infrastructure or directed at a specific interface.
+ * @bConfigurationValue: Copied into configuration descriptor.
+ * @iConfiguration: Copied into configuration descriptor.
+ * @bmAttributes: Copied into configuration descriptor.
+ * @bMaxPower: Copied into configuration descriptor.
+ * @cdev: assigned by @usb_add_config() before calling @bind(); this is
+ *	the device associated with this configuration.
+ *
+ * Configurations are building blocks for gadget drivers structured around
+ * function drivers.  Simple USB gadgets require only one function and one
+ * configuration, and handle dual-speed hardware by always providing the same
+ * functionality.  Slightly more complex gadgets may have more than one
+ * single-function configuration at a given speed; or have configurations
+ * that only work at one speed.
+ *
+ * Composite devices are, by definition, ones with configurations which
+ * include more than one function.
+ *
+ * The lifecycle of a usb_configuration includes allocation, initialization
+ * of the fields described above, and calling @usb_add_config() to set up
+ * internal data and bind it to a specific device.  The configuration's
+ * @bind() method is then used to initialize all the functions and then
+ * call @usb_add_function() for them.
+ *
+ * Those functions would normally be independant of each other, but that's
+ * not mandatory.  CDC WMC devices are an example where functions often
+ * depend on other functions, with some functions subsidiary to others.
+ * Such interdependency may be managed in any way, so long as all of the
+ * descriptors complete by the time the composite driver returns from
+ * its bind() routine.
+ */
+struct usb_configuration {
+	const char			*label;
+	struct usb_gadget_strings	**strings;
+	const struct usb_descriptor_header **descriptors;
+
+	/* REVISIT:  bind() functions can be marked __init, which
+	 * makes trouble for section mismatch analysis.  See if
+	 * we can't restructure things to avoid mismatching...
+	 */
+
+	/* configuration management:  bind/unbind */
+	int			(*bind)(struct usb_configuration *);
+	void			(*unbind)(struct usb_configuration *);
+	int			(*setup)(struct usb_configuration *,
+					const struct usb_ctrlrequest *);
+
+	/* fields in the config descriptor */
+	u8			bConfigurationValue;
+	u8			iConfiguration;
+	u8			bmAttributes;
+	u8			bMaxPower;
+
+	struct usb_composite_dev	*cdev;
+
+	/* internals */
+	struct list_head	list;
+	struct list_head	functions;
+	u8			next_interface_id;
+	unsigned		highspeed:1;
+	unsigned		fullspeed:1;
+	struct usb_function	*interface[MAX_CONFIG_INTERFACES];
+};
+
+int usb_add_config(struct usb_composite_dev *,
+		struct usb_configuration *);
+
+/**
+ * struct usb_composite_driver - groups configurations into a gadget
+ * @name: For diagnostics, identifies the driver.
+ * @dev: Template descriptor for the device, including default device
+ *	identifiers.
+ * @strings: tables of strings, keyed by identifiers assigned during bind()
+ *	and language IDs provided in control requests
+ * @bind: (REQUIRED) Used to allocate resources that are shared across the
+ *	whole device, such as string IDs, and add its configurations using
+ *	@usb_add_config().  This may fail by returning a negative errno
+ *	value; it should return zero on successful initialization.
+ * @unbind: Reverses @bind(); called as a side effect of unregistering
+ *	this driver.
+ *
+ * Devices default to reporting self powered operation.  Devices which rely
+ * on bus powered operation should report this in their @bind() method.
+ *
+ * Before returning from @bind, various fields in the template descriptor
+ * may be overridden.  These include the idVendor/idProduct/bcdDevice values
+ * normally to bind the appropriate host side driver, and the three strings
+ * (iManufacturer, iProduct, iSerialNumber) normally used to provide user
+ * meaningful device identifiers.  (The strings will not be defined unless
+ * they are defined in @dev and @strings.)  The correct ep0 maxpacket size
+ * is also reported, as defined by the underlying controller driver.
+ */
+struct usb_composite_driver {
+	const char				*name;
+	const struct usb_device_descriptor	*dev;
+	struct usb_gadget_strings		**strings;
+
+	/* REVISIT:  bind() functions can be marked __init, which
+	 * makes trouble for section mismatch analysis.  See if
+	 * we can't restructure things to avoid mismatching...
+	 */
+
+	int			(*bind)(struct usb_composite_dev *);
+	int			(*unbind)(struct usb_composite_dev *);
+};
+
+extern int usb_composite_register(struct usb_composite_driver *);
+extern void usb_composite_unregister(struct usb_composite_driver *);
+
+
+/**
+ * struct usb_composite_device - represents one composite usb gadget
+ * @gadget: read-only, abstracts the gadget's usb peripheral controller
+ * @req: used for control responses; buffer is pre-allocated
+ * @bufsiz: size of buffer pre-allocated in @req
+ * @config: the currently active configuration
+ *
+ * One of these devices is allocated and initialized before the
+ * associated device driver's bind() is called.
+ *
+ * OPEN ISSUE:  it appears that some WUSB devices will need to be
+ * built by combining a normal (wired) gadget with a wireless one.
+ * This revision of the gadget framework should probably try to make
+ * sure doing that won't hurt too much.
+ *
+ * One notion for how to handle Wireless USB devices involves:
+ * (a) a second gadget here, discovery mechanism TBD, but likely
+ *     needing separate "register/unregister WUSB gadget" calls;
+ * (b) updates to usb_gadget to include flags "is it wireless",
+ *     "is it wired", plus (presumably in a wrapper structure)
+ *     bandgroup and PHY info;
+ * (c) presumably a wireless_ep wrapping a usb_ep, and reporting
+ *     wireless-specific parameters like maxburst and maxsequence;
+ * (d) configurations that are specific to wireless links;
+ * (e) function drivers that understand wireless configs and will
+ *     support wireless for (additional) function instances;
+ * (f) a function to support association setup (like CBAF), not
+ *     necessarily requiring a wireless adapter;
+ * (g) composite device setup that can create one or more wireless
+ *     configs, including appropriate association setup support;
+ * (h) more, TBD.
+ */
+struct usb_composite_dev {
+	struct usb_gadget		*gadget;
+	struct usb_request		*req;
+	unsigned			bufsiz;
+
+	struct usb_configuration	*config;
+
+	/* internals */
+	struct usb_device_descriptor	desc;
+	struct list_head		configs;
+	struct usb_composite_driver	*driver;
+	u8				next_string_id;
+
+	spinlock_t			lock;
+
+	/* REVISIT use and existence of lock ... */
+};
+
+extern int usb_string_id(struct usb_composite_dev *c);
+
+/* messaging utils */
+#define DBG(d, fmt, args...) \
+	dev_dbg(&(d)->gadget->dev , fmt , ## args)
+#define VDBG(d, fmt, args...) \
+	dev_vdbg(&(d)->gadget->dev , fmt , ## args)
+#define ERROR(d, fmt, args...) \
+	dev_err(&(d)->gadget->dev , fmt , ## args)
+#define WARNING(d, fmt, args...) \
+	dev_warn(&(d)->gadget->dev , fmt , ## args)
+#define INFO(d, fmt, args...) \
+	dev_info(&(d)->gadget->dev , fmt , ## args)
+
+#endif	/* __LINUX_USB_COMPOSITE_H */
diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h
new file mode 100644
index 0000000..5b88e36
--- /dev/null
+++ b/include/linux/usb/ehci_def.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2001-2002 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __LINUX_USB_EHCI_DEF_H
+#define __LINUX_USB_EHCI_DEF_H
+
+/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */
+
+/* Section 2.2 Host Controller Capability Registers */
+struct ehci_caps {
+	/* these fields are specified as 8 and 16 bit registers,
+	 * but some hosts can't perform 8 or 16 bit PCI accesses.
+	 */
+	u32		hc_capbase;
+#define HC_LENGTH(p)		(((p)>>00)&0x00ff)	/* bits 7:0 */
+#define HC_VERSION(p)		(((p)>>16)&0xffff)	/* bits 31:16 */
+	u32		hcs_params;     /* HCSPARAMS - offset 0x4 */
+#define HCS_DEBUG_PORT(p)	(((p)>>20)&0xf)	/* bits 23:20, debug port? */
+#define HCS_INDICATOR(p)	((p)&(1 << 16))	/* true: has port indicators */
+#define HCS_N_CC(p)		(((p)>>12)&0xf)	/* bits 15:12, #companion HCs */
+#define HCS_N_PCC(p)		(((p)>>8)&0xf)	/* bits 11:8, ports per CC */
+#define HCS_PORTROUTED(p)	((p)&(1 << 7))	/* true: port routing */
+#define HCS_PPC(p)		((p)&(1 << 4))	/* true: port power control */
+#define HCS_N_PORTS(p)		(((p)>>0)&0xf)	/* bits 3:0, ports on HC */
+
+	u32		hcc_params;      /* HCCPARAMS - offset 0x8 */
+#define HCC_EXT_CAPS(p)		(((p)>>8)&0xff)	/* for pci extended caps */
+#define HCC_ISOC_CACHE(p)       ((p)&(1 << 7))  /* true: can cache isoc frame */
+#define HCC_ISOC_THRES(p)       (((p)>>4)&0x7)  /* bits 6:4, uframes cached */
+#define HCC_CANPARK(p)		((p)&(1 << 2))  /* true: can park on async qh */
+#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1))  /* true: periodic_size changes*/
+#define HCC_64BIT_ADDR(p)       ((p)&(1))       /* true: can use 64-bit addr */
+	u8		portroute [8];	 /* nibbles for routing - offset 0xC */
+} __attribute__ ((packed));
+
+
+/* Section 2.3 Host Controller Operational Registers */
+struct ehci_regs {
+
+	/* USBCMD: offset 0x00 */
+	u32		command;
+/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */
+#define CMD_PARK	(1<<11)		/* enable "park" on async qh */
+#define CMD_PARK_CNT(c)	(((c)>>8)&3)	/* how many transfers to park for */
+#define CMD_LRESET	(1<<7)		/* partial reset (no ports, etc) */
+#define CMD_IAAD	(1<<6)		/* "doorbell" interrupt async advance */
+#define CMD_ASE		(1<<5)		/* async schedule enable */
+#define CMD_PSE		(1<<4)		/* periodic schedule enable */
+/* 3:2 is periodic frame list size */
+#define CMD_RESET	(1<<1)		/* reset HC not bus */
+#define CMD_RUN		(1<<0)		/* start/stop HC */
+
+	/* USBSTS: offset 0x04 */
+	u32		status;
+#define STS_ASS		(1<<15)		/* Async Schedule Status */
+#define STS_PSS		(1<<14)		/* Periodic Schedule Status */
+#define STS_RECL	(1<<13)		/* Reclamation */
+#define STS_HALT	(1<<12)		/* Not running (any reason) */
+/* some bits reserved */
+	/* these STS_* flags are also intr_enable bits (USBINTR) */
+#define STS_IAA		(1<<5)		/* Interrupted on async advance */
+#define STS_FATAL	(1<<4)		/* such as some PCI access errors */
+#define STS_FLR		(1<<3)		/* frame list rolled over */
+#define STS_PCD		(1<<2)		/* port change detect */
+#define STS_ERR		(1<<1)		/* "error" completion (overflow, ...) */
+#define STS_INT		(1<<0)		/* "normal" completion (short, ...) */
+
+	/* USBINTR: offset 0x08 */
+	u32		intr_enable;
+
+	/* FRINDEX: offset 0x0C */
+	u32		frame_index;	/* current microframe number */
+	/* CTRLDSSEGMENT: offset 0x10 */
+	u32		segment;	/* address bits 63:32 if needed */
+	/* PERIODICLISTBASE: offset 0x14 */
+	u32		frame_list;	/* points to periodic list */
+	/* ASYNCLISTADDR: offset 0x18 */
+	u32		async_next;	/* address of next async queue head */
+
+	u32		reserved [9];
+
+	/* CONFIGFLAG: offset 0x40 */
+	u32		configured_flag;
+#define FLAG_CF		(1<<0)		/* true: we'll support "high speed" */
+
+	/* PORTSC: offset 0x44 */
+	u32		port_status [0];	/* up to N_PORTS */
+/* 31:23 reserved */
+#define PORT_WKOC_E	(1<<22)		/* wake on overcurrent (enable) */
+#define PORT_WKDISC_E	(1<<21)		/* wake on disconnect (enable) */
+#define PORT_WKCONN_E	(1<<20)		/* wake on connect (enable) */
+/* 19:16 for port testing */
+#define PORT_LED_OFF	(0<<14)
+#define PORT_LED_AMBER	(1<<14)
+#define PORT_LED_GREEN	(2<<14)
+#define PORT_LED_MASK	(3<<14)
+#define PORT_OWNER	(1<<13)		/* true: companion hc owns this port */
+#define PORT_POWER	(1<<12)		/* true: has power (see PPC) */
+#define PORT_USB11(x) (((x)&(3<<10)) == (1<<10))	/* USB 1.1 device */
+/* 11:10 for detecting lowspeed devices (reset vs release ownership) */
+/* 9 reserved */
+#define PORT_RESET	(1<<8)		/* reset port */
+#define PORT_SUSPEND	(1<<7)		/* suspend port */
+#define PORT_RESUME	(1<<6)		/* resume it */
+#define PORT_OCC	(1<<5)		/* over current change */
+#define PORT_OC		(1<<4)		/* over current active */
+#define PORT_PEC	(1<<3)		/* port enable change */
+#define PORT_PE		(1<<2)		/* port enable */
+#define PORT_CSC	(1<<1)		/* connect status change */
+#define PORT_CONNECT	(1<<0)		/* device connected */
+#define PORT_RWC_BITS   (PORT_CSC | PORT_PEC | PORT_OCC)
+} __attribute__ ((packed));
+
+#define USBMODE		0x68		/* USB Device mode */
+#define USBMODE_SDIS	(1<<3)		/* Stream disable */
+#define USBMODE_BE	(1<<2)		/* BE/LE endianness select */
+#define USBMODE_CM_HC	(3<<0)		/* host controller mode */
+#define USBMODE_CM_IDLE	(0<<0)		/* idle state */
+
+/* Appendix C, Debug port ... intended for use with special "debug devices"
+ * that can help if there's no serial console.  (nonstandard enumeration.)
+ */
+struct ehci_dbg_port {
+	u32	control;
+#define DBGP_OWNER	(1<<30)
+#define DBGP_ENABLED	(1<<28)
+#define DBGP_DONE	(1<<16)
+#define DBGP_INUSE	(1<<10)
+#define DBGP_ERRCODE(x)	(((x)>>7)&0x07)
+#	define DBGP_ERR_BAD	1
+#	define DBGP_ERR_SIGNAL	2
+#define DBGP_ERROR	(1<<6)
+#define DBGP_GO		(1<<5)
+#define DBGP_OUT	(1<<4)
+#define DBGP_LEN(x)	(((x)>>0)&0x0f)
+	u32	pids;
+#define DBGP_PID_GET(x)		(((x)>>16)&0xff)
+#define DBGP_PID_SET(data, tok)	(((data)<<8)|(tok))
+	u32	data03;
+	u32	data47;
+	u32	address;
+#define DBGP_EPADDR(dev, ep)	(((dev)<<8)|(ep))
+} __attribute__ ((packed));
+
+#endif /* __LINUX_USB_EHCI_DEF_H */
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index cf468fb..0460a74 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -33,7 +33,8 @@ struct usb_ep;
  * @short_not_ok: When reading data, makes short packets be
  *     treated as errors (queue stops advancing till cleanup).
  * @complete: Function called when request completes, so this request and
- *	its buffer may be re-used.
+ *	its buffer may be re-used.  The function will always be called with
+ *	interrupts disabled, and it must not sleep.
  *	Reads terminate with a short packet, or when the buffer fills,
  *	whichever comes first.  When writes terminate, some data bytes
  *	will usually still be in flight (often in a hardware fifo).
@@ -271,7 +272,10 @@ static inline void usb_ep_free_request(struct usb_ep *ep,
  * (Note that some USB device controllers disallow protocol stall responses
  * in some cases.)  When control responses are deferred (the response is
  * written after the setup callback returns), then usb_ep_set_halt() may be
- * used on ep0 to trigger protocol stalls.
+ * used on ep0 to trigger protocol stalls.  Depending on the controller,
+ * it may not be possible to trigger a status-stage protocol stall when the
+ * data stage is over, that is, from within the response's completion
+ * routine.
  *
  * For periodic endpoints, like interrupt or isochronous ones, the usb host
  * arranges to poll once per interval, and the gadget driver usually will
@@ -858,6 +862,25 @@ int usb_descriptor_fillbuf(void *, unsigned,
 int usb_gadget_config_buf(const struct usb_config_descriptor *config,
 	void *buf, unsigned buflen, const struct usb_descriptor_header **desc);
 
+/* copy a NULL-terminated vector of descriptors */
+struct usb_descriptor_header **usb_copy_descriptors(
+		struct usb_descriptor_header **);
+
+/* return copy of endpoint descriptor given original descriptor set */
+struct usb_endpoint_descriptor *usb_find_endpoint(
+	struct usb_descriptor_header **src,
+	struct usb_descriptor_header **copy,
+	struct usb_endpoint_descriptor *match);
+
+/**
+ * usb_free_descriptors - free descriptors returned by usb_copy_descriptors()
+ * @v: vector of descriptors
+ */
+static inline void usb_free_descriptors(struct usb_descriptor_header **v)
+{
+	kfree(v);
+}
+
 /*-------------------------------------------------------------------------*/
 
 /* utility wrapping a simple endpoint selection policy */
diff --git a/include/linux/usb/irda.h b/include/linux/usb/irda.h
new file mode 100644
index 0000000..e345cea
--- /dev/null
+++ b/include/linux/usb/irda.h
@@ -0,0 +1,151 @@
+/*
+ * USB IrDA Bridge Device Definition
+ */
+
+#ifndef __LINUX_USB_IRDA_H
+#define __LINUX_USB_IRDA_H
+
+/* This device should use Application-specific class */
+
+#define USB_SUBCLASS_IRDA			0x02
+
+/*-------------------------------------------------------------------------*/
+
+/* Class-Specific requests (bRequest field) */
+
+#define USB_REQ_CS_IRDA_RECEIVING		1
+#define USB_REQ_CS_IRDA_CHECK_MEDIA_BUSY	3
+#define USB_REQ_CS_IRDA_RATE_SNIFF		4
+#define USB_REQ_CS_IRDA_UNICAST_LIST		5
+#define USB_REQ_CS_IRDA_GET_CLASS_DESC		6
+
+/*-------------------------------------------------------------------------*/
+
+/* Class-Specific descriptor */
+
+#define USB_DT_CS_IRDA				0x21
+
+/*-------------------------------------------------------------------------*/
+
+/* Data sizes */
+
+#define USB_IRDA_DS_2048			(1 << 5)
+#define USB_IRDA_DS_1024			(1 << 4)
+#define USB_IRDA_DS_512				(1 << 3)
+#define USB_IRDA_DS_256				(1 << 2)
+#define USB_IRDA_DS_128				(1 << 1)
+#define USB_IRDA_DS_64				(1 << 0)
+
+/* Window sizes */
+
+#define USB_IRDA_WS_7				(1 << 6)
+#define USB_IRDA_WS_6				(1 << 5)
+#define USB_IRDA_WS_5				(1 << 4)
+#define USB_IRDA_WS_4				(1 << 3)
+#define USB_IRDA_WS_3				(1 << 2)
+#define USB_IRDA_WS_2				(1 << 1)
+#define USB_IRDA_WS_1				(1 << 0)
+
+/* Min turnaround times in usecs */
+
+#define USB_IRDA_MTT_0				(1 << 7)
+#define USB_IRDA_MTT_10				(1 << 6)
+#define USB_IRDA_MTT_50				(1 << 5)
+#define USB_IRDA_MTT_100			(1 << 4)
+#define USB_IRDA_MTT_500			(1 << 3)
+#define USB_IRDA_MTT_1000			(1 << 2)
+#define USB_IRDA_MTT_5000			(1 << 1)
+#define USB_IRDA_MTT_10000			(1 << 0)
+
+/* Baud rates */
+
+#define USB_IRDA_BR_4000000			(1 << 8)
+#define USB_IRDA_BR_1152000			(1 << 7)
+#define USB_IRDA_BR_576000			(1 << 6)
+#define USB_IRDA_BR_115200			(1 << 5)
+#define USB_IRDA_BR_57600			(1 << 4)
+#define USB_IRDA_BR_38400			(1 << 3)
+#define USB_IRDA_BR_19200			(1 << 2)
+#define USB_IRDA_BR_9600			(1 << 1)
+#define USB_IRDA_BR_2400			(1 << 0)
+
+/* Additional BOFs */
+
+#define USB_IRDA_AB_0				(1 << 7)
+#define USB_IRDA_AB_1				(1 << 6)
+#define USB_IRDA_AB_2				(1 << 5)
+#define USB_IRDA_AB_3				(1 << 4)
+#define USB_IRDA_AB_6				(1 << 3)
+#define USB_IRDA_AB_12				(1 << 2)
+#define USB_IRDA_AB_24				(1 << 1)
+#define USB_IRDA_AB_48				(1 << 0)
+
+/* IRDA Rate Sniff */
+
+#define USB_IRDA_RATE_SNIFF			1
+
+/*-------------------------------------------------------------------------*/
+
+struct usb_irda_cs_descriptor {
+	__u8	bLength;
+	__u8	bDescriptorType;
+
+	__le16	bcdSpecRevision;
+	__u8	bmDataSize;
+	__u8	bmWindowSize;
+	__u8	bmMinTurnaroundTime;
+	__le16	wBaudRate;
+	__u8	bmAdditionalBOFs;
+	__u8	bIrdaRateSniff;
+	__u8	bMaxUnicastList;
+} __attribute__ ((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* Data Format */
+
+#define USB_IRDA_STATUS_MEDIA_BUSY	(1 << 7)
+
+/* The following is a 4-bit value used for both
+ * inbound and outbound headers:
+ *
+ * 0 - speed ignored
+ * 1 - 2400 bps
+ * 2 - 9600 bps
+ * 3 - 19200 bps
+ * 4 - 38400 bps
+ * 5 - 57600 bps
+ * 6 - 115200 bps
+ * 7 - 576000 bps
+ * 8 - 1.152 Mbps
+ * 9 - 5 mbps
+ * 10..15 - Reserved
+ */
+#define USB_IRDA_STATUS_LINK_SPEED	0x0f
+
+/* The following is a 4-bit value used only for
+ * outbound header:
+ *
+ * 0 - No change (BOF ignored)
+ * 1 - 48 BOFs
+ * 2 - 24 BOFs
+ * 3 - 12 BOFs
+ * 4 - 6 BOFs
+ * 5 - 3 BOFs
+ * 6 - 2 BOFs
+ * 7 - 1 BOFs
+ * 8 - 0 BOFs
+ * 9..15 - Reserved
+ */
+#define USB_IRDA_EXTRA_BOFS		0xf0
+
+struct usb_irda_inbound_header {
+	__u8		bmStatus;
+};
+
+struct usb_irda_outbound_header {
+	__u8		bmChange;
+};
+
+#endif /* __LINUX_USB_IRDA_H */
+
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
new file mode 100644
index 0000000..630962c
--- /dev/null
+++ b/include/linux/usb/musb.h
@@ -0,0 +1,98 @@
+/*
+ * This is used to for host and peripheral modes of the driver for
+ * Inventra (Multidrop) Highspeed Dual-Role Controllers:  (M)HDRC.
+ *
+ * Board initialization should put one of these into dev->platform_data,
+ * probably on some platform_device named "musb_hdrc".  It encapsulates
+ * key configuration differences between boards.
+ */
+
+/* The USB role is defined by the connector used on the board, so long as
+ * standards are being followed.  (Developer boards sometimes won't.)
+ */
+enum musb_mode {
+	MUSB_UNDEFINED = 0,
+	MUSB_HOST,		/* A or Mini-A connector */
+	MUSB_PERIPHERAL,	/* B or Mini-B connector */
+	MUSB_OTG		/* Mini-AB connector */
+};
+
+struct clk;
+
+struct musb_hdrc_eps_bits {
+	const char	name[16];
+	u8		bits;
+};
+
+struct musb_hdrc_config {
+	/* MUSB configuration-specific details */
+	unsigned	multipoint:1;	/* multipoint device */
+	unsigned	dyn_fifo:1;	/* supports dynamic fifo sizing */
+	unsigned	soft_con:1;	/* soft connect required */
+	unsigned	utm_16:1;	/* utm data witdh is 16 bits */
+	unsigned	big_endian:1;	/* true if CPU uses big-endian */
+	unsigned	mult_bulk_tx:1;	/* Tx ep required for multbulk pkts */
+	unsigned	mult_bulk_rx:1;	/* Rx ep required for multbulk pkts */
+	unsigned	high_iso_tx:1;	/* Tx ep required for HB iso */
+	unsigned	high_iso_rx:1;	/* Rx ep required for HD iso */
+	unsigned	dma:1;		/* supports DMA */
+	unsigned	vendor_req:1;	/* vendor registers required */
+
+	u8		num_eps;	/* number of endpoints _with_ ep0 */
+	u8		dma_channels;	/* number of dma channels */
+	u8		dyn_fifo_size;	/* dynamic size in bytes */
+	u8		vendor_ctrl;	/* vendor control reg width */
+	u8		vendor_stat;	/* vendor status reg witdh */
+	u8		dma_req_chan;	/* bitmask for required dma channels */
+	u8		ram_bits;	/* ram address size */
+
+	struct musb_hdrc_eps_bits *eps_bits;
+};
+
+struct musb_hdrc_platform_data {
+	/* MUSB_HOST, MUSB_PERIPHERAL, or MUSB_OTG */
+	u8		mode;
+
+	/* for clk_get() */
+	const char	*clock;
+
+	/* (HOST or OTG) switch VBUS on/off */
+	int		(*set_vbus)(struct device *dev, int is_on);
+
+	/* (HOST or OTG) mA/2 power supplied on (default = 8mA) */
+	u8		power;
+
+	/* (PERIPHERAL) mA/2 max power consumed (default = 100mA) */
+	u8		min_power;
+
+	/* (HOST or OTG) msec/2 after VBUS on till power good */
+	u8		potpgt;
+
+	/* Power the device on or off */
+	int		(*set_power)(int state);
+
+	/* Turn device clock on or off */
+	int		(*set_clock)(struct clk *clock, int is_on);
+
+	/* MUSB configuration-specific details */
+	struct musb_hdrc_config	*config;
+};
+
+
+/* TUSB 6010 support */
+
+#define	TUSB6010_OSCCLK_60	16667	/* psec/clk @ 60.0 MHz */
+#define	TUSB6010_REFCLK_24	41667	/* psec/clk @ 24.0 MHz XI */
+#define	TUSB6010_REFCLK_19	52083	/* psec/clk @ 19.2 MHz CLKIN */
+
+#ifdef	CONFIG_ARCH_OMAP2
+
+extern int __init tusb6010_setup_interface(
+		struct musb_hdrc_platform_data *data,
+		unsigned ps_refclk, unsigned waitpin,
+		unsigned async_cs, unsigned sync_cs,
+		unsigned irq, unsigned dmachan);
+
+extern int tusb6010_platform_retime(unsigned is_refclk);
+
+#endif	/* OMAP2 */
diff --git a/include/linux/usb/rndis_host.h b/include/linux/usb/rndis_host.h
index 29d6458..0a6e6d4 100644
--- a/include/linux/usb/rndis_host.h
+++ b/include/linux/usb/rndis_host.h
@@ -260,7 +260,8 @@ struct rndis_keepalive_c {	/* IN (optionally OUT) */
 
 
 extern void rndis_status(struct usbnet *dev, struct urb *urb);
-extern int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf);
+extern int
+rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen);
 extern int
 generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags);
 extern void rndis_unbind(struct usbnet *dev, struct usb_interface *intf);
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 8f891cb..655341d 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -17,7 +17,8 @@
 #include <linux/mutex.h>
 
 #define SERIAL_TTY_MAJOR	188	/* Nice legal number now */
-#define SERIAL_TTY_MINORS	255	/* loads of devices :) */
+#define SERIAL_TTY_MINORS	254	/* loads of devices :) */
+#define SERIAL_TTY_NO_MINOR	255	/* No minor was assigned */
 
 /* The maximum number of ports one device can grab at once */
 #define MAX_NUM_PORTS		8
@@ -62,7 +63,7 @@
  */
 struct usb_serial_port {
 	struct usb_serial	*serial;
-	struct tty_struct	*tty;
+	struct tty_port		port;
 	spinlock_t		lock;
 	struct mutex            mutex;
 	unsigned char		number;
@@ -89,7 +90,6 @@ struct usb_serial_port {
 
 	wait_queue_head_t	write_wait;
 	struct work_struct	work;
-	int			open_count;
 	char			throttled;
 	char			throttle_req;
 	char			console;
@@ -217,22 +217,27 @@ struct usb_serial_driver {
 	int (*resume)(struct usb_serial *serial);
 
 	/* serial function calls */
-	int  (*open)(struct usb_serial_port *port, struct file *filp);
-	void (*close)(struct usb_serial_port *port, struct file *filp);
-	int  (*write)(struct usb_serial_port *port, const unsigned char *buf,
-		      int count);
-	int  (*write_room)(struct usb_serial_port *port);
-	int  (*ioctl)(struct usb_serial_port *port, struct file *file,
+	/* Called by console with tty = NULL and by tty */
+	int  (*open)(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+	void (*close)(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+	int  (*write)(struct tty_struct *tty, struct usb_serial_port *port,
+			const unsigned char *buf, int count);
+	/* Called only by the tty layer */
+	int  (*write_room)(struct tty_struct *tty);
+	int  (*ioctl)(struct tty_struct *tty, struct file *file,
 		      unsigned int cmd, unsigned long arg);
-	void (*set_termios)(struct usb_serial_port *port, struct ktermios *old);
-	void (*break_ctl)(struct usb_serial_port *port, int break_state);
-	int  (*chars_in_buffer)(struct usb_serial_port *port);
-	void (*throttle)(struct usb_serial_port *port);
-	void (*unthrottle)(struct usb_serial_port *port);
-	int  (*tiocmget)(struct usb_serial_port *port, struct file *file);
-	int  (*tiocmset)(struct usb_serial_port *port, struct file *file,
+	void (*set_termios)(struct tty_struct *tty,
+			struct usb_serial_port *port, struct ktermios *old);
+	void (*break_ctl)(struct tty_struct *tty, int break_state);
+	int  (*chars_in_buffer)(struct tty_struct *tty);
+	void (*throttle)(struct tty_struct *tty);
+	void (*unthrottle)(struct tty_struct *tty);
+	int  (*tiocmget)(struct tty_struct *tty, struct file *file);
+	int  (*tiocmset)(struct tty_struct *tty, struct file *file,
 			 unsigned int set, unsigned int clear);
-
+	/* USB events */
 	void (*read_int_callback)(struct urb *urb);
 	void (*write_int_callback)(struct urb *urb);
 	void (*read_bulk_callback)(struct urb *urb);
@@ -270,19 +275,19 @@ static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}
 /* Functions needed by other parts of the usbserial core */
 extern struct usb_serial *usb_serial_get_by_index(unsigned int minor);
 extern void usb_serial_put(struct usb_serial *serial);
-extern int usb_serial_generic_open(struct usb_serial_port *port,
-				   struct file *filp);
-extern int usb_serial_generic_write(struct usb_serial_port *port,
-				    const unsigned char *buf, int count);
-extern void usb_serial_generic_close(struct usb_serial_port *port,
-				     struct file *filp);
+extern int usb_serial_generic_open(struct tty_struct *tty,
+		struct usb_serial_port *port, struct file *filp);
+extern int usb_serial_generic_write(struct tty_struct *tty,
+	struct usb_serial_port *port, const unsigned char *buf, int count);
+extern void usb_serial_generic_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
 extern int usb_serial_generic_resume(struct usb_serial *serial);
-extern int usb_serial_generic_write_room(struct usb_serial_port *port);
-extern int usb_serial_generic_chars_in_buffer(struct usb_serial_port *port);
+extern int usb_serial_generic_write_room(struct tty_struct *tty);
+extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);
 extern void usb_serial_generic_read_bulk_callback(struct urb *urb);
 extern void usb_serial_generic_write_bulk_callback(struct urb *urb);
-extern void usb_serial_generic_throttle(struct usb_serial_port *port);
-extern void usb_serial_generic_unthrottle(struct usb_serial_port *port);
+extern void usb_serial_generic_throttle(struct tty_struct *tty);
+extern void usb_serial_generic_unthrottle(struct tty_struct *tty);
 extern void usb_serial_generic_shutdown(struct usb_serial *serial);
 extern int usb_serial_generic_register(int debug);
 extern void usb_serial_generic_deregister(void);