Merge tag 'usb-for-v3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

Felipe writes:

usb: patches for v3.17 merge window

Surprisingly enough, while a big set of patches, the majority is
composed of cleanups (using devm_*, fixing sparse errors, moving
code around, adding const, etc).

The highlights are addition of new support for PLX USB338x devices,
and support for USB 2.0-only configurations of the DWC3 IP core.

Signed-of-by: Felipe Balbi <balbi@ti.com>
diff --git a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl
index 2c425d7..6416292 100644
--- a/Documentation/DocBook/gadget.tmpl
+++ b/Documentation/DocBook/gadget.tmpl
@@ -556,11 +556,11 @@
 Near-term plans include converting all of them, except for "gadgetfs".
 </para>
 
-!Edrivers/usb/gadget/f_acm.c
-!Edrivers/usb/gadget/f_ecm.c
-!Edrivers/usb/gadget/f_subset.c
-!Edrivers/usb/gadget/f_obex.c
-!Edrivers/usb/gadget/f_serial.c
+!Edrivers/usb/gadget/function/f_acm.c
+!Edrivers/usb/gadget/function/f_ecm.c
+!Edrivers/usb/gadget/function/f_subset.c
+!Edrivers/usb/gadget/function/f_obex.c
+!Edrivers/usb/gadget/function/f_serial.c
 
 </sect1>
 
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index eb69eb9..b769c1f 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -386,6 +386,13 @@
 	}
 	dwc->revision = reg;
 
+	/* Handle USB2.0-only core configuration */
+	if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
+			DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
+		if (dwc->maximum_speed == USB_SPEED_SUPER)
+			dwc->maximum_speed = USB_SPEED_HIGH;
+	}
+
 	/* issue device SoftReset too */
 	timeout = jiffies + msecs_to_jiffies(500);
 	dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
@@ -656,6 +663,31 @@
 		return -ENODEV;
 	}
 
+	dwc->xhci_resources[0].start = res->start;
+	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
+					DWC3_XHCI_REGS_END;
+	dwc->xhci_resources[0].flags = res->flags;
+	dwc->xhci_resources[0].name = res->name;
+
+	res->start += DWC3_GLOBALS_REGS_START;
+
+	/*
+	 * Request memory region but exclude xHCI regs,
+	 * since it will be requested by the xhci-plat driver.
+	 */
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	dwc->regs	= regs;
+	dwc->regs_size	= resource_size(res);
+	/*
+	 * restore res->start back to its original value so that,
+	 * in case the probe is deferred, we don't end up getting error in
+	 * request the memory region the next time probe is called.
+	 */
+	res->start -= DWC3_GLOBALS_REGS_START;
+
 	if (node) {
 		dwc->maximum_speed = of_usb_get_maximum_speed(node);
 
@@ -676,28 +708,9 @@
 	if (ret)
 		return ret;
 
-	dwc->xhci_resources[0].start = res->start;
-	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
-					DWC3_XHCI_REGS_END;
-	dwc->xhci_resources[0].flags = res->flags;
-	dwc->xhci_resources[0].name = res->name;
-
-	res->start += DWC3_GLOBALS_REGS_START;
-
-	/*
-	 * Request memory region but exclude xHCI regs,
-	 * since it will be requested by the xhci-plat driver.
-	 */
-	regs = devm_ioremap_resource(dev, res);
-	if (IS_ERR(regs))
-		return PTR_ERR(regs);
-
 	spin_lock_init(&dwc->lock);
 	platform_set_drvdata(pdev, dwc);
 
-	dwc->regs	= regs;
-	dwc->regs_size	= resource_size(res);
-
 	dev->dma_mask	= dev->parent->dma_mask;
 	dev->dma_parms	= dev->parent->dma_parms;
 	dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 57332e3..48fb264 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -191,6 +191,19 @@
 #define DWC3_GHWPARAMS1_PWROPT(n)	((n) << 24)
 #define DWC3_GHWPARAMS1_PWROPT_MASK	DWC3_GHWPARAMS1_PWROPT(3)
 
+/* Global HWPARAMS3 Register */
+#define DWC3_GHWPARAMS3_SSPHY_IFC(n)		((n) & 3)
+#define DWC3_GHWPARAMS3_SSPHY_IFC_DIS		0
+#define DWC3_GHWPARAMS3_SSPHY_IFC_ENA		1
+#define DWC3_GHWPARAMS3_HSPHY_IFC(n)		(((n) & (3 << 2)) >> 2)
+#define DWC3_GHWPARAMS3_HSPHY_IFC_DIS		0
+#define DWC3_GHWPARAMS3_HSPHY_IFC_UTMI		1
+#define DWC3_GHWPARAMS3_HSPHY_IFC_ULPI		2
+#define DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI	3
+#define DWC3_GHWPARAMS3_FSPHY_IFC(n)		(((n) & (3 << 4)) >> 4)
+#define DWC3_GHWPARAMS3_FSPHY_IFC_DIS		0
+#define DWC3_GHWPARAMS3_FSPHY_IFC_ENA		1
+
 /* Global HWPARAMS4 Register */
 #define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n)	(((n) & (0x0f << 13)) >> 13)
 #define DWC3_MAX_HIBER_SCRATCHBUFS		15
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 07a736a..ef4936f 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -77,10 +77,6 @@
 #define USBOTGSS_DEV_EBC_EN			0x0110
 #define USBOTGSS_DEBUG_OFFSET			0x0600
 
-/* REVISION REGISTER */
-#define USBOTGSS_REVISION_XMAJOR(reg)		((reg >> 8) & 0x7)
-#define USBOTGSS_REVISION_XMAJOR1		1
-#define USBOTGSS_REVISION_XMAJOR2		2
 /* SYSCONFIG REGISTER */
 #define USBOTGSS_SYSCONFIG_DMADISABLE		(1 << 16)
 
@@ -129,7 +125,6 @@
 	u32			irq_eoi_offset;
 	u32			debug_offset;
 	u32			irq0_offset;
-	u32			revision;
 
 	u32			dma_status:1;
 
@@ -383,6 +378,87 @@
 	return NOTIFY_DONE;
 }
 
+static void dwc3_omap_map_offset(struct dwc3_omap *omap)
+{
+	struct device_node	*node = omap->dev->of_node;
+
+	/*
+	 * Differentiate between OMAP5 and AM437x.
+	 *
+	 * For OMAP5(ES2.0) and AM437x wrapper revision is same, even
+	 * though there are changes in wrapper register offsets.
+	 *
+	 * Using dt compatible to differentiate AM437x.
+	 */
+	if (of_device_is_compatible(node, "ti,am437x-dwc3")) {
+		omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
+		omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
+		omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
+		omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
+		omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
+	}
+}
+
+static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap)
+{
+	u32			reg;
+	struct device_node	*node = omap->dev->of_node;
+	int			utmi_mode = 0;
+
+	reg = dwc3_omap_read_utmi_status(omap);
+
+	of_property_read_u32(node, "utmi-mode", &utmi_mode);
+
+	switch (utmi_mode) {
+	case DWC3_OMAP_UTMI_MODE_SW:
+		reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+		break;
+	case DWC3_OMAP_UTMI_MODE_HW:
+		reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+		break;
+	default:
+		dev_dbg(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode);
+	}
+
+	dwc3_omap_write_utmi_status(omap, reg);
+}
+
+static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
+{
+	u32			ret;
+	struct device_node	*node = omap->dev->of_node;
+	struct extcon_dev	*edev;
+
+	if (of_property_read_bool(node, "extcon")) {
+		edev = extcon_get_edev_by_phandle(omap->dev, 0);
+		if (IS_ERR(edev)) {
+			dev_vdbg(omap->dev, "couldn't get extcon device\n");
+			return -EPROBE_DEFER;
+		}
+
+		omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
+		ret = extcon_register_interest(&omap->extcon_vbus_dev,
+					       edev->name, "USB",
+					       &omap->vbus_nb);
+		if (ret < 0)
+			dev_vdbg(omap->dev, "failed to register notifier for USB\n");
+
+		omap->id_nb.notifier_call = dwc3_omap_id_notifier;
+		ret = extcon_register_interest(&omap->extcon_id_dev,
+					       edev->name, "USB-HOST",
+					       &omap->id_nb);
+		if (ret < 0)
+			dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n");
+
+		if (extcon_get_cable_state(edev, "USB") == true)
+			dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
+		if (extcon_get_cable_state(edev, "USB-HOST") == true)
+			dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
+	}
+
+	return 0;
+}
+
 static int dwc3_omap_probe(struct platform_device *pdev)
 {
 	struct device_node	*node = pdev->dev.of_node;
@@ -390,15 +466,11 @@
 	struct dwc3_omap	*omap;
 	struct resource		*res;
 	struct device		*dev = &pdev->dev;
-	struct extcon_dev	*edev;
 	struct regulator	*vbus_reg = NULL;
 
 	int			ret;
 	int			irq;
 
-	int			utmi_mode = 0;
-	int			x_major;
-
 	u32			reg;
 
 	void __iomem		*base;
@@ -448,58 +520,8 @@
 		goto err0;
 	}
 
-	reg = dwc3_omap_readl(omap->base, USBOTGSS_REVISION);
-	omap->revision = reg;
-	x_major = USBOTGSS_REVISION_XMAJOR(reg);
-
-	/* Differentiate between OMAP5 and AM437x */
-	switch (x_major) {
-	case USBOTGSS_REVISION_XMAJOR1:
-	case USBOTGSS_REVISION_XMAJOR2:
-		omap->irq_eoi_offset = 0;
-		omap->irq0_offset = 0;
-		omap->irqmisc_offset = 0;
-		omap->utmi_otg_offset = 0;
-		omap->debug_offset = 0;
-		break;
-	default:
-		/* Default to the latest revision */
-		omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
-		omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
-		omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
-		omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
-		omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
-		break;
-	}
-
-	/* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are
-	 * changes in wrapper registers, Using dt compatible for aegis
-	 */
-
-	if (of_device_is_compatible(node, "ti,am437x-dwc3")) {
-		omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
-		omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
-		omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
-		omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
-		omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
-	}
-
-	reg = dwc3_omap_read_utmi_status(omap);
-
-	of_property_read_u32(node, "utmi-mode", &utmi_mode);
-
-	switch (utmi_mode) {
-	case DWC3_OMAP_UTMI_MODE_SW:
-		reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-		break;
-	case DWC3_OMAP_UTMI_MODE_HW:
-		reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-		break;
-	default:
-		dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode);
-	}
-
-	dwc3_omap_write_utmi_status(omap, reg);
+	dwc3_omap_map_offset(omap);
+	dwc3_omap_set_utmi_mode(omap);
 
 	/* check the DMA Status */
 	reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
@@ -515,31 +537,9 @@
 
 	dwc3_omap_enable_irqs(omap);
 
-	if (of_property_read_bool(node, "extcon")) {
-		edev = extcon_get_edev_by_phandle(dev, 0);
-		if (IS_ERR(edev)) {
-			dev_vdbg(dev, "couldn't get extcon device\n");
-			ret = -EPROBE_DEFER;
-			goto err2;
-		}
-
-		omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
-		ret = extcon_register_interest(&omap->extcon_vbus_dev,
-			edev->name, "USB", &omap->vbus_nb);
-		if (ret < 0)
-			dev_vdbg(dev, "failed to register notifier for USB\n");
-		omap->id_nb.notifier_call = dwc3_omap_id_notifier;
-		ret = extcon_register_interest(&omap->extcon_id_dev, edev->name,
-					 "USB-HOST", &omap->id_nb);
-		if (ret < 0)
-			dev_vdbg(dev,
-				"failed to register notifier for USB-HOST\n");
-
-		if (extcon_get_cable_state(edev, "USB") == true)
-			dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
-		if (extcon_get_cable_state(edev, "USB-HOST") == true)
-			dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
-	}
+	ret = dwc3_omap_extcon_register(omap);
+	if (ret < 0)
+		goto err2;
 
 	ret = of_platform_populate(node, NULL, NULL, dev);
 	if (ret) {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index dab7927..349cacc 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1971,8 +1971,7 @@
 }
 
 static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
-		struct dwc3_ep *dep, const struct dwc3_event_depevt *event,
-		int start_new)
+		struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
 {
 	unsigned		status = 0;
 	int			clean_busy;
@@ -2039,7 +2038,7 @@
 			return;
 		}
 
-		dwc3_endpoint_transfer_complete(dwc, dep, event, 1);
+		dwc3_endpoint_transfer_complete(dwc, dep, event);
 		break;
 	case DWC3_DEPEVT_XFERINPROGRESS:
 		if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
@@ -2048,7 +2047,7 @@
 			return;
 		}
 
-		dwc3_endpoint_transfer_complete(dwc, dep, event, 0);
+		dwc3_endpoint_transfer_complete(dwc, dep, event);
 		break;
 	case DWC3_DEPEVT_XFERNOTREADY:
 		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index ba18e9c..5c822af 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -127,368 +127,7 @@
 	   a module parameter as well.
 	   If unsure, say 2.
 
-#
-# USB Peripheral Controller Support
-#
-# The order here is alphabetical, except that integrated controllers go
-# before discrete ones so they will be the initial/default value:
-#   - integrated/SOC controllers first
-#   - licensed IP used in both SOC and discrete versions
-#   - discrete ones (including all PCI-only controllers)
-#   - debug/dummy gadget+hcd is last.
-#
-menu "USB Peripheral Controller"
-
-#
-# Integrated controllers
-#
-
-config USB_AT91
-	tristate "Atmel AT91 USB Device Port"
-	depends on ARCH_AT91
-	help
-	   Many Atmel AT91 processors (such as the AT91RM2000) have a
-	   full speed USB Device Port with support for five configurable
-	   endpoints (plus endpoint zero).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "at91_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_LPC32XX
-	tristate "LPC32XX USB Peripheral Controller"
-	depends on ARCH_LPC32XX && I2C
-	select USB_ISP1301
-	help
-	   This option selects the USB device controller in the LPC32xx SoC.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "lpc32xx_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_ATMEL_USBA
-	tristate "Atmel USBA"
-	depends on AVR32 || ARCH_AT91
-	help
-	  USBA is the integrated high-speed USB Device controller on
-	  the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
-
-config USB_BCM63XX_UDC
-	tristate "Broadcom BCM63xx Peripheral Controller"
-	depends on BCM63XX
-	help
-	   Many Broadcom BCM63xx chipsets (such as the BCM6328) have a
-	   high speed USB Device Port with support for four fixed endpoints
-	   (plus endpoint zero).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "bcm63xx_udc".
-
-config USB_FSL_USB2
-	tristate "Freescale Highspeed USB DR Peripheral Controller"
-	depends on FSL_SOC || ARCH_MXC
-	select USB_FSL_MPH_DR_OF if OF
-	help
-	   Some of Freescale PowerPC and i.MX processors have a High Speed
-	   Dual-Role(DR) USB controller, which supports device mode.
-
-	   The number of programmable endpoints is different through
-	   SOC revisions.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "fsl_usb2_udc" and force
-	   all gadget drivers to also be dynamically linked.
-
-config USB_FUSB300
-	tristate "Faraday FUSB300 USB Peripheral Controller"
-	depends on !PHYS_ADDR_T_64BIT && HAS_DMA
-	help
-	   Faraday usb device controller FUSB300 driver
-
-config USB_FOTG210_UDC
-	depends on HAS_DMA
-	tristate "Faraday FOTG210 USB Peripheral Controller"
-	help
-	   Faraday USB2.0 OTG controller which can be configured as
-	   high speed or full speed USB device. This driver supppors
-	   Bulk Transfer so far.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "fotg210_udc".
-
-config USB_GR_UDC
-       tristate "Aeroflex Gaisler GRUSBDC USB Peripheral Controller Driver"
-       depends on HAS_DMA
-       help
-          Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB
-	  VHDL IP core library.
-
-config USB_OMAP
-	tristate "OMAP USB Device Controller"
-	depends on ARCH_OMAP1
-	depends on ISP1301_OMAP || !(MACH_OMAP_H2 || MACH_OMAP_H3)
-	help
-	   Many Texas Instruments OMAP processors have flexible full
-	   speed USB device controllers, with support for up to 30
-	   endpoints (plus endpoint zero).  This driver supports the
-	   controller in the OMAP 1611, and should work with controllers
-	   in other OMAP processors too, given minor tweaks.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "omap_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_PXA25X
-	tristate "PXA 25x or IXP 4xx"
-	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
-	help
-	   Intel's PXA 25x series XScale ARM-5TE processors include
-	   an integrated full speed USB 1.1 device controller.  The
-	   controller in the IXP 4xx series is register-compatible.
-
-	   It has fifteen fixed-function endpoints, as well as endpoint
-	   zero (for control transfers).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "pxa25x_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-# if there's only one gadget driver, using only two bulk endpoints,
-# don't waste memory for the other endpoints
-config USB_PXA25X_SMALL
-	depends on USB_PXA25X
-	bool
-	default n if USB_ETH_RNDIS
-	default y if USB_ZERO
-	default y if USB_ETH
-	default y if USB_G_SERIAL
-
-config USB_R8A66597
-	tristate "Renesas R8A66597 USB Peripheral Controller"
-	depends on HAS_DMA
-	help
-	   R8A66597 is a discrete USB host and peripheral controller chip that
-	   supports both full and high speed USB 2.0 data transfers.
-	   It has nine configurable endpoints, and endpoint zero.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "r8a66597_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_RENESAS_USBHS_UDC
-	tristate 'Renesas USBHS controller'
-	depends on USB_RENESAS_USBHS
-	help
-	   Renesas USBHS is a discrete USB host and peripheral controller chip
-	   that supports both full and high speed USB 2.0 data transfers.
-	   It has nine or more configurable endpoints, and endpoint zero.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "renesas_usbhs" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_PXA27X
-	tristate "PXA 27x"
-	help
-	   Intel's PXA 27x series XScale ARM v5TE processors include
-	   an integrated full speed USB 1.1 device controller.
-
-	   It has up to 23 endpoints, as well as endpoint zero (for
-	   control transfers).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "pxa27x_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_S3C2410
-	tristate "S3C2410 USB Device Controller"
-	depends on ARCH_S3C24XX
-	help
-	  Samsung's S3C2410 is an ARM-4 processor with an integrated
-	  full speed USB 1.1 device controller.  It has 4 configurable
-	  endpoints, as well as endpoint zero (for control transfers).
-
-	  This driver has been tested on the S3C2410, S3C2412, and
-	  S3C2440 processors.
-
-config USB_S3C2410_DEBUG
-	boolean "S3C2410 udc debug messages"
-	depends on USB_S3C2410
-
-config USB_S3C_HSUDC
-	tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller"
-	depends on ARCH_S3C24XX
-	help
-	  Samsung's S3C2416, S3C2443 and S3C2450 is an ARM9 based SoC
-	  integrated with dual speed USB 2.0 device controller. It has
-	  8 endpoints, as well as endpoint zero.
-
-	  This driver has been tested on S3C2416 and S3C2450 processors.
-
-config USB_MV_UDC
-	tristate "Marvell USB2.0 Device Controller"
-	depends on HAS_DMA
-	help
-	  Marvell Socs (including PXA and MMP series) include a high speed
-	  USB2.0 OTG controller, which can be configured as high speed or
-	  full speed USB peripheral.
-
-config USB_MV_U3D
-	depends on HAS_DMA
-	tristate "MARVELL PXA2128 USB 3.0 controller"
-	help
-	  MARVELL PXA2128 Processor series include a super speed USB3.0 device
-	  controller, which support super speed USB peripheral.
-
-#
-# Controllers available in both integrated and discrete versions
-#
-
-config USB_M66592
-	tristate "Renesas M66592 USB Peripheral Controller"
-	help
-	   M66592 is a discrete USB peripheral controller chip that
-	   supports both full and high speed USB 2.0 data transfers.
-	   It has seven configurable endpoints, and endpoint zero.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "m66592_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-#
-# Controllers available only in discrete form (and all PCI controllers)
-#
-
-config USB_AMD5536UDC
-	tristate "AMD5536 UDC"
-	depends on PCI
-	help
-	   The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
-	   It is a USB Highspeed DMA capable USB device controller. Beside ep0
-	   it provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
-	   The UDC port supports OTG operation, and may be used as a host port
-	   if it's not being used to implement peripheral or OTG roles.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "amd5536udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_FSL_QE
-	tristate "Freescale QE/CPM USB Device Controller"
-	depends on FSL_SOC && (QUICC_ENGINE || CPM)
-	help
-	   Some of Freescale PowerPC processors have a Full Speed
-	   QE/CPM2 USB controller, which support device mode with 4
-	   programmable endpoints. This driver supports the
-	   controller in the MPC8360 and MPC8272, and should work with
-	   controllers having QE or CPM2, given minor tweaks.
-
-	   Set CONFIG_USB_GADGET to "m" to build this driver as a
-	   dynamically linked module called "fsl_qe_udc".
-
-config USB_NET2272
-	tristate "PLX NET2272"
-	help
-	  PLX NET2272 is a USB peripheral controller which supports
-	  both full and high speed USB 2.0 data transfers.
-
-	  It has three configurable endpoints, as well as endpoint zero
-	  (for control transfer).
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "net2272" and force all
-	  gadget drivers to also be dynamically linked.
-
-config USB_NET2272_DMA
-	boolean "Support external DMA controller"
-	depends on USB_NET2272 && HAS_DMA
-	help
-	  The NET2272 part can optionally support an external DMA
-	  controller, but your board has to have support in the
-	  driver itself.
-
-	  If unsure, say "N" here.  The driver works fine in PIO mode.
-
-config USB_NET2280
-	tristate "NetChip 228x"
-	depends on PCI
-	help
-	   NetChip 2280 / 2282 is a PCI based USB peripheral controller which
-	   supports both full and high speed USB 2.0 data transfers.
-
-	   It has six configurable endpoints, as well as endpoint zero
-	   (for control transfers) and several endpoints with dedicated
-	   functions.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "net2280" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_GOKU
-	tristate "Toshiba TC86C001 'Goku-S'"
-	depends on PCI
-	help
-	   The Toshiba TC86C001 is a PCI device which includes controllers
-	   for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
-
-	   The device controller has three configurable (bulk or interrupt)
-	   endpoints, plus endpoint zero (for control transfers).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "goku_udc" and to force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_EG20T
-	tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
-	depends on PCI
-	help
-	  This is a USB device driver for EG20T PCH.
-	  EG20T PCH is the platform controller hub that is used in Intel's
-	  general embedded platform. EG20T PCH has USB device interface.
-	  Using this interface, it is able to access system devices connected
-	  to USB device.
-	  This driver enables USB device function.
-	  USB device is a USB peripheral controller which
-	  supports both full and high speed USB 2.0 data transfers.
-	  This driver supports both control transfer and bulk transfer modes.
-	  This driver dose not support interrupt transfer or isochronous
-	  transfer modes.
-
-	  This driver also can be used for LAPIS Semiconductor's ML7213 which is
-	  for IVI(In-Vehicle Infotainment) use.
-	  ML7831 is for general purpose use.
-	  ML7213/ML7831 is companion chip for Intel Atom E6xx series.
-	  ML7213/ML7831 is completely compatible for Intel EG20T PCH.
-
-#
-# LAST -- dummy/emulated controller
-#
-
-config USB_DUMMY_HCD
-	tristate "Dummy HCD (DEVELOPMENT)"
-	depends on USB=y || (USB=m && USB_GADGET=m)
-	help
-	  This host controller driver emulates USB, looping all data transfer
-	  requests back to a USB "gadget driver" in the same host.  The host
-	  side is the master; the gadget side is the slave.  Gadget drivers
-	  can be high, full, or low speed; and they have access to endpoints
-	  like those from NET2280, PXA2xx, or SA1100 hardware.
-
-	  This may help in some stages of creating a driver to embed in a
-	  Linux device, since it lets you debug several parts of the gadget
-	  driver without its hardware or drivers being involved.
-
-	  Since such a gadget side driver needs to interoperate with a host
-	  side Linux-USB device driver, this may help to debug both sides
-	  of a USB protocol stack.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "dummy_hcd" and force all
-	  gadget drivers to also be dynamically linked.
-
-# NOTE:  Please keep dummy_hcd LAST so that "real hardware" appears
-# first and will be selected by default.
-
-endmenu
+source "drivers/usb/gadget/udc/Kconfig"
 
 #
 # USB Gadget Drivers
@@ -714,466 +353,7 @@
 	  implemented in kernel space (for instance Ethernet, serial or
 	  mass storage) and other are implemented in user space.
 
-config USB_ZERO
-	tristate "Gadget Zero (DEVELOPMENT)"
-	select USB_LIBCOMPOSITE
-	select USB_F_SS_LB
-	help
-	  Gadget Zero is a two-configuration device.  It either sinks and
-	  sources bulk data; or it loops back a configurable number of
-	  transfers.  It also implements control requests, for "chapter 9"
-	  conformance.  The driver needs only two bulk-capable endpoints, so
-	  it can work on top of most device-side usb controllers.  It's
-	  useful for testing, and is also a working example showing how
-	  USB "gadget drivers" can be written.
-
-	  Make this be the first driver you try using on top of any new
-	  USB peripheral controller driver.  Then you can use host-side
-	  test software, like the "usbtest" driver, to put your hardware
-	  and its driver through a basic set of functional tests.
-
-	  Gadget Zero also works with the host-side "usb-skeleton" driver,
-	  and with many kinds of host-side test software.  You may need
-	  to tweak product and vendor IDs before host software knows about
-	  this device, and arrange to select an appropriate configuration.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_zero".
-
-config USB_ZERO_HNPTEST
-	boolean "HNP Test Device"
-	depends on USB_ZERO && USB_OTG
-	help
-	  You can configure this device to enumerate using the device
-	  identifiers of the USB-OTG test device.  That means that when
-	  this gadget connects to another OTG device, with this one using
-	  the "B-Peripheral" role, that device will use HNP to let this
-	  one serve as the USB host instead (in the "B-Host" role).
-
-config USB_AUDIO
-	tristate "Audio Gadget"
-	depends on SND
-	select USB_LIBCOMPOSITE
-	select SND_PCM
-	help
-	  This Gadget Audio driver is compatible with USB Audio Class
-	  specification 2.0. It implements 1 AudioControl interface,
-	  1 AudioStreaming Interface each for USB-OUT and USB-IN.
-	  Number of channels, sample rate and sample size can be
-	  specified as module parameters.
-	  This driver doesn't expect any real Audio codec to be present
-	  on the device - the audio streams are simply sinked to and
-	  sourced from a virtual ALSA sound card created. The user-space
-	  application may choose to do whatever it wants with the data
-	  received from the USB Host and choose to provide whatever it
-	  wants as audio data to the USB Host.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_audio".
-
-config GADGET_UAC1
-	bool "UAC 1.0 (Legacy)"
-	depends on USB_AUDIO
-	help
-	  If you instead want older UAC Spec-1.0 driver that also has audio
-	  paths hardwired to the Audio codec chip on-board and doesn't work
-	  without one.
-
-config USB_ETH
-	tristate "Ethernet Gadget (with CDC Ethernet support)"
-	depends on NET
-	select USB_LIBCOMPOSITE
-	select USB_U_ETHER
-	select USB_F_ECM
-	select USB_F_SUBSET
-	select CRC32
-	help
-	  This driver implements Ethernet style communication, in one of
-	  several ways:
-	  
-	   - The "Communication Device Class" (CDC) Ethernet Control Model.
-	     That protocol is often avoided with pure Ethernet adapters, in
-	     favor of simpler vendor-specific hardware, but is widely
-	     supported by firmware for smart network devices.
-
-	   - On hardware can't implement that protocol, a simple CDC subset
-	     is used, placing fewer demands on USB.
-
-	   - CDC Ethernet Emulation Model (EEM) is a newer standard that has
-	     a simpler interface that can be used by more USB hardware.
-
-	  RNDIS support is an additional option, more demanding than than
-	  subset.
-
-	  Within the USB device, this gadget driver exposes a network device
-	  "usbX", where X depends on what other networking devices you have.
-	  Treat it like a two-node Ethernet link:  host, and gadget.
-
-	  The Linux-USB host-side "usbnet" driver interoperates with this
-	  driver, so that deep I/O queues can be supported.  On 2.4 kernels,
-	  use "CDCEther" instead, if you're using the CDC option. That CDC
-	  mode should also interoperate with standard CDC Ethernet class
-	  drivers on other host operating systems.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_ether".
-
-config USB_ETH_RNDIS
-	bool "RNDIS support"
-	depends on USB_ETH
-	select USB_LIBCOMPOSITE
-	select USB_F_RNDIS
-	default y
-	help
-	   Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
-	   and Microsoft provides redistributable binary RNDIS drivers for
-	   older versions of Windows.
-
-	   If you say "y" here, the Ethernet gadget driver will try to provide
-	   a second device configuration, supporting RNDIS to talk to such
-	   Microsoft USB hosts.
-	   
-	   To make MS-Windows work with this, use Documentation/usb/linux.inf
-	   as the "driver info file".  For versions of MS-Windows older than
-	   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_EEM
-       bool "Ethernet Emulation Model (EEM) support"
-       depends on USB_ETH
-	select USB_LIBCOMPOSITE
-	select USB_F_EEM
-       default n
-       help
-         CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
-         and therefore can be supported by more hardware.  Technically ECM and
-         EEM are designed for different applications.  The ECM model extends
-         the network interface to the target (e.g. a USB cable modem), and the
-         EEM model is for mobile devices to communicate with hosts using
-         ethernet over USB.  For Linux gadgets, however, the interface with
-         the host is the same (a usbX device), so the differences are minimal.
-
-         If you say "y" here, the Ethernet gadget driver will use the EEM
-         protocol rather than ECM.  If unsure, say "n".
-
-config USB_G_NCM
-	tristate "Network Control Model (NCM) support"
-	depends on NET
-	select USB_LIBCOMPOSITE
-	select USB_U_ETHER
-	select USB_F_NCM
-	select CRC32
-	help
-	  This driver implements USB CDC NCM subclass standard. NCM is
-	  an advanced protocol for Ethernet encapsulation, allows grouping
-	  of several ethernet frames into one USB transfer and different
-	  alignment possibilities.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_ncm".
-
-config USB_GADGETFS
-	tristate "Gadget Filesystem"
-	help
-	  This driver provides a filesystem based API that lets user mode
-	  programs implement a single-configuration USB device, including
-	  endpoint I/O and control requests that don't relate to enumeration.
-	  All endpoints, transfer speeds, and transfer types supported by
-	  the hardware are available, through read() and write() calls.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "gadgetfs".
-
-config USB_FUNCTIONFS
-	tristate "Function Filesystem"
-	select USB_LIBCOMPOSITE
-	select USB_F_FS
-	select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
-	help
-	  The Function Filesystem (FunctionFS) lets one create USB
-	  composite functions in user space in the same way GadgetFS
-	  lets one create USB gadgets in user space.  This allows creation
-	  of composite gadgets such that some of the functions are
-	  implemented in kernel space (for instance Ethernet, serial or
-	  mass storage) and other are implemented in user space.
-
-	  If you say "y" or "m" here you will be able what kind of
-	  configurations the gadget will provide.
-
-	  Say "y" to link the driver statically, or "m" to build
-	  a dynamically linked module called "g_ffs".
-
-config USB_FUNCTIONFS_ETH
-	bool "Include configuration with CDC ECM (Ethernet)"
-	depends on USB_FUNCTIONFS && NET
-	select USB_U_ETHER
-	select USB_F_ECM
-	select USB_F_SUBSET
-	help
-	  Include a configuration with CDC ECM function (Ethernet) and the
-	  Function Filesystem.
-
-config USB_FUNCTIONFS_RNDIS
-	bool "Include configuration with RNDIS (Ethernet)"
-	depends on USB_FUNCTIONFS && NET
-	select USB_U_ETHER
-	select USB_F_RNDIS
-	help
-	  Include a configuration with RNDIS function (Ethernet) and the Filesystem.
-
-config USB_FUNCTIONFS_GENERIC
-	bool "Include 'pure' configuration"
-	depends on USB_FUNCTIONFS
-	help
-	  Include a configuration with the Function Filesystem alone with
-	  no Ethernet interface.
-
-config USB_MASS_STORAGE
-	tristate "Mass Storage Gadget"
-	depends on BLOCK
-	select USB_LIBCOMPOSITE
-	select USB_F_MASS_STORAGE
-	help
-	  The Mass Storage Gadget acts as a USB Mass Storage disk drive.
-	  As its storage repository it can use a regular file or a block
-	  device (in much the same way as the "loop" device driver),
-	  specified as a module parameter or sysfs option.
-
-	  This driver is a replacement for now removed File-backed
-	  Storage Gadget (g_file_storage).
-
-	  Say "y" to link the driver statically, or "m" to build
-	  a dynamically linked module called "g_mass_storage".
-
-config USB_GADGET_TARGET
-	tristate "USB Gadget Target Fabric Module"
-	depends on TARGET_CORE
-	select USB_LIBCOMPOSITE
-	help
-	  This fabric is an USB gadget. Two USB protocols are supported that is
-	  BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is
-	  advertised on alternative interface 0 (primary) and UAS is on
-	  alternative interface 1. Both protocols can work on USB2.0 and USB3.0.
-	  UAS utilizes the USB 3.0 feature called streams support.
-
-config USB_G_SERIAL
-	tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
-	depends on TTY
-	select USB_U_SERIAL
-	select USB_F_ACM
-	select USB_F_SERIAL
-	select USB_F_OBEX
-	select USB_LIBCOMPOSITE
-	help
-	  The Serial Gadget talks to the Linux-USB generic serial driver.
-	  This driver supports a CDC-ACM module option, which can be used
-	  to interoperate with MS-Windows hosts or with the Linux-USB
-	  "cdc-acm" driver.
-
-	  This driver also supports a CDC-OBEX option.  You will need a
-	  user space OBEX server talking to /dev/ttyGS*, since the kernel
-	  itself doesn't implement the OBEX protocol.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_serial".
-
-	  For more information, see Documentation/usb/gadget_serial.txt
-	  which includes instructions and a "driver info file" needed to
-	  make MS-Windows work with CDC ACM.
-
-config USB_MIDI_GADGET
-	tristate "MIDI Gadget"
-	depends on SND
-	select USB_LIBCOMPOSITE
-	select SND_RAWMIDI
-	help
-	  The MIDI Gadget acts as a USB Audio device, with one MIDI
-	  input and one MIDI output. These MIDI jacks appear as
-	  a sound "card" in the ALSA sound system. Other MIDI
-	  connections can then be made on the gadget system, using
-	  ALSA's aconnect utility etc.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_midi".
-
-config USB_G_PRINTER
-	tristate "Printer Gadget"
-	select USB_LIBCOMPOSITE
-	help
-	  The Printer Gadget channels data between the USB host and a
-	  userspace program driving the print engine. The user space
-	  program reads and writes the device file /dev/g_printer to
-	  receive or send printer data. It can use ioctl calls to
-	  the device file to get or set printer status.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_printer".
-
-	  For more information, see Documentation/usb/gadget_printer.txt
-	  which includes sample code for accessing the device file.
-
-if TTY
-
-config USB_CDC_COMPOSITE
-	tristate "CDC Composite Device (Ethernet and ACM)"
-	depends on NET
-	select USB_LIBCOMPOSITE
-	select USB_U_SERIAL
-	select USB_U_ETHER
-	select USB_F_ACM
-	select USB_F_ECM
-	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.
-
-config USB_G_NOKIA
-	tristate "Nokia composite gadget"
-	depends on PHONET
-	select USB_LIBCOMPOSITE
-	select USB_U_SERIAL
-	select USB_U_ETHER
-	select USB_F_ACM
-	select USB_F_OBEX
-	select USB_F_PHONET
-	select USB_F_ECM
-	help
-	  The Nokia composite gadget provides support for acm, obex
-	  and phonet in only one composite gadget driver.
-
-	  It's only really useful for N900 hardware. If you're building
-	  a kernel for N900, say Y or M here. If unsure, say N.
-
-config USB_G_ACM_MS
-	tristate "CDC Composite Device (ACM and mass storage)"
-	depends on BLOCK
-	select USB_LIBCOMPOSITE
-	select USB_U_SERIAL
-	select USB_F_ACM
-	select USB_F_MASS_STORAGE
-	help
-	  This driver provides two functions in one configuration:
-	  a mass storage, and a CDC ACM (serial port) link.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_acm_ms".
-
-config USB_G_MULTI
-	tristate "Multifunction Composite Gadget"
-	depends on BLOCK && NET
-	select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
-	select USB_LIBCOMPOSITE
-	select USB_U_SERIAL
-	select USB_U_ETHER
-	select USB_F_ACM
-	select USB_F_MASS_STORAGE
-	help
-	  The Multifunction Composite Gadget provides Ethernet (RNDIS
-	  and/or CDC Ethernet), mass storage and ACM serial link
-	  interfaces.
-
-	  You will be asked to choose which of the two configurations is
-	  to be available in the gadget.  At least one configuration must
-	  be chosen to make the gadget usable.  Selecting more than one
-	  configuration will prevent Windows from automatically detecting
-	  the gadget as a composite gadget, so an INF file will be needed to
-	  use the gadget.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_multi".
-
-config USB_G_MULTI_RNDIS
-	bool "RNDIS + CDC Serial + Storage configuration"
-	depends on USB_G_MULTI
-	select USB_F_RNDIS
-	default y
-	help
-	  This option enables a configuration with RNDIS, CDC Serial and
-	  Mass Storage functions available in the Multifunction Composite
-	  Gadget.  This is the configuration dedicated for Windows since RNDIS
-	  is Microsoft's protocol.
-
-	  If unsure, say "y".
-
-config USB_G_MULTI_CDC
-	bool "CDC Ethernet + CDC Serial + Storage configuration"
-	depends on USB_G_MULTI
-	default n
-	select USB_F_ECM
-	help
-	  This option enables a configuration with CDC Ethernet (ECM), CDC
-	  Serial and Mass Storage functions available in the Multifunction
-	  Composite Gadget.
-
-	  If unsure, say "y".
-
-endif # TTY
-
-config USB_G_HID
-	tristate "HID Gadget"
-	select USB_LIBCOMPOSITE
-	help
-	  The HID gadget driver provides generic emulation of USB
-	  Human Interface Devices (HID).
-
-	  For more information, see Documentation/usb/gadget_hid.txt which
-	  includes sample code for accessing the device files.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_hid".
-
-# Standalone / single function gadgets
-config USB_G_DBGP
-	tristate "EHCI Debug Device Gadget"
-	depends on TTY
-	select USB_LIBCOMPOSITE
-	help
-	  This gadget emulates an EHCI Debug device. This is useful when you want
-	  to interact with an EHCI Debug Port.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_dbgp".
-
-if USB_G_DBGP
-choice
-	prompt "EHCI Debug Device mode"
-	default USB_G_DBGP_SERIAL
-
-config USB_G_DBGP_PRINTK
-	depends on USB_G_DBGP
-	bool "printk"
-	help
-	  Directly printk() received data. No interaction.
-
-config USB_G_DBGP_SERIAL
-	depends on USB_G_DBGP
-	select USB_U_SERIAL
-	bool "serial"
-	help
-	  Userland can interact using /dev/ttyGSxxx.
-endchoice
-endif
-
-# put drivers that need isochronous transfer support (for audio
-# or video class gadget drivers), or specific hardware, here.
-config USB_G_WEBCAM
-	tristate "USB Webcam Gadget"
-	depends on VIDEO_DEV
-	select USB_LIBCOMPOSITE
-	select VIDEOBUF2_VMALLOC
-	help
-	  The Webcam Gadget acts as a composite USB Audio and Video Class
-	  device. It provides a userspace API to process UVC control requests
-	  and stream video data to the host.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_webcam".
+source "drivers/usb/gadget/legacy/Kconfig"
 
 endchoice
 
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 49514ea..a186afe 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -1,105 +1,12 @@
 #
 # USB peripheral controller drivers
 #
-ccflags-$(CONFIG_USB_GADGET_DEBUG)	:= -DDEBUG
-ccflags-$(CONFIG_USB_GADGET_VERBOSE)	+= -DVERBOSE_DEBUG
+subdir-ccflags-$(CONFIG_USB_GADGET_DEBUG)	:= -DDEBUG
+subdir-ccflags-$(CONFIG_USB_GADGET_VERBOSE)	+= -DVERBOSE_DEBUG
+ccflags-y				+= -I$(PWD)/drivers/usb/gadget/udc
 
-obj-$(CONFIG_USB_GADGET)	+= udc-core.o
 obj-$(CONFIG_USB_LIBCOMPOSITE)	+= libcomposite.o
 libcomposite-y			:= usbstring.o config.o epautoconf.o
 libcomposite-y			+= composite.o functions.o configfs.o u_f.o
-obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
-obj-$(CONFIG_USB_NET2272)	+= net2272.o
-obj-$(CONFIG_USB_NET2280)	+= net2280.o
-obj-$(CONFIG_USB_AMD5536UDC)	+= amd5536udc.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
-obj-$(CONFIG_USB_S3C2410)	+= s3c2410_udc.o
-obj-$(CONFIG_USB_AT91)		+= at91_udc.o
-obj-$(CONFIG_USB_ATMEL_USBA)	+= atmel_usba_udc.o
-obj-$(CONFIG_USB_BCM63XX_UDC)	+= bcm63xx_udc.o
-obj-$(CONFIG_USB_FSL_USB2)	+= fsl_usb2_udc.o
-fsl_usb2_udc-y			:= fsl_udc_core.o
-fsl_usb2_udc-$(CONFIG_ARCH_MXC)	+= fsl_mxc_udc.o
-obj-$(CONFIG_USB_M66592)	+= m66592-udc.o
-obj-$(CONFIG_USB_R8A66597)	+= r8a66597-udc.o
-obj-$(CONFIG_USB_FSL_QE)	+= fsl_qe_udc.o
-obj-$(CONFIG_USB_S3C_HSUDC)	+= s3c-hsudc.o
-obj-$(CONFIG_USB_LPC32XX)	+= lpc32xx_udc.o
-obj-$(CONFIG_USB_EG20T)		+= pch_udc.o
-obj-$(CONFIG_USB_MV_UDC)	+= mv_udc.o
-mv_udc-y			:= mv_udc_core.o
-obj-$(CONFIG_USB_FUSB300)	+= fusb300_udc.o
-obj-$(CONFIG_USB_FOTG210_UDC)	+= fotg210-udc.o
-obj-$(CONFIG_USB_MV_U3D)	+= mv_u3d_core.o
-obj-$(CONFIG_USB_GR_UDC)	+= gr_udc.o
 
-# USB Functions
-usb_f_acm-y			:= f_acm.o
-obj-$(CONFIG_USB_F_ACM)		+= usb_f_acm.o
-usb_f_ss_lb-y			:= f_loopback.o f_sourcesink.o
-obj-$(CONFIG_USB_F_SS_LB)	+= usb_f_ss_lb.o
-obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o
-usb_f_serial-y			:= f_serial.o
-obj-$(CONFIG_USB_F_SERIAL)	+= usb_f_serial.o
-usb_f_obex-y			:= f_obex.o
-obj-$(CONFIG_USB_F_OBEX)	+= usb_f_obex.o
-obj-$(CONFIG_USB_U_ETHER)	+= u_ether.o
-usb_f_ncm-y			:= f_ncm.o
-obj-$(CONFIG_USB_F_NCM)		+= usb_f_ncm.o
-usb_f_ecm-y			:= f_ecm.o
-obj-$(CONFIG_USB_F_ECM)		+= usb_f_ecm.o
-usb_f_phonet-y			:= f_phonet.o
-obj-$(CONFIG_USB_F_PHONET)	+= usb_f_phonet.o
-usb_f_eem-y			:= f_eem.o
-obj-$(CONFIG_USB_F_EEM)		+= usb_f_eem.o
-usb_f_ecm_subset-y		:= f_subset.o
-obj-$(CONFIG_USB_F_SUBSET)	+= usb_f_ecm_subset.o
-usb_f_rndis-y			:= f_rndis.o rndis.o
-obj-$(CONFIG_USB_F_RNDIS)	+= usb_f_rndis.o
-usb_f_mass_storage-y		:= f_mass_storage.o storage_common.o
-obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
-usb_f_fs-y			:= f_fs.o
-obj-$(CONFIG_USB_F_FS)		+= usb_f_fs.o
-
-#
-# USB gadget drivers
-#
-g_zero-y			:= zero.o
-g_audio-y			:= audio.o
-g_ether-y			:= ether.o
-g_serial-y			:= serial.o
-g_midi-y			:= gmidi.o
-gadgetfs-y			:= inode.o
-g_mass_storage-y		:= mass_storage.o
-g_printer-y			:= printer.o
-g_cdc-y				:= cdc2.o
-g_multi-y			:= multi.o
-g_hid-y				:= hid.o
-g_dbgp-y			:= dbgp.o
-g_nokia-y			:= nokia.o
-g_webcam-y			:= webcam.o
-g_ncm-y				:= ncm.o
-g_acm_ms-y			:= acm_ms.o
-g_tcm_usb_gadget-y		:= tcm_usb_gadget.o
-
-obj-$(CONFIG_USB_ZERO)		+= g_zero.o
-obj-$(CONFIG_USB_AUDIO)		+= g_audio.o
-obj-$(CONFIG_USB_ETH)		+= g_ether.o
-obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
-obj-$(CONFIG_USB_FUNCTIONFS)	+= g_ffs.o
-obj-$(CONFIG_USB_MASS_STORAGE)	+= g_mass_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
-obj-$(CONFIG_USB_G_HID)		+= g_hid.o
-obj-$(CONFIG_USB_G_DBGP)	+= g_dbgp.o
-obj-$(CONFIG_USB_G_MULTI)	+= g_multi.o
-obj-$(CONFIG_USB_G_NOKIA)	+= g_nokia.o
-obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o
-obj-$(CONFIG_USB_G_NCM)		+= g_ncm.o
-obj-$(CONFIG_USB_G_ACM_MS)	+= g_acm_ms.o
-obj-$(CONFIG_USB_GADGET_TARGET)	+= tcm_usb_gadget.o
+obj-$(CONFIG_USB_GADGET)	+= udc/ function/ legacy/
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index f801519..6935a82 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1956,6 +1956,7 @@
 	}
 	if (cdev->req) {
 		kfree(cdev->req->buf);
+		usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
 		usb_ep_free_request(cdev->gadget->ep0, cdev->req);
 	}
 	cdev->next_string_id = 0;
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 9714214..811c2c7 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1021,12 +1021,10 @@
 
 	if (page[len - 1] == '\n' || page[len - 1] == '\0')
 		--len;
-	new_data = kzalloc(len, GFP_KERNEL);
+	new_data = kmemdup(page, len, GFP_KERNEL);
 	if (!new_data)
 		return -ENOMEM;
 
-	memcpy(new_data, page, len);
-
 	if (desc->opts_mutex)
 		mutex_lock(desc->opts_mutex);
 	kfree(ext_prop->data);
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile
new file mode 100644
index 0000000..6d91f21
--- /dev/null
+++ b/drivers/usb/gadget/function/Makefile
@@ -0,0 +1,34 @@
+#
+# USB peripheral controller drivers
+#
+
+ccflags-y			:= -I$(PWD)/drivers/usb/gadget/
+ccflags-y			+= -I$(PWD)/drivers/usb/gadget/udc/
+
+# USB Functions
+usb_f_acm-y			:= f_acm.o
+obj-$(CONFIG_USB_F_ACM)		+= usb_f_acm.o
+usb_f_ss_lb-y			:= f_loopback.o f_sourcesink.o
+obj-$(CONFIG_USB_F_SS_LB)	+= usb_f_ss_lb.o
+obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o
+usb_f_serial-y			:= f_serial.o
+obj-$(CONFIG_USB_F_SERIAL)	+= usb_f_serial.o
+usb_f_obex-y			:= f_obex.o
+obj-$(CONFIG_USB_F_OBEX)	+= usb_f_obex.o
+obj-$(CONFIG_USB_U_ETHER)	+= u_ether.o
+usb_f_ncm-y			:= f_ncm.o
+obj-$(CONFIG_USB_F_NCM)		+= usb_f_ncm.o
+usb_f_ecm-y			:= f_ecm.o
+obj-$(CONFIG_USB_F_ECM)		+= usb_f_ecm.o
+usb_f_phonet-y			:= f_phonet.o
+obj-$(CONFIG_USB_F_PHONET)	+= usb_f_phonet.o
+usb_f_eem-y			:= f_eem.o
+obj-$(CONFIG_USB_F_EEM)		+= usb_f_eem.o
+usb_f_ecm_subset-y		:= f_subset.o
+obj-$(CONFIG_USB_F_SUBSET)	+= usb_f_ecm_subset.o
+usb_f_rndis-y			:= f_rndis.o rndis.o
+obj-$(CONFIG_USB_F_RNDIS)	+= usb_f_rndis.o
+usb_f_mass_storage-y		:= f_mass_storage.o storage_common.o
+obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
+usb_f_fs-y			:= f_fs.o
+obj-$(CONFIG_USB_F_FS)		+= usb_f_fs.o
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/function/f_acm.c
similarity index 100%
rename from drivers/usb/gadget/f_acm.c
rename to drivers/usb/gadget/function/f_acm.c
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c
similarity index 100%
rename from drivers/usb/gadget/f_ecm.c
rename to drivers/usb/gadget/function/f_ecm.c
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/function/f_eem.c
similarity index 97%
rename from drivers/usb/gadget/f_eem.c
rename to drivers/usb/gadget/function/f_eem.c
index d61c11d..4d8b236 100644
--- a/drivers/usb/gadget/f_eem.c
+++ b/drivers/usb/gadget/function/f_eem.c
@@ -355,20 +355,18 @@
 	int		padlen = 0;
 	u16		len = skb->len;
 
-	if (!skb_cloned(skb)) {
-		int headroom = skb_headroom(skb);
-		int tailroom = skb_tailroom(skb);
+	int headroom = skb_headroom(skb);
+	int tailroom = skb_tailroom(skb);
 
-		/* When (len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) is 0,
-		 * stick two bytes of zero-length EEM packet on the end.
-		 */
-		if (((len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) == 0)
-			padlen += 2;
+	/* When (len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) is 0,
+	 * stick two bytes of zero-length EEM packet on the end.
+	 */
+	if (((len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) == 0)
+		padlen += 2;
 
-		if ((tailroom >= (ETH_FCS_LEN + padlen)) &&
-				(headroom >= EEM_HLEN))
-			goto done;
-	}
+	if ((tailroom >= (ETH_FCS_LEN + padlen)) &&
+			(headroom >= EEM_HLEN) && !skb_cloned(skb))
+		goto done;
 
 	skb2 = skb_copy_expand(skb, EEM_HLEN, ETH_FCS_LEN + padlen, GFP_ATOMIC);
 	dev_kfree_skb_any(skb);
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/function/f_fs.c
similarity index 87%
rename from drivers/usb/gadget/f_fs.c
rename to drivers/usb/gadget/function/f_fs.c
index 8598c27..dc30adf 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -34,6 +34,7 @@
 
 #include "u_fs.h"
 #include "u_f.h"
+#include "u_os_desc.h"
 #include "configfs.h"
 
 #define FUNCTIONFS_MAGIC	0xa647361 /* Chosen by a honest dice roll ;) */
@@ -1646,13 +1647,22 @@
 	FFS_DESCRIPTOR, FFS_INTERFACE, FFS_STRING, FFS_ENDPOINT
 };
 
+enum ffs_os_desc_type {
+	FFS_OS_DESC, FFS_OS_DESC_EXT_COMPAT, FFS_OS_DESC_EXT_PROP
+};
+
 typedef int (*ffs_entity_callback)(enum ffs_entity_type entity,
 				   u8 *valuep,
 				   struct usb_descriptor_header *desc,
 				   void *priv);
 
-static int __must_check ffs_do_desc(char *data, unsigned len,
-				    ffs_entity_callback entity, void *priv)
+typedef int (*ffs_os_desc_callback)(enum ffs_os_desc_type entity,
+				    struct usb_os_desc_header *h, void *data,
+				    unsigned len, void *priv);
+
+static int __must_check ffs_do_single_desc(char *data, unsigned len,
+					   ffs_entity_callback entity,
+					   void *priv)
 {
 	struct usb_descriptor_header *_ds = (void *)data;
 	u8 length;
@@ -1804,7 +1814,7 @@
 		if (!data)
 			return _len - len;
 
-		ret = ffs_do_desc(data, len, entity, priv);
+		ret = ffs_do_single_desc(data, len, entity, priv);
 		if (unlikely(ret < 0)) {
 			pr_debug("%s returns %d\n", __func__, ret);
 			return ret;
@@ -1857,11 +1867,191 @@
 	return 0;
 }
 
+static int __ffs_do_os_desc_header(enum ffs_os_desc_type *next_type,
+				   struct usb_os_desc_header *desc)
+{
+	u16 bcd_version = le16_to_cpu(desc->bcdVersion);
+	u16 w_index = le16_to_cpu(desc->wIndex);
+
+	if (bcd_version != 1) {
+		pr_vdebug("unsupported os descriptors version: %d",
+			  bcd_version);
+		return -EINVAL;
+	}
+	switch (w_index) {
+	case 0x4:
+		*next_type = FFS_OS_DESC_EXT_COMPAT;
+		break;
+	case 0x5:
+		*next_type = FFS_OS_DESC_EXT_PROP;
+		break;
+	default:
+		pr_vdebug("unsupported os descriptor type: %d", w_index);
+		return -EINVAL;
+	}
+
+	return sizeof(*desc);
+}
+
+/*
+ * Process all extended compatibility/extended property descriptors
+ * of a feature descriptor
+ */
+static int __must_check ffs_do_single_os_desc(char *data, unsigned len,
+					      enum ffs_os_desc_type type,
+					      u16 feature_count,
+					      ffs_os_desc_callback entity,
+					      void *priv,
+					      struct usb_os_desc_header *h)
+{
+	int ret;
+	const unsigned _len = len;
+
+	ENTER();
+
+	/* loop over all ext compat/ext prop descriptors */
+	while (feature_count--) {
+		ret = entity(type, h, data, len, priv);
+		if (unlikely(ret < 0)) {
+			pr_debug("bad OS descriptor, type: %d\n", type);
+			return ret;
+		}
+		data += ret;
+		len -= ret;
+	}
+	return _len - len;
+}
+
+/* Process a number of complete Feature Descriptors (Ext Compat or Ext Prop) */
+static int __must_check ffs_do_os_descs(unsigned count,
+					char *data, unsigned len,
+					ffs_os_desc_callback entity, void *priv)
+{
+	const unsigned _len = len;
+	unsigned long num = 0;
+
+	ENTER();
+
+	for (num = 0; num < count; ++num) {
+		int ret;
+		enum ffs_os_desc_type type;
+		u16 feature_count;
+		struct usb_os_desc_header *desc = (void *)data;
+
+		if (len < sizeof(*desc))
+			return -EINVAL;
+
+		/*
+		 * Record "descriptor" entity.
+		 * Process dwLength, bcdVersion, wIndex, get b/wCount.
+		 * Move the data pointer to the beginning of extended
+		 * compatibilities proper or extended properties proper
+		 * portions of the data
+		 */
+		if (le32_to_cpu(desc->dwLength) > len)
+			return -EINVAL;
+
+		ret = __ffs_do_os_desc_header(&type, desc);
+		if (unlikely(ret < 0)) {
+			pr_debug("entity OS_DESCRIPTOR(%02lx); ret = %d\n",
+				 num, ret);
+			return ret;
+		}
+		/*
+		 * 16-bit hex "?? 00" Little Endian looks like 8-bit hex "??"
+		 */
+		feature_count = le16_to_cpu(desc->wCount);
+		if (type == FFS_OS_DESC_EXT_COMPAT &&
+		    (feature_count > 255 || desc->Reserved))
+				return -EINVAL;
+		len -= ret;
+		data += ret;
+
+		/*
+		 * Process all function/property descriptors
+		 * of this Feature Descriptor
+		 */
+		ret = ffs_do_single_os_desc(data, len, type,
+					    feature_count, entity, priv, desc);
+		if (unlikely(ret < 0)) {
+			pr_debug("%s returns %d\n", __func__, ret);
+			return ret;
+		}
+
+		len -= ret;
+		data += ret;
+	}
+	return _len - len;
+}
+
+/**
+ * Validate contents of the buffer from userspace related to OS descriptors.
+ */
+static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
+				 struct usb_os_desc_header *h, void *data,
+				 unsigned len, void *priv)
+{
+	struct ffs_data *ffs = priv;
+	u8 length;
+
+	ENTER();
+
+	switch (type) {
+	case FFS_OS_DESC_EXT_COMPAT: {
+		struct usb_ext_compat_desc *d = data;
+		int i;
+
+		if (len < sizeof(*d) ||
+		    d->bFirstInterfaceNumber >= ffs->interfaces_count ||
+		    d->Reserved1)
+			return -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i)
+			if (d->Reserved2[i])
+				return -EINVAL;
+
+		length = sizeof(struct usb_ext_compat_desc);
+	}
+		break;
+	case FFS_OS_DESC_EXT_PROP: {
+		struct usb_ext_prop_desc *d = data;
+		u32 type, pdl;
+		u16 pnl;
+
+		if (len < sizeof(*d) || h->interface >= ffs->interfaces_count)
+			return -EINVAL;
+		length = le32_to_cpu(d->dwSize);
+		type = le32_to_cpu(d->dwPropertyDataType);
+		if (type < USB_EXT_PROP_UNICODE ||
+		    type > USB_EXT_PROP_UNICODE_MULTI) {
+			pr_vdebug("unsupported os descriptor property type: %d",
+				  type);
+			return -EINVAL;
+		}
+		pnl = le16_to_cpu(d->wPropertyNameLength);
+		pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl));
+		if (length != 14 + pnl + pdl) {
+			pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n",
+				  length, pnl, pdl, type);
+			return -EINVAL;
+		}
+		++ffs->ms_os_descs_ext_prop_count;
+		/* property name reported to the host as "WCHAR"s */
+		ffs->ms_os_descs_ext_prop_name_len += pnl * 2;
+		ffs->ms_os_descs_ext_prop_data_len += pdl;
+	}
+		break;
+	default:
+		pr_vdebug("unknown descriptor: %d\n", type);
+		return -EINVAL;
+	}
+	return length;
+}
+
 static int __ffs_data_got_descs(struct ffs_data *ffs,
 				char *const _data, size_t len)
 {
 	char *data = _data, *raw_descs;
-	unsigned counts[3], flags;
+	unsigned os_descs_count = 0, counts[3], flags;
 	int ret = -EINVAL, i;
 
 	ENTER();
@@ -1879,7 +2069,8 @@
 		flags = get_unaligned_le32(data + 8);
 		if (flags & ~(FUNCTIONFS_HAS_FS_DESC |
 			      FUNCTIONFS_HAS_HS_DESC |
-			      FUNCTIONFS_HAS_SS_DESC)) {
+			      FUNCTIONFS_HAS_SS_DESC |
+			      FUNCTIONFS_HAS_MS_OS_DESC)) {
 			ret = -ENOSYS;
 			goto error;
 		}
@@ -1902,6 +2093,11 @@
 			len  -= 4;
 		}
 	}
+	if (flags & (1 << i)) {
+		os_descs_count = get_unaligned_le32(data);
+		data += 4;
+		len -= 4;
+	};
 
 	/* Read descriptors */
 	raw_descs = data;
@@ -1915,6 +2111,14 @@
 		data += ret;
 		len  -= ret;
 	}
+	if (os_descs_count) {
+		ret = ffs_do_os_descs(os_descs_count, data, len,
+				      __ffs_data_do_os_desc, ffs);
+		if (ret < 0)
+			goto error;
+		data += ret;
+		len -= ret;
+	}
 
 	if (raw_descs == data || len) {
 		ret = -EINVAL;
@@ -1927,6 +2131,7 @@
 	ffs->fs_descs_count	= counts[0];
 	ffs->hs_descs_count	= counts[1];
 	ffs->ss_descs_count	= counts[2];
+	ffs->ms_os_descs_count	= os_descs_count;
 
 	return 0;
 
@@ -2268,6 +2473,85 @@
 	return 0;
 }
 
+static int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type,
+				      struct usb_os_desc_header *h, void *data,
+				      unsigned len, void *priv)
+{
+	struct ffs_function *func = priv;
+	u8 length = 0;
+
+	switch (type) {
+	case FFS_OS_DESC_EXT_COMPAT: {
+		struct usb_ext_compat_desc *desc = data;
+		struct usb_os_desc_table *t;
+
+		t = &func->function.os_desc_table[desc->bFirstInterfaceNumber];
+		t->if_id = func->interfaces_nums[desc->bFirstInterfaceNumber];
+		memcpy(t->os_desc->ext_compat_id, &desc->CompatibleID,
+		       ARRAY_SIZE(desc->CompatibleID) +
+		       ARRAY_SIZE(desc->SubCompatibleID));
+		length = sizeof(*desc);
+	}
+		break;
+	case FFS_OS_DESC_EXT_PROP: {
+		struct usb_ext_prop_desc *desc = data;
+		struct usb_os_desc_table *t;
+		struct usb_os_desc_ext_prop *ext_prop;
+		char *ext_prop_name;
+		char *ext_prop_data;
+
+		t = &func->function.os_desc_table[h->interface];
+		t->if_id = func->interfaces_nums[h->interface];
+
+		ext_prop = func->ffs->ms_os_descs_ext_prop_avail;
+		func->ffs->ms_os_descs_ext_prop_avail += sizeof(*ext_prop);
+
+		ext_prop->type = le32_to_cpu(desc->dwPropertyDataType);
+		ext_prop->name_len = le16_to_cpu(desc->wPropertyNameLength);
+		ext_prop->data_len = le32_to_cpu(*(u32 *)
+			usb_ext_prop_data_len_ptr(data, ext_prop->name_len));
+		length = ext_prop->name_len + ext_prop->data_len + 14;
+
+		ext_prop_name = func->ffs->ms_os_descs_ext_prop_name_avail;
+		func->ffs->ms_os_descs_ext_prop_name_avail +=
+			ext_prop->name_len;
+
+		ext_prop_data = func->ffs->ms_os_descs_ext_prop_data_avail;
+		func->ffs->ms_os_descs_ext_prop_data_avail +=
+			ext_prop->data_len;
+		memcpy(ext_prop_data,
+		       usb_ext_prop_data_ptr(data, ext_prop->name_len),
+		       ext_prop->data_len);
+		/* unicode data reported to the host as "WCHAR"s */
+		switch (ext_prop->type) {
+		case USB_EXT_PROP_UNICODE:
+		case USB_EXT_PROP_UNICODE_ENV:
+		case USB_EXT_PROP_UNICODE_LINK:
+		case USB_EXT_PROP_UNICODE_MULTI:
+			ext_prop->data_len *= 2;
+			break;
+		}
+		ext_prop->data = ext_prop_data;
+
+		memcpy(ext_prop_name, usb_ext_prop_name_ptr(data),
+		       ext_prop->name_len);
+		/* property name reported to the host as "WCHAR"s */
+		ext_prop->name_len *= 2;
+		ext_prop->name = ext_prop_name;
+
+		t->os_desc->ext_prop_len +=
+			ext_prop->name_len + ext_prop->data_len + 14;
+		++t->os_desc->ext_prop_count;
+		list_add_tail(&ext_prop->entry, &t->os_desc->ext_prop);
+	}
+		break;
+	default:
+		pr_vdebug("unknown descriptor: %d\n", type);
+	}
+
+	return length;
+}
+
 static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
 						struct usb_configuration *c)
 {
@@ -2329,7 +2613,7 @@
 	const int super = gadget_is_superspeed(func->gadget) &&
 		func->ffs->ss_descs_count;
 
-	int fs_len, hs_len, ret;
+	int fs_len, hs_len, ss_len, ret, i;
 
 	/* Make it a single chunk, less management later on */
 	vla_group(d);
@@ -2341,6 +2625,18 @@
 	vla_item_with_sz(d, struct usb_descriptor_header *, ss_descs,
 		super ? ffs->ss_descs_count + 1 : 0);
 	vla_item_with_sz(d, short, inums, ffs->interfaces_count);
+	vla_item_with_sz(d, struct usb_os_desc_table, os_desc_table,
+			 c->cdev->use_os_string ? ffs->interfaces_count : 0);
+	vla_item_with_sz(d, char[16], ext_compat,
+			 c->cdev->use_os_string ? ffs->interfaces_count : 0);
+	vla_item_with_sz(d, struct usb_os_desc, os_desc,
+			 c->cdev->use_os_string ? ffs->interfaces_count : 0);
+	vla_item_with_sz(d, struct usb_os_desc_ext_prop, ext_prop,
+			 ffs->ms_os_descs_ext_prop_count);
+	vla_item_with_sz(d, char, ext_prop_name,
+			 ffs->ms_os_descs_ext_prop_name_len);
+	vla_item_with_sz(d, char, ext_prop_data,
+			 ffs->ms_os_descs_ext_prop_data_len);
 	vla_item_with_sz(d, char, raw_descs, ffs->raw_descs_length);
 	char *vlabuf;
 
@@ -2351,12 +2647,16 @@
 		return -ENOTSUPP;
 
 	/* Allocate a single chunk, less management later on */
-	vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL);
+	vlabuf = kzalloc(vla_group_size(d), GFP_KERNEL);
 	if (unlikely(!vlabuf))
 		return -ENOMEM;
 
-	/* Zero */
-	memset(vla_ptr(vlabuf, d, eps), 0, d_eps__sz);
+	ffs->ms_os_descs_ext_prop_avail = vla_ptr(vlabuf, d, ext_prop);
+	ffs->ms_os_descs_ext_prop_name_avail =
+		vla_ptr(vlabuf, d, ext_prop_name);
+	ffs->ms_os_descs_ext_prop_data_avail =
+		vla_ptr(vlabuf, d, ext_prop_data);
+
 	/* Copy descriptors  */
 	memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs,
 	       ffs->raw_descs_length);
@@ -2410,12 +2710,16 @@
 
 	if (likely(super)) {
 		func->function.ss_descriptors = vla_ptr(vlabuf, d, ss_descs);
-		ret = ffs_do_descs(ffs->ss_descs_count,
+		ss_len = ffs_do_descs(ffs->ss_descs_count,
 				vla_ptr(vlabuf, d, raw_descs) + fs_len + hs_len,
 				d_raw_descs__sz - fs_len - hs_len,
 				__ffs_func_bind_do_descs, func);
-		if (unlikely(ret < 0))
+		if (unlikely(ss_len < 0)) {
+			ret = ss_len;
 			goto error;
+		}
+	} else {
+		ss_len = 0;
 	}
 
 	/*
@@ -2431,6 +2735,28 @@
 	if (unlikely(ret < 0))
 		goto error;
 
+	func->function.os_desc_table = vla_ptr(vlabuf, d, os_desc_table);
+	if (c->cdev->use_os_string)
+		for (i = 0; i < ffs->interfaces_count; ++i) {
+			struct usb_os_desc *desc;
+
+			desc = func->function.os_desc_table[i].os_desc =
+				vla_ptr(vlabuf, d, os_desc) +
+				i * sizeof(struct usb_os_desc);
+			desc->ext_compat_id =
+				vla_ptr(vlabuf, d, ext_compat) + i * 16;
+			INIT_LIST_HEAD(&desc->ext_prop);
+		}
+	ret = ffs_do_os_descs(ffs->ms_os_descs_count,
+			      vla_ptr(vlabuf, d, raw_descs) +
+			      fs_len + hs_len + ss_len,
+			      d_raw_descs__sz - fs_len - hs_len - ss_len,
+			      __ffs_func_bind_do_os_desc, func);
+	if (unlikely(ret < 0))
+		goto error;
+	func->function.os_desc_n =
+		c->cdev->use_os_string ? ffs->interfaces_count : 0;
+
 	/* And we're done */
 	ffs_event_add(ffs, FUNCTIONFS_BIND);
 	return 0;
@@ -2901,12 +3227,12 @@
 
 	ffs_dev = _ffs_find_dev(dev_name);
 	if (!ffs_dev)
-		ffs_dev = ERR_PTR(-ENODEV);
+		ffs_dev = ERR_PTR(-ENOENT);
 	else if (ffs_dev->mounted)
 		ffs_dev = ERR_PTR(-EBUSY);
 	else if (ffs_dev->ffs_acquire_dev_callback &&
 	    ffs_dev->ffs_acquire_dev_callback(ffs_dev))
-		ffs_dev = ERR_PTR(-ENODEV);
+		ffs_dev = ERR_PTR(-ENOENT);
 	else
 		ffs_dev->mounted = true;
 
diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/function/f_hid.c
similarity index 100%
rename from drivers/usb/gadget/f_hid.c
rename to drivers/usb/gadget/function/f_hid.c
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c
similarity index 100%
rename from drivers/usb/gadget/f_loopback.c
rename to drivers/usb/gadget/function/f_loopback.c
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
similarity index 100%
rename from drivers/usb/gadget/f_mass_storage.c
rename to drivers/usb/gadget/function/f_mass_storage.c
diff --git a/drivers/usb/gadget/f_mass_storage.h b/drivers/usb/gadget/function/f_mass_storage.h
similarity index 100%
rename from drivers/usb/gadget/f_mass_storage.h
rename to drivers/usb/gadget/function/f_mass_storage.h
diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/function/f_midi.c
similarity index 100%
rename from drivers/usb/gadget/f_midi.c
rename to drivers/usb/gadget/function/f_midi.c
diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
similarity index 77%
rename from drivers/usb/gadget/f_ncm.c
rename to drivers/usb/gadget/function/f_ncm.c
index a9499fd..bcdc882 100644
--- a/drivers/usb/gadget/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -68,6 +68,18 @@
 	 * callback and ethernet open/close
 	 */
 	spinlock_t			lock;
+
+	struct net_device		*netdev;
+
+	/* For multi-frame NDP TX */
+	struct sk_buff			*skb_tx_data;
+	struct sk_buff			*skb_tx_ndp;
+	u16				ndp_dgram_count;
+	bool				timer_force_tx;
+	struct tasklet_struct		tx_tasklet;
+	struct hrtimer			task_timer;
+
+	bool				timer_stopping;
 };
 
 static inline struct f_ncm *func_to_ncm(struct usb_function *f)
@@ -92,15 +104,20 @@
  * If the host can group frames, allow it to do that, 16K is selected,
  * because it's used by default by the current linux host driver
  */
-#define NTB_DEFAULT_IN_SIZE	USB_CDC_NCM_NTB_MIN_IN_SIZE
+#define NTB_DEFAULT_IN_SIZE	16384
 #define NTB_OUT_SIZE		16384
 
-/*
- * skbs of size less than that will not be aligned
- * to NCM's dwNtbInMaxSize to save bus bandwidth
+/* Allocation for storing the NDP, 32 should suffice for a
+ * 16k packet. This allows a maximum of 32 * 507 Byte packets to
+ * be transmitted in a single 16kB skb, though when sending full size
+ * packets this limit will be plenty.
+ * Smaller packets are not likely to be trying to maximize the
+ * throughput and will be mstly sending smaller infrequent frames.
  */
+#define TX_MAX_NUM_DPE		32
 
-#define	MAX_TX_NONFIXED		(512 * 3)
+/* Delay for the transmit to wait before sending an unfilled NTB frame. */
+#define TX_TIMEOUT_NSECS	300000
 
 #define FORMATS_SUPPORTED	(USB_CDC_NCM_NTB16_SUPPORTED |	\
 				 USB_CDC_NCM_NTB32_SUPPORTED)
@@ -355,14 +372,15 @@
 	u32		ndp_sign;
 	unsigned	nth_size;
 	unsigned	ndp_size;
+	unsigned	dpe_size;
 	unsigned	ndplen_align;
 	/* sizes in u16 units */
 	unsigned	dgram_item_len; /* index or length */
 	unsigned	block_length;
-	unsigned	fp_index;
+	unsigned	ndp_index;
 	unsigned	reserved1;
 	unsigned	reserved2;
-	unsigned	next_fp_index;
+	unsigned	next_ndp_index;
 };
 
 #define INIT_NDP16_OPTS {					\
@@ -370,13 +388,14 @@
 		.ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN,	\
 		.nth_size = sizeof(struct usb_cdc_ncm_nth16),	\
 		.ndp_size = sizeof(struct usb_cdc_ncm_ndp16),	\
+		.dpe_size = sizeof(struct usb_cdc_ncm_dpe16),	\
 		.ndplen_align = 4,				\
 		.dgram_item_len = 1,				\
 		.block_length = 1,				\
-		.fp_index = 1,					\
+		.ndp_index = 1,					\
 		.reserved1 = 0,					\
 		.reserved2 = 0,					\
-		.next_fp_index = 1,				\
+		.next_ndp_index = 1,				\
 	}
 
 
@@ -385,13 +404,14 @@
 		.ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN,	\
 		.nth_size = sizeof(struct usb_cdc_ncm_nth32),	\
 		.ndp_size = sizeof(struct usb_cdc_ncm_ndp32),	\
+		.dpe_size = sizeof(struct usb_cdc_ncm_dpe32),	\
 		.ndplen_align = 8,				\
 		.dgram_item_len = 2,				\
 		.block_length = 2,				\
-		.fp_index = 2,					\
+		.ndp_index = 2,					\
 		.reserved1 = 1,					\
 		.reserved2 = 2,					\
-		.next_fp_index = 2,				\
+		.next_ndp_index = 2,				\
 	}
 
 static const struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
@@ -803,6 +823,8 @@
 
 		if (ncm->port.in_ep->driver_data) {
 			DBG(cdev, "reset ncm\n");
+			ncm->timer_stopping = true;
+			ncm->netdev = NULL;
 			gether_disconnect(&ncm->port);
 			ncm_reset_values(ncm);
 		}
@@ -839,6 +861,8 @@
 			net = gether_connect(&ncm->port);
 			if (IS_ERR(net))
 				return PTR_ERR(net);
+			ncm->netdev = net;
+			ncm->timer_stopping = false;
 		}
 
 		spin_lock(&ncm->lock);
@@ -865,95 +889,232 @@
 	return ncm->port.in_ep->driver_data ? 1 : 0;
 }
 
+static struct sk_buff *package_for_tx(struct f_ncm *ncm)
+{
+	__le16		*ntb_iter;
+	struct sk_buff	*skb2 = NULL;
+	unsigned	ndp_pad;
+	unsigned	ndp_index;
+	unsigned	new_len;
+
+	const struct ndp_parser_opts *opts = ncm->parser_opts;
+	const int ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
+	const int dgram_idx_len = 2 * 2 * opts->dgram_item_len;
+
+	/* Stop the timer */
+	hrtimer_try_to_cancel(&ncm->task_timer);
+
+	ndp_pad = ALIGN(ncm->skb_tx_data->len, ndp_align) -
+			ncm->skb_tx_data->len;
+	ndp_index = ncm->skb_tx_data->len + ndp_pad;
+	new_len = ndp_index + dgram_idx_len + ncm->skb_tx_ndp->len;
+
+	/* Set the final BlockLength and wNdpIndex */
+	ntb_iter = (void *) ncm->skb_tx_data->data;
+	/* Increment pointer to BlockLength */
+	ntb_iter += 2 + 1 + 1;
+	put_ncm(&ntb_iter, opts->block_length, new_len);
+	put_ncm(&ntb_iter, opts->ndp_index, ndp_index);
+
+	/* Set the final NDP wLength */
+	new_len = opts->ndp_size +
+			(ncm->ndp_dgram_count * dgram_idx_len);
+	ncm->ndp_dgram_count = 0;
+	/* Increment from start to wLength */
+	ntb_iter = (void *) ncm->skb_tx_ndp->data;
+	ntb_iter += 2;
+	put_unaligned_le16(new_len, ntb_iter);
+
+	/* Merge the skbs */
+	swap(skb2, ncm->skb_tx_data);
+	if (ncm->skb_tx_data) {
+		dev_kfree_skb_any(ncm->skb_tx_data);
+		ncm->skb_tx_data = NULL;
+	}
+
+	/* Insert NDP alignment. */
+	ntb_iter = (void *) skb_put(skb2, ndp_pad);
+	memset(ntb_iter, 0, ndp_pad);
+
+	/* Copy NTB across. */
+	ntb_iter = (void *) skb_put(skb2, ncm->skb_tx_ndp->len);
+	memcpy(ntb_iter, ncm->skb_tx_ndp->data, ncm->skb_tx_ndp->len);
+	dev_kfree_skb_any(ncm->skb_tx_ndp);
+	ncm->skb_tx_ndp = NULL;
+
+	/* Insert zero'd datagram. */
+	ntb_iter = (void *) skb_put(skb2, dgram_idx_len);
+	memset(ntb_iter, 0, dgram_idx_len);
+
+	return skb2;
+}
+
 static struct sk_buff *ncm_wrap_ntb(struct gether *port,
 				    struct sk_buff *skb)
 {
 	struct f_ncm	*ncm = func_to_ncm(&port->func);
-	struct sk_buff	*skb2;
+	struct sk_buff	*skb2 = NULL;
 	int		ncb_len = 0;
-	__le16		*tmp;
-	int		div;
-	int		rem;
-	int		pad;
-	int		ndp_align;
-	int		ndp_pad;
+	__le16		*ntb_data;
+	__le16		*ntb_ndp;
+	int		dgram_pad;
+
 	unsigned	max_size = ncm->port.fixed_in_len;
 	const struct ndp_parser_opts *opts = ncm->parser_opts;
-	unsigned	crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
+	const int ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
+	const int div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
+	const int rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
+	const int dgram_idx_len = 2 * 2 * opts->dgram_item_len;
 
-	div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
-	rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
-	ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
+	if (!skb && !ncm->skb_tx_data)
+		return NULL;
 
-	ncb_len += opts->nth_size;
-	ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len;
-	ncb_len += ndp_pad;
-	ncb_len += opts->ndp_size;
-	ncb_len += 2 * 2 * opts->dgram_item_len; /* Datagram entry */
-	ncb_len += 2 * 2 * opts->dgram_item_len; /* Zero datagram entry */
-	pad = ALIGN(ncb_len, div) + rem - ncb_len;
-	ncb_len += pad;
+	if (skb) {
+		/* Add the CRC if required up front */
+		if (ncm->is_crc) {
+			uint32_t	crc;
+			__le16		*crc_pos;
 
-	if (ncb_len + skb->len + crc_len > max_size) {
+			crc = ~crc32_le(~0,
+					skb->data,
+					skb->len);
+			crc_pos = (void *) skb_put(skb, sizeof(uint32_t));
+			put_unaligned_le32(crc, crc_pos);
+		}
+
+		/* If the new skb is too big for the current NCM NTB then
+		 * set the current stored skb to be sent now and clear it
+		 * ready for new data.
+		 * NOTE: Assume maximum align for speed of calculation.
+		 */
+		if (ncm->skb_tx_data
+		    && (ncm->ndp_dgram_count >= TX_MAX_NUM_DPE
+		    || (ncm->skb_tx_data->len +
+		    div + rem + skb->len +
+		    ncm->skb_tx_ndp->len + ndp_align + (2 * dgram_idx_len))
+		    > max_size)) {
+			skb2 = package_for_tx(ncm);
+			if (!skb2)
+				goto err;
+		}
+
+		if (!ncm->skb_tx_data) {
+			ncb_len = opts->nth_size;
+			dgram_pad = ALIGN(ncb_len, div) + rem - ncb_len;
+			ncb_len += dgram_pad;
+
+			/* Create a new skb for the NTH and datagrams. */
+			ncm->skb_tx_data = alloc_skb(max_size, GFP_ATOMIC);
+			if (!ncm->skb_tx_data)
+				goto err;
+
+			ntb_data = (void *) skb_put(ncm->skb_tx_data, ncb_len);
+			memset(ntb_data, 0, ncb_len);
+			/* dwSignature */
+			put_unaligned_le32(opts->nth_sign, ntb_data);
+			ntb_data += 2;
+			/* wHeaderLength */
+			put_unaligned_le16(opts->nth_size, ntb_data++);
+
+			/* Allocate an skb for storing the NDP,
+			 * TX_MAX_NUM_DPE should easily suffice for a
+			 * 16k packet.
+			 */
+			ncm->skb_tx_ndp = alloc_skb((int)(opts->ndp_size
+						    + opts->dpe_size
+						    * TX_MAX_NUM_DPE),
+						    GFP_ATOMIC);
+			if (!ncm->skb_tx_ndp)
+				goto err;
+			ntb_ndp = (void *) skb_put(ncm->skb_tx_ndp,
+						    opts->ndp_size);
+			memset(ntb_ndp, 0, ncb_len);
+			/* dwSignature */
+			put_unaligned_le32(ncm->ndp_sign, ntb_ndp);
+			ntb_ndp += 2;
+
+			/* There is always a zeroed entry */
+			ncm->ndp_dgram_count = 1;
+
+			/* Note: we skip opts->next_ndp_index */
+		}
+
+		/* Delay the timer. */
+		hrtimer_start(&ncm->task_timer,
+			      ktime_set(0, TX_TIMEOUT_NSECS),
+			      HRTIMER_MODE_REL);
+
+		/* Add the datagram position entries */
+		ntb_ndp = (void *) skb_put(ncm->skb_tx_ndp, dgram_idx_len);
+		memset(ntb_ndp, 0, dgram_idx_len);
+
+		ncb_len = ncm->skb_tx_data->len;
+		dgram_pad = ALIGN(ncb_len, div) + rem - ncb_len;
+		ncb_len += dgram_pad;
+
+		/* (d)wDatagramIndex */
+		put_ncm(&ntb_ndp, opts->dgram_item_len, ncb_len);
+		/* (d)wDatagramLength */
+		put_ncm(&ntb_ndp, opts->dgram_item_len, skb->len);
+		ncm->ndp_dgram_count++;
+
+		/* Add the new data to the skb */
+		ntb_data = (void *) skb_put(ncm->skb_tx_data, dgram_pad);
+		memset(ntb_data, 0, dgram_pad);
+		ntb_data = (void *) skb_put(ncm->skb_tx_data, skb->len);
+		memcpy(ntb_data, skb->data, skb->len);
 		dev_kfree_skb_any(skb);
-		return NULL;
+		skb = NULL;
+
+	} else if (ncm->skb_tx_data && ncm->timer_force_tx) {
+		/* If the tx was requested because of a timeout then send */
+		skb2 = package_for_tx(ncm);
+		if (!skb2)
+			goto err;
 	}
 
-	skb2 = skb_copy_expand(skb, ncb_len,
-			       max_size - skb->len - ncb_len - crc_len,
-			       GFP_ATOMIC);
-	dev_kfree_skb_any(skb);
-	if (!skb2)
-		return NULL;
+	return skb2;
 
-	skb = skb2;
+err:
+	ncm->netdev->stats.tx_dropped++;
 
-	tmp = (void *) skb_push(skb, ncb_len);
-	memset(tmp, 0, ncb_len);
+	if (skb)
+		dev_kfree_skb_any(skb);
+	if (ncm->skb_tx_data)
+		dev_kfree_skb_any(ncm->skb_tx_data);
+	if (ncm->skb_tx_ndp)
+		dev_kfree_skb_any(ncm->skb_tx_ndp);
 
-	put_unaligned_le32(opts->nth_sign, tmp); /* dwSignature */
-	tmp += 2;
-	/* wHeaderLength */
-	put_unaligned_le16(opts->nth_size, tmp++);
-	tmp++; /* skip wSequence */
-	put_ncm(&tmp, opts->block_length, skb->len); /* (d)wBlockLength */
-	/* (d)wFpIndex */
-	/* the first pointer is right after the NTH + align */
-	put_ncm(&tmp, opts->fp_index, opts->nth_size + ndp_pad);
+	return NULL;
+}
 
-	tmp = (void *)tmp + ndp_pad;
+/*
+ * This transmits the NTB if there are frames waiting.
+ */
+static void ncm_tx_tasklet(unsigned long data)
+{
+	struct f_ncm	*ncm = (void *)data;
 
-	/* NDP */
-	put_unaligned_le32(ncm->ndp_sign, tmp); /* dwSignature */
-	tmp += 2;
-	/* wLength */
-	put_unaligned_le16(ncb_len - opts->nth_size - pad, tmp++);
+	if (ncm->timer_stopping)
+		return;
 
-	tmp += opts->reserved1;
-	tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */
-	tmp += opts->reserved2;
-
-	if (ncm->is_crc) {
-		uint32_t crc;
-
-		crc = ~crc32_le(~0,
-				skb->data + ncb_len,
-				skb->len - ncb_len);
-		put_unaligned_le32(crc, skb->data + skb->len);
-		skb_put(skb, crc_len);
+	/* Only send if data is available. */
+	if (ncm->skb_tx_data) {
+		ncm->timer_force_tx = true;
+		ncm->netdev->netdev_ops->ndo_start_xmit(NULL, ncm->netdev);
+		ncm->timer_force_tx = false;
 	}
+}
 
-	/* (d)wDatagramIndex[0] */
-	put_ncm(&tmp, opts->dgram_item_len, ncb_len);
-	/* (d)wDatagramLength[0] */
-	put_ncm(&tmp, opts->dgram_item_len, skb->len - ncb_len);
-	/* (d)wDatagramIndex[1] and  (d)wDatagramLength[1] already zeroed */
-
-	if (skb->len > MAX_TX_NONFIXED)
-		memset(skb_put(skb, max_size - skb->len),
-		       0, max_size - skb->len);
-
-	return skb;
+/*
+ * The transmit should only be run if no skb data has been sent
+ * for a certain duration.
+ */
+static enum hrtimer_restart ncm_tx_timeout(struct hrtimer *data)
+{
+	struct f_ncm *ncm = container_of(data, struct f_ncm, task_timer);
+	tasklet_schedule(&ncm->tx_tasklet);
+	return HRTIMER_NORESTART;
 }
 
 static int ncm_unwrap_ntb(struct gether *port,
@@ -963,6 +1124,7 @@
 	struct f_ncm	*ncm = func_to_ncm(&port->func);
 	__le16		*tmp = (void *) skb->data;
 	unsigned	index, index2;
+	int		ndp_index;
 	unsigned	dg_len, dg_len2;
 	unsigned	ndp_len;
 	struct sk_buff	*skb2;
@@ -995,91 +1157,101 @@
 		goto err;
 	}
 
-	index = get_ncm(&tmp, opts->fp_index);
-	/* NCM 3.2 */
-	if (((index % 4) != 0) && (index < opts->nth_size)) {
-		INFO(port->func.config->cdev, "Bad index: %x\n",
-			index);
-		goto err;
-	}
+	ndp_index = get_ncm(&tmp, opts->ndp_index);
 
-	/* walk through NDP */
-	tmp = ((void *)skb->data) + index;
-	if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
-		INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
-		goto err;
-	}
-	tmp += 2;
-
-	ndp_len = get_unaligned_le16(tmp++);
-	/*
-	 * NCM 3.3.1
-	 * entry is 2 items
-	 * item size is 16/32 bits, opts->dgram_item_len * 2 bytes
-	 * minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry
-	 */
-	if ((ndp_len < opts->ndp_size + 2 * 2 * (opts->dgram_item_len * 2))
-	    || (ndp_len % opts->ndplen_align != 0)) {
-		INFO(port->func.config->cdev, "Bad NDP length: %x\n", ndp_len);
-		goto err;
-	}
-	tmp += opts->reserved1;
-	tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */
-	tmp += opts->reserved2;
-
-	ndp_len -= opts->ndp_size;
-	index2 = get_ncm(&tmp, opts->dgram_item_len);
-	dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
-	dgram_counter = 0;
-
+	/* Run through all the NDP's in the NTB */
 	do {
-		index = index2;
-		dg_len = dg_len2;
-		if (dg_len < 14 + crc_len) { /* ethernet header + crc */
-			INFO(port->func.config->cdev, "Bad dgram length: %x\n",
-			     dg_len);
+		/* NCM 3.2 */
+		if (((ndp_index % 4) != 0) &&
+				(ndp_index < opts->nth_size)) {
+			INFO(port->func.config->cdev, "Bad index: %#X\n",
+			     ndp_index);
 			goto err;
 		}
-		if (ncm->is_crc) {
-			uint32_t crc, crc2;
 
-			crc = get_unaligned_le32(skb->data +
-						 index + dg_len - crc_len);
-			crc2 = ~crc32_le(~0,
-					 skb->data + index,
-					 dg_len - crc_len);
-			if (crc != crc2) {
-				INFO(port->func.config->cdev, "Bad CRC\n");
-				goto err;
-			}
+		/* walk through NDP */
+		tmp = (void *)(skb->data + ndp_index);
+		if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
+			INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
+			goto err;
 		}
+		tmp += 2;
 
+		ndp_len = get_unaligned_le16(tmp++);
+		/*
+		 * NCM 3.3.1
+		 * entry is 2 items
+		 * item size is 16/32 bits, opts->dgram_item_len * 2 bytes
+		 * minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry
+		 * Each entry is a dgram index and a dgram length.
+		 */
+		if ((ndp_len < opts->ndp_size
+				+ 2 * 2 * (opts->dgram_item_len * 2))
+				|| (ndp_len % opts->ndplen_align != 0)) {
+			INFO(port->func.config->cdev, "Bad NDP length: %#X\n",
+			     ndp_len);
+			goto err;
+		}
+		tmp += opts->reserved1;
+		/* Check for another NDP (d)wNextNdpIndex */
+		ndp_index = get_ncm(&tmp, opts->next_ndp_index);
+		tmp += opts->reserved2;
+
+		ndp_len -= opts->ndp_size;
 		index2 = get_ncm(&tmp, opts->dgram_item_len);
 		dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
+		dgram_counter = 0;
 
-		if (index2 == 0 || dg_len2 == 0) {
-			skb2 = skb;
-		} else {
-			skb2 = skb_clone(skb, GFP_ATOMIC);
+		do {
+			index = index2;
+			dg_len = dg_len2;
+			if (dg_len < 14 + crc_len) { /* ethernet hdr + crc */
+				INFO(port->func.config->cdev,
+				     "Bad dgram length: %#X\n", dg_len);
+				goto err;
+			}
+			if (ncm->is_crc) {
+				uint32_t crc, crc2;
+
+				crc = get_unaligned_le32(skb->data +
+							 index + dg_len -
+							 crc_len);
+				crc2 = ~crc32_le(~0,
+						 skb->data + index,
+						 dg_len - crc_len);
+				if (crc != crc2) {
+					INFO(port->func.config->cdev,
+					     "Bad CRC\n");
+					goto err;
+				}
+			}
+
+			index2 = get_ncm(&tmp, opts->dgram_item_len);
+			dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
+
+			/*
+			 * Copy the data into a new skb.
+			 * This ensures the truesize is correct
+			 */
+			skb2 = netdev_alloc_skb_ip_align(ncm->netdev,
+							 dg_len - crc_len);
 			if (skb2 == NULL)
 				goto err;
-		}
+			memcpy(skb_put(skb2, dg_len - crc_len),
+			       skb->data + index, dg_len - crc_len);
 
-		if (!skb_pull(skb2, index)) {
-			ret = -EOVERFLOW;
-			goto err;
-		}
+			skb_queue_tail(list, skb2);
 
-		skb_trim(skb2, dg_len - crc_len);
-		skb_queue_tail(list, skb2);
+			ndp_len -= 2 * (opts->dgram_item_len * 2);
 
-		ndp_len -= 2 * (opts->dgram_item_len * 2);
+			dgram_counter++;
 
-		dgram_counter++;
+			if (index2 == 0 || dg_len2 == 0)
+				break;
+		} while (ndp_len > 2 * (opts->dgram_item_len * 2));
+	} while (ndp_index);
 
-		if (index2 == 0 || dg_len2 == 0)
-			break;
-	} while (ndp_len > 2 * (opts->dgram_item_len * 2)); /* zero entry */
+	dev_kfree_skb_any(skb);
 
 	VDBG(port->func.config->cdev,
 	     "Parsed NTB with %d frames\n", dgram_counter);
@@ -1097,8 +1269,11 @@
 
 	DBG(cdev, "ncm deactivated\n");
 
-	if (ncm->port.in_ep->driver_data)
+	if (ncm->port.in_ep->driver_data) {
+		ncm->timer_stopping = true;
+		ncm->netdev = NULL;
 		gether_disconnect(&ncm->port);
+	}
 
 	if (ncm->notify->driver_data) {
 		usb_ep_disable(ncm->notify);
@@ -1267,6 +1442,10 @@
 	ncm->port.open = ncm_open;
 	ncm->port.close = ncm_close;
 
+	tasklet_init(&ncm->tx_tasklet, ncm_tx_tasklet, (unsigned long) ncm);
+	hrtimer_init(&ncm->task_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	ncm->task_timer.function = ncm_tx_timeout;
+
 	DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n",
 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
 			ncm->port.in_ep->name, ncm->port.out_ep->name,
@@ -1380,6 +1559,10 @@
 
 	DBG(c->cdev, "ncm unbind\n");
 
+	hrtimer_cancel(&ncm->task_timer);
+	tasklet_kill(&ncm->tx_tasklet);
+
+	ncm_string_defs[0].id = 0;
 	usb_free_all_descriptors(f);
 
 	kfree(ncm->notify_req->buf);
@@ -1416,6 +1599,7 @@
 	ncm->port.ioport = netdev_priv(opts->net);
 	mutex_unlock(&opts->lock);
 	ncm->port.is_fixed = true;
+	ncm->port.supports_multi_frame = true;
 
 	ncm->port.func.name = "cdc_network";
 	/* descriptors are per-instance copies */
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/function/f_obex.c
similarity index 100%
rename from drivers/usb/gadget/f_obex.c
rename to drivers/usb/gadget/function/f_obex.c
diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c
similarity index 100%
rename from drivers/usb/gadget/f_phonet.c
rename to drivers/usb/gadget/function/f_phonet.c
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c
similarity index 99%
rename from drivers/usb/gadget/f_rndis.c
rename to drivers/usb/gadget/function/f_rndis.c
index 9c41e95..ddb09dc 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/function/f_rndis.c
@@ -727,6 +727,10 @@
 	rndis_control_intf.bInterfaceNumber = status;
 	rndis_union_desc.bMasterInterface0 = status;
 
+	if (cdev->use_os_string)
+		f->os_desc_table[0].if_id =
+			rndis_iad_descriptor.bFirstInterface;
+
 	status = usb_interface_id(c, f);
 	if (status < 0)
 		goto fail;
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/function/f_serial.c
similarity index 100%
rename from drivers/usb/gadget/f_serial.c
rename to drivers/usb/gadget/function/f_serial.c
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c
similarity index 100%
rename from drivers/usb/gadget/f_sourcesink.c
rename to drivers/usb/gadget/function/f_sourcesink.c
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/function/f_subset.c
similarity index 100%
rename from drivers/usb/gadget/f_subset.c
rename to drivers/usb/gadget/function/f_subset.c
diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c
similarity index 100%
rename from drivers/usb/gadget/f_uac1.c
rename to drivers/usb/gadget/function/f_uac1.c
diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
similarity index 98%
rename from drivers/usb/gadget/f_uac2.c
rename to drivers/usb/gadget/function/f_uac2.c
index 6261db4a..3ed89ec 100644
--- a/drivers/usb/gadget/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -348,14 +348,34 @@
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		spin_lock_init(&uac2->p_prm.lock);
 		runtime->hw.rate_min = p_srate;
-		runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! p_ssize ! */
+		switch (p_ssize) {
+		case 3:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
+			break;
+		case 4:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+			break;
+		default:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+			break;
+		}
 		runtime->hw.channels_min = num_channels(p_chmask);
 		runtime->hw.period_bytes_min = 2 * uac2->p_prm.max_psize
 						/ runtime->hw.periods_min;
 	} else {
 		spin_lock_init(&uac2->c_prm.lock);
 		runtime->hw.rate_min = c_srate;
-		runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! c_ssize ! */
+		switch (c_ssize) {
+		case 3:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
+			break;
+		case 4:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+			break;
+		default:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+			break;
+		}
 		runtime->hw.channels_min = num_channels(c_chmask);
 		runtime->hw.period_bytes_min = 2 * uac2->c_prm.max_psize
 						/ runtime->hw.periods_min;
diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
similarity index 100%
rename from drivers/usb/gadget/f_uvc.c
rename to drivers/usb/gadget/function/f_uvc.c
diff --git a/drivers/usb/gadget/f_uvc.h b/drivers/usb/gadget/function/f_uvc.h
similarity index 100%
rename from drivers/usb/gadget/f_uvc.h
rename to drivers/usb/gadget/function/f_uvc.h
diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/function/g_zero.h
similarity index 100%
rename from drivers/usb/gadget/g_zero.h
rename to drivers/usb/gadget/function/g_zero.h
diff --git a/drivers/usb/gadget/ndis.h b/drivers/usb/gadget/function/ndis.h
similarity index 100%
rename from drivers/usb/gadget/ndis.h
rename to drivers/usb/gadget/function/ndis.h
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/function/rndis.c
similarity index 100%
rename from drivers/usb/gadget/rndis.c
rename to drivers/usb/gadget/function/rndis.c
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/function/rndis.h
similarity index 100%
rename from drivers/usb/gadget/rndis.h
rename to drivers/usb/gadget/function/rndis.h
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/function/storage_common.c
similarity index 100%
rename from drivers/usb/gadget/storage_common.c
rename to drivers/usb/gadget/function/storage_common.c
diff --git a/drivers/usb/gadget/storage_common.h b/drivers/usb/gadget/function/storage_common.h
similarity index 100%
rename from drivers/usb/gadget/storage_common.h
rename to drivers/usb/gadget/function/storage_common.h
diff --git a/drivers/usb/gadget/u_ecm.h b/drivers/usb/gadget/function/u_ecm.h
similarity index 100%
rename from drivers/usb/gadget/u_ecm.h
rename to drivers/usb/gadget/function/u_ecm.h
diff --git a/drivers/usb/gadget/u_eem.h b/drivers/usb/gadget/function/u_eem.h
similarity index 100%
rename from drivers/usb/gadget/u_eem.h
rename to drivers/usb/gadget/function/u_eem.h
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/function/u_ether.c
similarity index 98%
rename from drivers/usb/gadget/u_ether.c
rename to drivers/usb/gadget/function/u_ether.c
index 97b0277..d50adda 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -483,7 +483,7 @@
 					struct net_device *net)
 {
 	struct eth_dev		*dev = netdev_priv(net);
-	int			length = skb->len;
+	int			length = 0;
 	int			retval;
 	struct usb_request	*req = NULL;
 	unsigned long		flags;
@@ -500,13 +500,13 @@
 	}
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	if (!in) {
+	if (skb && !in) {
 		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
 	}
 
 	/* apply outgoing CDC or RNDIS filters */
-	if (!is_promisc(cdc_filter)) {
+	if (skb && !is_promisc(cdc_filter)) {
 		u8		*dest = skb->data;
 
 		if (is_multicast_ether_addr(dest)) {
@@ -557,11 +557,17 @@
 		if (dev->port_usb)
 			skb = dev->wrap(dev->port_usb, skb);
 		spin_unlock_irqrestore(&dev->lock, flags);
-		if (!skb)
+		if (!skb) {
+			/* Multi frame CDC protocols may store the frame for
+			 * later which is not a dropped frame.
+			 */
+			if (dev->port_usb->supports_multi_frame)
+				goto multiframe;
 			goto drop;
-
-		length = skb->len;
+		}
 	}
+
+	length = skb->len;
 	req->buf = skb->data;
 	req->context = skb;
 	req->complete = tx_complete;
@@ -604,6 +610,7 @@
 		dev_kfree_skb_any(skb);
 drop:
 		dev->net->stats.tx_dropped++;
+multiframe:
 		spin_lock_irqsave(&dev->req_lock, flags);
 		if (list_empty(&dev->tx_reqs))
 			netif_start_queue(net);
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/function/u_ether.h
similarity index 98%
rename from drivers/usb/gadget/u_ether.h
rename to drivers/usb/gadget/function/u_ether.h
index 0f0290a..334b389 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/function/u_ether.h
@@ -18,6 +18,7 @@
 #include <linux/if_ether.h>
 #include <linux/usb/composite.h>
 #include <linux/usb/cdc.h>
+#include <linux/netdevice.h>
 
 #include "gadget_chips.h"
 
@@ -74,6 +75,7 @@
 	bool				is_fixed;
 	u32				fixed_out_len;
 	u32				fixed_in_len;
+	bool				supports_multi_frame;
 	struct sk_buff			*(*wrap)(struct gether *port,
 						struct sk_buff *skb);
 	int				(*unwrap)(struct gether *port,
diff --git a/drivers/usb/gadget/u_ether_configfs.h b/drivers/usb/gadget/function/u_ether_configfs.h
similarity index 100%
rename from drivers/usb/gadget/u_ether_configfs.h
rename to drivers/usb/gadget/function/u_ether_configfs.h
diff --git a/drivers/usb/gadget/u_fs.h b/drivers/usb/gadget/function/u_fs.h
similarity index 95%
rename from drivers/usb/gadget/u_fs.h
rename to drivers/usb/gadget/function/u_fs.h
index bf0ba37..63d6e71 100644
--- a/drivers/usb/gadget/u_fs.h
+++ b/drivers/usb/gadget/function/u_fs.h
@@ -216,6 +216,13 @@
 	unsigned			fs_descs_count;
 	unsigned			hs_descs_count;
 	unsigned			ss_descs_count;
+	unsigned			ms_os_descs_count;
+	unsigned			ms_os_descs_ext_prop_count;
+	unsigned			ms_os_descs_ext_prop_name_len;
+	unsigned			ms_os_descs_ext_prop_data_len;
+	void				*ms_os_descs_ext_prop_avail;
+	void				*ms_os_descs_ext_prop_name_avail;
+	void				*ms_os_descs_ext_prop_data_avail;
 
 	unsigned short			strings_count;
 	unsigned short			interfaces_count;
diff --git a/drivers/usb/gadget/u_gether.h b/drivers/usb/gadget/function/u_gether.h
similarity index 100%
rename from drivers/usb/gadget/u_gether.h
rename to drivers/usb/gadget/function/u_gether.h
diff --git a/drivers/usb/gadget/u_ncm.h b/drivers/usb/gadget/function/u_ncm.h
similarity index 100%
rename from drivers/usb/gadget/u_ncm.h
rename to drivers/usb/gadget/function/u_ncm.h
diff --git a/drivers/usb/gadget/u_phonet.h b/drivers/usb/gadget/function/u_phonet.h
similarity index 100%
rename from drivers/usb/gadget/u_phonet.h
rename to drivers/usb/gadget/function/u_phonet.h
diff --git a/drivers/usb/gadget/u_rndis.h b/drivers/usb/gadget/function/u_rndis.h
similarity index 100%
rename from drivers/usb/gadget/u_rndis.h
rename to drivers/usb/gadget/function/u_rndis.h
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/function/u_serial.c
similarity index 100%
rename from drivers/usb/gadget/u_serial.c
rename to drivers/usb/gadget/function/u_serial.c
diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/function/u_serial.h
similarity index 100%
rename from drivers/usb/gadget/u_serial.h
rename to drivers/usb/gadget/function/u_serial.h
diff --git a/drivers/usb/gadget/u_uac1.c b/drivers/usb/gadget/function/u_uac1.c
similarity index 100%
rename from drivers/usb/gadget/u_uac1.c
rename to drivers/usb/gadget/function/u_uac1.c
diff --git a/drivers/usb/gadget/u_uac1.h b/drivers/usb/gadget/function/u_uac1.h
similarity index 100%
rename from drivers/usb/gadget/u_uac1.h
rename to drivers/usb/gadget/function/u_uac1.h
diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/function/uvc.h
similarity index 100%
rename from drivers/usb/gadget/uvc.h
rename to drivers/usb/gadget/function/uvc.h
diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c
similarity index 100%
rename from drivers/usb/gadget/uvc_queue.c
rename to drivers/usb/gadget/function/uvc_queue.c
diff --git a/drivers/usb/gadget/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h
similarity index 100%
rename from drivers/usb/gadget/uvc_queue.h
rename to drivers/usb/gadget/function/uvc_queue.h
diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c
similarity index 100%
rename from drivers/usb/gadget/uvc_v4l2.c
rename to drivers/usb/gadget/function/uvc_v4l2.c
diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c
similarity index 100%
rename from drivers/usb/gadget/uvc_video.c
rename to drivers/usb/gadget/function/uvc_video.c
diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig
new file mode 100644
index 0000000..aa376f0
--- /dev/null
+++ b/drivers/usb/gadget/legacy/Kconfig
@@ -0,0 +1,475 @@
+#
+# USB Gadget support on a system involves
+#    (a) a peripheral controller, and
+#    (b) the gadget driver using it.
+#
+# NOTE:  Gadget support ** DOES NOT ** depend on host-side CONFIG_USB !!
+#
+#  - Host systems (like PCs) need CONFIG_USB (with "A" jacks).
+#  - Peripherals (like PDAs) need CONFIG_USB_GADGET (with "B" jacks).
+#  - Some systems have both kinds of controllers.
+#
+# With help from a special transceiver and a "Mini-AB" jack, systems with
+# both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
+#
+
+config USB_ZERO
+	tristate "Gadget Zero (DEVELOPMENT)"
+	select USB_LIBCOMPOSITE
+	select USB_F_SS_LB
+	help
+	  Gadget Zero is a two-configuration device.  It either sinks and
+	  sources bulk data; or it loops back a configurable number of
+	  transfers.  It also implements control requests, for "chapter 9"
+	  conformance.  The driver needs only two bulk-capable endpoints, so
+	  it can work on top of most device-side usb controllers.  It's
+	  useful for testing, and is also a working example showing how
+	  USB "gadget drivers" can be written.
+
+	  Make this be the first driver you try using on top of any new
+	  USB peripheral controller driver.  Then you can use host-side
+	  test software, like the "usbtest" driver, to put your hardware
+	  and its driver through a basic set of functional tests.
+
+	  Gadget Zero also works with the host-side "usb-skeleton" driver,
+	  and with many kinds of host-side test software.  You may need
+	  to tweak product and vendor IDs before host software knows about
+	  this device, and arrange to select an appropriate configuration.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_zero".
+
+config USB_ZERO_HNPTEST
+	boolean "HNP Test Device"
+	depends on USB_ZERO && USB_OTG
+	help
+	  You can configure this device to enumerate using the device
+	  identifiers of the USB-OTG test device.  That means that when
+	  this gadget connects to another OTG device, with this one using
+	  the "B-Peripheral" role, that device will use HNP to let this
+	  one serve as the USB host instead (in the "B-Host" role).
+
+config USB_AUDIO
+	tristate "Audio Gadget"
+	depends on SND
+	select USB_LIBCOMPOSITE
+	select SND_PCM
+	help
+	  This Gadget Audio driver is compatible with USB Audio Class
+	  specification 2.0. It implements 1 AudioControl interface,
+	  1 AudioStreaming Interface each for USB-OUT and USB-IN.
+	  Number of channels, sample rate and sample size can be
+	  specified as module parameters.
+	  This driver doesn't expect any real Audio codec to be present
+	  on the device - the audio streams are simply sinked to and
+	  sourced from a virtual ALSA sound card created. The user-space
+	  application may choose to do whatever it wants with the data
+	  received from the USB Host and choose to provide whatever it
+	  wants as audio data to the USB Host.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_audio".
+
+config GADGET_UAC1
+	bool "UAC 1.0 (Legacy)"
+	depends on USB_AUDIO
+	help
+	  If you instead want older UAC Spec-1.0 driver that also has audio
+	  paths hardwired to the Audio codec chip on-board and doesn't work
+	  without one.
+
+config USB_ETH
+	tristate "Ethernet Gadget (with CDC Ethernet support)"
+	depends on NET
+	select USB_LIBCOMPOSITE
+	select USB_U_ETHER
+	select USB_F_ECM
+	select USB_F_SUBSET
+	select CRC32
+	help
+	  This driver implements Ethernet style communication, in one of
+	  several ways:
+
+	   - The "Communication Device Class" (CDC) Ethernet Control Model.
+	     That protocol is often avoided with pure Ethernet adapters, in
+	     favor of simpler vendor-specific hardware, but is widely
+	     supported by firmware for smart network devices.
+
+	   - On hardware can't implement that protocol, a simple CDC subset
+	     is used, placing fewer demands on USB.
+
+	   - CDC Ethernet Emulation Model (EEM) is a newer standard that has
+	     a simpler interface that can be used by more USB hardware.
+
+	  RNDIS support is an additional option, more demanding than than
+	  subset.
+
+	  Within the USB device, this gadget driver exposes a network device
+	  "usbX", where X depends on what other networking devices you have.
+	  Treat it like a two-node Ethernet link:  host, and gadget.
+
+	  The Linux-USB host-side "usbnet" driver interoperates with this
+	  driver, so that deep I/O queues can be supported.  On 2.4 kernels,
+	  use "CDCEther" instead, if you're using the CDC option. That CDC
+	  mode should also interoperate with standard CDC Ethernet class
+	  drivers on other host operating systems.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_ether".
+
+config USB_ETH_RNDIS
+	bool "RNDIS support"
+	depends on USB_ETH
+	select USB_LIBCOMPOSITE
+	select USB_F_RNDIS
+	default y
+	help
+	   Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
+	   and Microsoft provides redistributable binary RNDIS drivers for
+	   older versions of Windows.
+
+	   If you say "y" here, the Ethernet gadget driver will try to provide
+	   a second device configuration, supporting RNDIS to talk to such
+	   Microsoft USB hosts.
+
+	   To make MS-Windows work with this, use Documentation/usb/linux.inf
+	   as the "driver info file".  For versions of MS-Windows older than
+	   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_EEM
+       bool "Ethernet Emulation Model (EEM) support"
+       depends on USB_ETH
+	select USB_LIBCOMPOSITE
+	select USB_F_EEM
+       default n
+       help
+         CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
+         and therefore can be supported by more hardware.  Technically ECM and
+         EEM are designed for different applications.  The ECM model extends
+         the network interface to the target (e.g. a USB cable modem), and the
+         EEM model is for mobile devices to communicate with hosts using
+         ethernet over USB.  For Linux gadgets, however, the interface with
+         the host is the same (a usbX device), so the differences are minimal.
+
+         If you say "y" here, the Ethernet gadget driver will use the EEM
+         protocol rather than ECM.  If unsure, say "n".
+
+config USB_G_NCM
+	tristate "Network Control Model (NCM) support"
+	depends on NET
+	select USB_LIBCOMPOSITE
+	select USB_U_ETHER
+	select USB_F_NCM
+	select CRC32
+	help
+	  This driver implements USB CDC NCM subclass standard. NCM is
+	  an advanced protocol for Ethernet encapsulation, allows grouping
+	  of several ethernet frames into one USB transfer and different
+	  alignment possibilities.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_ncm".
+
+config USB_GADGETFS
+	tristate "Gadget Filesystem"
+	help
+	  This driver provides a filesystem based API that lets user mode
+	  programs implement a single-configuration USB device, including
+	  endpoint I/O and control requests that don't relate to enumeration.
+	  All endpoints, transfer speeds, and transfer types supported by
+	  the hardware are available, through read() and write() calls.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "gadgetfs".
+
+config USB_FUNCTIONFS
+	tristate "Function Filesystem"
+	select USB_LIBCOMPOSITE
+	select USB_F_FS
+	select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
+	help
+	  The Function Filesystem (FunctionFS) lets one create USB
+	  composite functions in user space in the same way GadgetFS
+	  lets one create USB gadgets in user space.  This allows creation
+	  of composite gadgets such that some of the functions are
+	  implemented in kernel space (for instance Ethernet, serial or
+	  mass storage) and other are implemented in user space.
+
+	  If you say "y" or "m" here you will be able what kind of
+	  configurations the gadget will provide.
+
+	  Say "y" to link the driver statically, or "m" to build
+	  a dynamically linked module called "g_ffs".
+
+config USB_FUNCTIONFS_ETH
+	bool "Include configuration with CDC ECM (Ethernet)"
+	depends on USB_FUNCTIONFS && NET
+	select USB_U_ETHER
+	select USB_F_ECM
+	select USB_F_SUBSET
+	help
+	  Include a configuration with CDC ECM function (Ethernet) and the
+	  Function Filesystem.
+
+config USB_FUNCTIONFS_RNDIS
+	bool "Include configuration with RNDIS (Ethernet)"
+	depends on USB_FUNCTIONFS && NET
+	select USB_U_ETHER
+	select USB_F_RNDIS
+	help
+	  Include a configuration with RNDIS function (Ethernet) and the Filesystem.
+
+config USB_FUNCTIONFS_GENERIC
+	bool "Include 'pure' configuration"
+	depends on USB_FUNCTIONFS
+	help
+	  Include a configuration with the Function Filesystem alone with
+	  no Ethernet interface.
+
+config USB_MASS_STORAGE
+	tristate "Mass Storage Gadget"
+	depends on BLOCK
+	select USB_LIBCOMPOSITE
+	select USB_F_MASS_STORAGE
+	help
+	  The Mass Storage Gadget acts as a USB Mass Storage disk drive.
+	  As its storage repository it can use a regular file or a block
+	  device (in much the same way as the "loop" device driver),
+	  specified as a module parameter or sysfs option.
+
+	  This driver is a replacement for now removed File-backed
+	  Storage Gadget (g_file_storage).
+
+	  Say "y" to link the driver statically, or "m" to build
+	  a dynamically linked module called "g_mass_storage".
+
+config USB_GADGET_TARGET
+	tristate "USB Gadget Target Fabric Module"
+	depends on TARGET_CORE
+	select USB_LIBCOMPOSITE
+	help
+	  This fabric is an USB gadget. Two USB protocols are supported that is
+	  BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is
+	  advertised on alternative interface 0 (primary) and UAS is on
+	  alternative interface 1. Both protocols can work on USB2.0 and USB3.0.
+	  UAS utilizes the USB 3.0 feature called streams support.
+
+config USB_G_SERIAL
+	tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
+	depends on TTY
+	select USB_U_SERIAL
+	select USB_F_ACM
+	select USB_F_SERIAL
+	select USB_F_OBEX
+	select USB_LIBCOMPOSITE
+	help
+	  The Serial Gadget talks to the Linux-USB generic serial driver.
+	  This driver supports a CDC-ACM module option, which can be used
+	  to interoperate with MS-Windows hosts or with the Linux-USB
+	  "cdc-acm" driver.
+
+	  This driver also supports a CDC-OBEX option.  You will need a
+	  user space OBEX server talking to /dev/ttyGS*, since the kernel
+	  itself doesn't implement the OBEX protocol.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_serial".
+
+	  For more information, see Documentation/usb/gadget_serial.txt
+	  which includes instructions and a "driver info file" needed to
+	  make MS-Windows work with CDC ACM.
+
+config USB_MIDI_GADGET
+	tristate "MIDI Gadget"
+	depends on SND
+	select USB_LIBCOMPOSITE
+	select SND_RAWMIDI
+	help
+	  The MIDI Gadget acts as a USB Audio device, with one MIDI
+	  input and one MIDI output. These MIDI jacks appear as
+	  a sound "card" in the ALSA sound system. Other MIDI
+	  connections can then be made on the gadget system, using
+	  ALSA's aconnect utility etc.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_midi".
+
+config USB_G_PRINTER
+	tristate "Printer Gadget"
+	select USB_LIBCOMPOSITE
+	help
+	  The Printer Gadget channels data between the USB host and a
+	  userspace program driving the print engine. The user space
+	  program reads and writes the device file /dev/g_printer to
+	  receive or send printer data. It can use ioctl calls to
+	  the device file to get or set printer status.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_printer".
+
+	  For more information, see Documentation/usb/gadget_printer.txt
+	  which includes sample code for accessing the device file.
+
+if TTY
+
+config USB_CDC_COMPOSITE
+	tristate "CDC Composite Device (Ethernet and ACM)"
+	depends on NET
+	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_U_ETHER
+	select USB_F_ACM
+	select USB_F_ECM
+	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.
+
+config USB_G_NOKIA
+	tristate "Nokia composite gadget"
+	depends on PHONET
+	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_U_ETHER
+	select USB_F_ACM
+	select USB_F_OBEX
+	select USB_F_PHONET
+	select USB_F_ECM
+	help
+	  The Nokia composite gadget provides support for acm, obex
+	  and phonet in only one composite gadget driver.
+
+	  It's only really useful for N900 hardware. If you're building
+	  a kernel for N900, say Y or M here. If unsure, say N.
+
+config USB_G_ACM_MS
+	tristate "CDC Composite Device (ACM and mass storage)"
+	depends on BLOCK
+	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_F_ACM
+	select USB_F_MASS_STORAGE
+	help
+	  This driver provides two functions in one configuration:
+	  a mass storage, and a CDC ACM (serial port) link.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_acm_ms".
+
+config USB_G_MULTI
+	tristate "Multifunction Composite Gadget"
+	depends on BLOCK && NET
+	select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
+	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_U_ETHER
+	select USB_F_ACM
+	select USB_F_MASS_STORAGE
+	help
+	  The Multifunction Composite Gadget provides Ethernet (RNDIS
+	  and/or CDC Ethernet), mass storage and ACM serial link
+	  interfaces.
+
+	  You will be asked to choose which of the two configurations is
+	  to be available in the gadget.  At least one configuration must
+	  be chosen to make the gadget usable.  Selecting more than one
+	  configuration will prevent Windows from automatically detecting
+	  the gadget as a composite gadget, so an INF file will be needed to
+	  use the gadget.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_multi".
+
+config USB_G_MULTI_RNDIS
+	bool "RNDIS + CDC Serial + Storage configuration"
+	depends on USB_G_MULTI
+	select USB_F_RNDIS
+	default y
+	help
+	  This option enables a configuration with RNDIS, CDC Serial and
+	  Mass Storage functions available in the Multifunction Composite
+	  Gadget.  This is the configuration dedicated for Windows since RNDIS
+	  is Microsoft's protocol.
+
+	  If unsure, say "y".
+
+config USB_G_MULTI_CDC
+	bool "CDC Ethernet + CDC Serial + Storage configuration"
+	depends on USB_G_MULTI
+	default n
+	select USB_F_ECM
+	help
+	  This option enables a configuration with CDC Ethernet (ECM), CDC
+	  Serial and Mass Storage functions available in the Multifunction
+	  Composite Gadget.
+
+	  If unsure, say "y".
+
+endif # TTY
+
+config USB_G_HID
+	tristate "HID Gadget"
+	select USB_LIBCOMPOSITE
+	help
+	  The HID gadget driver provides generic emulation of USB
+	  Human Interface Devices (HID).
+
+	  For more information, see Documentation/usb/gadget_hid.txt which
+	  includes sample code for accessing the device files.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_hid".
+
+# Standalone / single function gadgets
+config USB_G_DBGP
+	tristate "EHCI Debug Device Gadget"
+	depends on TTY
+	select USB_LIBCOMPOSITE
+	help
+	  This gadget emulates an EHCI Debug device. This is useful when you want
+	  to interact with an EHCI Debug Port.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_dbgp".
+
+if USB_G_DBGP
+choice
+	prompt "EHCI Debug Device mode"
+	default USB_G_DBGP_SERIAL
+
+config USB_G_DBGP_PRINTK
+	depends on USB_G_DBGP
+	bool "printk"
+	help
+	  Directly printk() received data. No interaction.
+
+config USB_G_DBGP_SERIAL
+	depends on USB_G_DBGP
+	select USB_U_SERIAL
+	bool "serial"
+	help
+	  Userland can interact using /dev/ttyGSxxx.
+endchoice
+endif
+
+# put drivers that need isochronous transfer support (for audio
+# or video class gadget drivers), or specific hardware, here.
+config USB_G_WEBCAM
+	tristate "USB Webcam Gadget"
+	depends on VIDEO_DEV
+	select USB_LIBCOMPOSITE
+	select VIDEOBUF2_VMALLOC
+	help
+	  The Webcam Gadget acts as a composite USB Audio and Video Class
+	  device. It provides a userspace API to process UVC control requests
+	  and stream video data to the host.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_webcam".
diff --git a/drivers/usb/gadget/legacy/Makefile b/drivers/usb/gadget/legacy/Makefile
new file mode 100644
index 0000000..a11aad5
--- /dev/null
+++ b/drivers/usb/gadget/legacy/Makefile
@@ -0,0 +1,44 @@
+#
+# USB gadget drivers
+#
+
+ccflags-y			:= -I$(PWD)/drivers/usb/gadget/
+ccflags-y			+= -I$(PWD)/drivers/usb/gadget/udc/
+ccflags-y			+= -I$(PWD)/drivers/usb/gadget/function/
+
+g_zero-y			:= zero.o
+g_audio-y			:= audio.o
+g_ether-y			:= ether.o
+g_serial-y			:= serial.o
+g_midi-y			:= gmidi.o
+gadgetfs-y			:= inode.o
+g_mass_storage-y		:= mass_storage.o
+g_printer-y			:= printer.o
+g_cdc-y				:= cdc2.o
+g_multi-y			:= multi.o
+g_hid-y				:= hid.o
+g_dbgp-y			:= dbgp.o
+g_nokia-y			:= nokia.o
+g_webcam-y			:= webcam.o
+g_ncm-y				:= ncm.o
+g_acm_ms-y			:= acm_ms.o
+g_tcm_usb_gadget-y		:= tcm_usb_gadget.o
+
+obj-$(CONFIG_USB_ZERO)		+= g_zero.o
+obj-$(CONFIG_USB_AUDIO)		+= g_audio.o
+obj-$(CONFIG_USB_ETH)		+= g_ether.o
+obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
+obj-$(CONFIG_USB_FUNCTIONFS)	+= g_ffs.o
+obj-$(CONFIG_USB_MASS_STORAGE)	+= g_mass_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
+obj-$(CONFIG_USB_G_HID)		+= g_hid.o
+obj-$(CONFIG_USB_G_DBGP)	+= g_dbgp.o
+obj-$(CONFIG_USB_G_MULTI)	+= g_multi.o
+obj-$(CONFIG_USB_G_NOKIA)	+= g_nokia.o
+obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o
+obj-$(CONFIG_USB_G_NCM)		+= g_ncm.o
+obj-$(CONFIG_USB_G_ACM_MS)	+= g_acm_ms.o
+obj-$(CONFIG_USB_GADGET_TARGET)	+= tcm_usb_gadget.o
diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/legacy/acm_ms.c
similarity index 96%
rename from drivers/usb/gadget/acm_ms.c
rename to drivers/usb/gadget/legacy/acm_ms.c
index a252444..c30b7b5 100644
--- a/drivers/usb/gadget/acm_ms.c
+++ b/drivers/usb/gadget/legacy/acm_ms.c
@@ -267,18 +267,8 @@
 	.unbind		= __exit_p(acm_ms_unbind),
 };
 
+module_usb_composite_driver(acm_ms_driver);
+
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Klaus Schwarzkopf <schwarzkopf@sensortherm.de>");
 MODULE_LICENSE("GPL v2");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&acm_ms_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&acm_ms_driver);
-}
-module_exit(cleanup);
diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/legacy/audio.c
similarity index 95%
rename from drivers/usb/gadget/audio.c
rename to drivers/usb/gadget/legacy/audio.c
index 231b0ef..6eb695e 100644
--- a/drivers/usb/gadget/audio.c
+++ b/drivers/usb/gadget/legacy/audio.c
@@ -172,17 +172,7 @@
 	.unbind		= __exit_p(audio_unbind),
 };
 
-static int __init init(void)
-{
-	return usb_composite_probe(&audio_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&audio_driver);
-}
-module_exit(cleanup);
+module_usb_composite_driver(audio_driver);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Bryan Wu <cooloney@kernel.org>");
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/legacy/cdc2.c
similarity index 96%
rename from drivers/usb/gadget/cdc2.c
rename to drivers/usb/gadget/legacy/cdc2.c
index e126b6b..2e85d94 100644
--- a/drivers/usb/gadget/cdc2.c
+++ b/drivers/usb/gadget/legacy/cdc2.c
@@ -231,18 +231,8 @@
 	.unbind		= __exit_p(cdc_unbind),
 };
 
+module_usb_composite_driver(cdc_driver);
+
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("David Brownell");
 MODULE_LICENSE("GPL");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&cdc_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&cdc_driver);
-}
-module_exit(cleanup);
diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c
similarity index 100%
rename from drivers/usb/gadget/dbgp.c
rename to drivers/usb/gadget/legacy/dbgp.c
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/legacy/ether.c
similarity index 98%
rename from drivers/usb/gadget/ether.c
rename to drivers/usb/gadget/legacy/ether.c
index c1c113e..c5fdc61 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/legacy/ether.c
@@ -475,18 +475,8 @@
 	.unbind		= __exit_p(eth_unbind),
 };
 
+module_usb_composite_driver(eth_driver);
+
 MODULE_DESCRIPTION(PREFIX DRIVER_DESC);
 MODULE_AUTHOR("David Brownell, Benedikt Spanger");
 MODULE_LICENSE("GPL");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&eth_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&eth_driver);
-}
-module_exit(cleanup);
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/legacy/g_ffs.c
similarity index 99%
rename from drivers/usb/gadget/g_ffs.c
rename to drivers/usb/gadget/legacy/g_ffs.c
index fe12e6a..06acfa5 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/legacy/g_ffs.c
@@ -276,7 +276,7 @@
 static void *functionfs_acquire_dev(struct ffs_dev *dev)
 {
 	if (!try_module_get(THIS_MODULE))
-		return ERR_PTR(-ENODEV);
+		return ERR_PTR(-ENOENT);
 	
 	return 0;
 }
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/legacy/gmidi.c
similarity index 95%
rename from drivers/usb/gadget/gmidi.c
rename to drivers/usb/gadget/legacy/gmidi.c
index e879e2c..3d696b8 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/legacy/gmidi.c
@@ -163,15 +163,4 @@
 	.unbind		= __exit_p(midi_unbind),
 };
 
-static int __init midi_init(void)
-{
-	return usb_composite_probe(&midi_driver);
-}
-module_init(midi_init);
-
-static void __exit midi_cleanup(void)
-{
-	usb_composite_unregister(&midi_driver);
-}
-module_exit(midi_cleanup);
-
+module_usb_composite_driver(midi_driver);
diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/legacy/hid.c
similarity index 100%
rename from drivers/usb/gadget/hid.c
rename to drivers/usb/gadget/legacy/hid.c
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/legacy/inode.c
similarity index 100%
rename from drivers/usb/gadget/inode.c
rename to drivers/usb/gadget/legacy/inode.c
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c
similarity index 100%
rename from drivers/usb/gadget/mass_storage.c
rename to drivers/usb/gadget/legacy/mass_storage.c
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/legacy/multi.c
similarity index 97%
rename from drivers/usb/gadget/multi.c
rename to drivers/usb/gadget/legacy/multi.c
index 940f6cd..39d27bb 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/legacy/multi.c
@@ -507,15 +507,4 @@
 	.needs_serial	= 1,
 };
 
-
-static int __init multi_init(void)
-{
-	return usb_composite_probe(&multi_driver);
-}
-module_init(multi_init);
-
-static void __exit multi_exit(void)
-{
-	usb_composite_unregister(&multi_driver);
-}
-module_exit(multi_exit);
+module_usb_composite_driver(multi_driver);
diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/legacy/ncm.c
similarity index 96%
rename from drivers/usb/gadget/ncm.c
rename to drivers/usb/gadget/legacy/ncm.c
index 81956fe..e90e23d 100644
--- a/drivers/usb/gadget/ncm.c
+++ b/drivers/usb/gadget/legacy/ncm.c
@@ -204,18 +204,8 @@
 	.unbind		= __exit_p(gncm_unbind),
 };
 
+module_usb_composite_driver(ncm_driver);
+
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Yauheni Kaliuta");
 MODULE_LICENSE("GPL");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&ncm_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&ncm_driver);
-}
-module_exit(cleanup);
diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/legacy/nokia.c
similarity index 97%
rename from drivers/usb/gadget/nokia.c
rename to drivers/usb/gadget/legacy/nokia.c
index 3ab3861..9b8fd70 100644
--- a/drivers/usb/gadget/nokia.c
+++ b/drivers/usb/gadget/legacy/nokia.c
@@ -347,14 +347,4 @@
 	.unbind		= __exit_p(nokia_unbind),
 };
 
-static int __init nokia_init(void)
-{
-	return usb_composite_probe(&nokia_driver);
-}
-module_init(nokia_init);
-
-static void __exit nokia_cleanup(void)
-{
-	usb_composite_unregister(&nokia_driver);
-}
-module_exit(nokia_cleanup);
+module_usb_composite_driver(nokia_driver);
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/legacy/printer.c
similarity index 100%
rename from drivers/usb/gadget/printer.c
rename to drivers/usb/gadget/legacy/printer.c
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/legacy/serial.c
similarity index 100%
rename from drivers/usb/gadget/serial.c
rename to drivers/usb/gadget/legacy/serial.c
diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/legacy/tcm_usb_gadget.c
similarity index 100%
rename from drivers/usb/gadget/tcm_usb_gadget.c
rename to drivers/usb/gadget/legacy/tcm_usb_gadget.c
diff --git a/drivers/usb/gadget/tcm_usb_gadget.h b/drivers/usb/gadget/legacy/tcm_usb_gadget.h
similarity index 100%
rename from drivers/usb/gadget/tcm_usb_gadget.h
rename to drivers/usb/gadget/legacy/tcm_usb_gadget.h
diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/legacy/webcam.c
similarity index 97%
rename from drivers/usb/gadget/webcam.c
rename to drivers/usb/gadget/legacy/webcam.c
index 8cef1e6..a11d8e4 100644
--- a/drivers/usb/gadget/webcam.c
+++ b/drivers/usb/gadget/legacy/webcam.c
@@ -390,20 +390,7 @@
 	.unbind		= webcam_unbind,
 };
 
-static int __init
-webcam_init(void)
-{
-	return usb_composite_probe(&webcam_driver);
-}
-
-static void __exit
-webcam_cleanup(void)
-{
-	usb_composite_unregister(&webcam_driver);
-}
-
-module_init(webcam_init);
-module_exit(webcam_cleanup);
+module_usb_composite_driver(webcam_driver);
 
 MODULE_AUTHOR("Laurent Pinchart");
 MODULE_DESCRIPTION("Webcam Video Gadget");
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/legacy/zero.c
similarity index 98%
rename from drivers/usb/gadget/zero.c
rename to drivers/usb/gadget/legacy/zero.c
index 134f354..c3d4968 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/legacy/zero.c
@@ -411,17 +411,7 @@
 	.resume		= zero_resume,
 };
 
+module_usb_composite_driver(zero_driver);
+
 MODULE_AUTHOR("David Brownell");
 MODULE_LICENSE("GPL");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&zero_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&zero_driver);
-}
-module_exit(cleanup);
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
deleted file mode 100644
index 300b3a7..0000000
--- a/drivers/usb/gadget/net2280.c
+++ /dev/null
@@ -1,2905 +0,0 @@
-/*
- * Driver for the PLX NET2280 USB device controller.
- * Specs and errata are available from <http://www.plxtech.com>.
- *
- * PLX Technology Inc. (formerly NetChip Technology) supported the
- * development of this driver.
- *
- *
- * CODE STATUS HIGHLIGHTS
- *
- * This driver should work well with most "gadget" drivers, including
- * the Mass Storage, Serial, and Ethernet/RNDIS gadget drivers
- * as well as Gadget Zero and Gadgetfs.
- *
- * DMA is enabled by default.  Drivers using transfer queues might use
- * DMA chaining to remove IRQ latencies between transfers.  (Except when
- * short OUT transfers happen.)  Drivers can use the req->no_interrupt
- * hint to completely eliminate some IRQs, if a later IRQ is guaranteed
- * and DMA chaining is enabled.
- *
- * Note that almost all the errata workarounds here are only needed for
- * rev1 chips.  Rev1a silicon (0110) fixes almost all of them.
- */
-
-/*
- * Copyright (C) 2003 David Brownell
- * Copyright (C) 2003-2005 PLX Technology, Inc.
- *
- * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility
- *	with 2282 chip
- *
- * 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.
- */
-
-#undef	DEBUG		/* messages on error and most fault paths */
-#undef	VERBOSE		/* extra debug messages (success too) */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/prefetch.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/unaligned.h>
-
-
-#define	DRIVER_DESC		"PLX NET228x USB Peripheral Controller"
-#define	DRIVER_VERSION		"2005 Sept 27"
-
-#define	EP_DONTUSE		13	/* nonzero */
-
-#define USE_RDK_LEDS		/* GPIO pins control three LEDs */
-
-
-static const char driver_name [] = "net2280";
-static const char driver_desc [] = DRIVER_DESC;
-
-static const char ep0name [] = "ep0";
-static const char *const ep_name [] = {
-	ep0name,
-	"ep-a", "ep-b", "ep-c", "ep-d",
-	"ep-e", "ep-f",
-};
-
-/* use_dma -- general goodness, fewer interrupts, less cpu load (vs PIO)
- * use_dma_chaining -- dma descriptor queueing gives even more irq reduction
- *
- * The net2280 DMA engines are not tightly integrated with their FIFOs;
- * not all cases are (yet) handled well in this driver or the silicon.
- * Some gadget drivers work better with the dma support here than others.
- * These two parameters let you use PIO or more aggressive DMA.
- */
-static bool use_dma = 1;
-static bool use_dma_chaining = 0;
-
-/* "modprobe net2280 use_dma=n" etc */
-module_param (use_dma, bool, S_IRUGO);
-module_param (use_dma_chaining, bool, S_IRUGO);
-
-
-/* mode 0 == ep-{a,b,c,d} 1K fifo each
- * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable
- * mode 2 == ep-a 2K fifo, ep-{b,c} 1K each, ep-d unavailable
- */
-static ushort fifo_mode = 0;
-
-/* "modprobe net2280 fifo_mode=1" etc */
-module_param (fifo_mode, ushort, 0644);
-
-/* enable_suspend -- When enabled, the driver will respond to
- * USB suspend requests by powering down the NET2280.  Otherwise,
- * USB suspend requests will be ignored.  This is acceptable for
- * self-powered devices
- */
-static bool enable_suspend = 0;
-
-/* "modprobe net2280 enable_suspend=1" etc */
-module_param (enable_suspend, bool, S_IRUGO);
-
-/* force full-speed operation */
-static bool full_speed;
-module_param(full_speed, bool, 0444);
-MODULE_PARM_DESC(full_speed, "force full-speed mode -- for testing only!");
-
-#define	DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out")
-
-#if defined(CONFIG_USB_GADGET_DEBUG_FILES) || defined (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 "net2280.h"
-
-#define valid_bit	cpu_to_le32 (1 << VALID_BIT)
-#define dma_done_ie	cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE)
-
-/*-------------------------------------------------------------------------*/
-
-static int
-net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
-{
-	struct net2280		*dev;
-	struct net2280_ep	*ep;
-	u32			max, tmp;
-	unsigned long		flags;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || !desc || ep->desc || _ep->name == ep0name
-			|| desc->bDescriptorType != USB_DT_ENDPOINT)
-		return -EINVAL;
-	dev = ep->dev;
-	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-
-	/* erratum 0119 workaround ties up an endpoint number */
-	if ((desc->bEndpointAddress & 0x0f) == EP_DONTUSE)
-		return -EDOM;
-
-	/* sanity check ep-e/ep-f since their fifos are small */
-	max = usb_endpoint_maxp (desc) & 0x1fff;
-	if (ep->num > 4 && max > 64)
-		return -ERANGE;
-
-	spin_lock_irqsave (&dev->lock, flags);
-	_ep->maxpacket = max & 0x7ff;
-	ep->desc = desc;
-
-	/* ep_reset() has already been called */
-	ep->stopped = 0;
-	ep->wedged = 0;
-	ep->out_overflow = 0;
-
-	/* set speed-dependent max packet; may kick in high bandwidth */
-	set_idx_reg (dev->regs, REG_EP_MAXPKT (dev, ep->num), max);
-
-	/* FIFO lines can't go to different packets.  PIO is ok, so
-	 * use it instead of troublesome (non-bulk) multi-packet DMA.
-	 */
-	if (ep->dma && (max % 4) != 0 && use_dma_chaining) {
-		DEBUG (ep->dev, "%s, no dma for maxpacket %d\n",
-			ep->ep.name, ep->ep.maxpacket);
-		ep->dma = NULL;
-	}
-
-	/* set type, direction, address; reset fifo counters */
-	writel ((1 << FIFO_FLUSH), &ep->regs->ep_stat);
-	tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
-	if (tmp == USB_ENDPOINT_XFER_INT) {
-		/* erratum 0105 workaround prevents hs NYET */
-		if (dev->chiprev == 0100
-				&& dev->gadget.speed == USB_SPEED_HIGH
-				&& !(desc->bEndpointAddress & USB_DIR_IN))
-			writel ((1 << CLEAR_NAK_OUT_PACKETS_MODE),
-				&ep->regs->ep_rsp);
-	} else if (tmp == USB_ENDPOINT_XFER_BULK) {
-		/* catch some particularly blatant driver bugs */
-		if ((dev->gadget.speed == USB_SPEED_HIGH
-					&& max != 512)
-				|| (dev->gadget.speed == USB_SPEED_FULL
-					&& max > 64)) {
-			spin_unlock_irqrestore (&dev->lock, flags);
-			return -ERANGE;
-		}
-	}
-	ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0;
-	tmp <<= ENDPOINT_TYPE;
-	tmp |= desc->bEndpointAddress;
-	tmp |= (4 << ENDPOINT_BYTE_COUNT);	/* default full fifo lines */
-	tmp |= 1 << ENDPOINT_ENABLE;
-	wmb ();
-
-	/* for OUT transfers, block the rx fifo until a read is posted */
-	ep->is_in = (tmp & USB_DIR_IN) != 0;
-	if (!ep->is_in)
-		writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-	else if (dev->pdev->device != 0x2280) {
-		/* Added for 2282, Don't use nak packets on an in endpoint,
-		 * this was ignored on 2280
-		 */
-		writel ((1 << CLEAR_NAK_OUT_PACKETS)
-			| (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
-	}
-
-	writel (tmp, &ep->regs->ep_cfg);
-
-	/* enable irqs */
-	if (!ep->dma) {				/* pio, per-packet */
-		tmp = (1 << ep->num) | readl (&dev->regs->pciirqenb0);
-		writel (tmp, &dev->regs->pciirqenb0);
-
-		tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
-			| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE);
-		if (dev->pdev->device == 0x2280)
-			tmp |= readl (&ep->regs->ep_irqenb);
-		writel (tmp, &ep->regs->ep_irqenb);
-	} else {				/* dma, per-request */
-		tmp = (1 << (8 + ep->num));	/* completion */
-		tmp |= readl (&dev->regs->pciirqenb1);
-		writel (tmp, &dev->regs->pciirqenb1);
-
-		/* for short OUT transfers, dma completions can't
-		 * advance the queue; do it pio-style, by hand.
-		 * NOTE erratum 0112 workaround #2
-		 */
-		if ((desc->bEndpointAddress & USB_DIR_IN) == 0) {
-			tmp = (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE);
-			writel (tmp, &ep->regs->ep_irqenb);
-
-			tmp = (1 << ep->num) | readl (&dev->regs->pciirqenb0);
-			writel (tmp, &dev->regs->pciirqenb0);
-		}
-	}
-
-	tmp = desc->bEndpointAddress;
-	DEBUG (dev, "enabled %s (ep%d%s-%s) %s max %04x\n",
-		_ep->name, tmp & 0x0f, DIR_STRING (tmp),
-		type_string (desc->bmAttributes),
-		ep->dma ? "dma" : "pio", max);
-
-	/* pci writes may still be posted */
-	spin_unlock_irqrestore (&dev->lock, flags);
-	return 0;
-}
-
-static int handshake (u32 __iomem *ptr, u32 mask, u32 done, int usec)
-{
-	u32	result;
-
-	do {
-		result = readl (ptr);
-		if (result == ~(u32)0)		/* "device unplugged" */
-			return -ENODEV;
-		result &= mask;
-		if (result == done)
-			return 0;
-		udelay (1);
-		usec--;
-	} while (usec > 0);
-	return -ETIMEDOUT;
-}
-
-static const struct usb_ep_ops net2280_ep_ops;
-
-static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
-{
-	u32		tmp;
-
-	ep->desc = NULL;
-	INIT_LIST_HEAD (&ep->queue);
-
-	usb_ep_set_maxpacket_limit(&ep->ep, ~0);
-	ep->ep.ops = &net2280_ep_ops;
-
-	/* disable the dma, irqs, endpoint... */
-	if (ep->dma) {
-		writel (0, &ep->dma->dmactl);
-		writel (  (1 << DMA_SCATTER_GATHER_DONE_INTERRUPT)
-			| (1 << DMA_TRANSACTION_DONE_INTERRUPT)
-			| (1 << DMA_ABORT)
-			, &ep->dma->dmastat);
-
-		tmp = readl (&regs->pciirqenb0);
-		tmp &= ~(1 << ep->num);
-		writel (tmp, &regs->pciirqenb0);
-	} else {
-		tmp = readl (&regs->pciirqenb1);
-		tmp &= ~(1 << (8 + ep->num));	/* completion */
-		writel (tmp, &regs->pciirqenb1);
-	}
-	writel (0, &ep->regs->ep_irqenb);
-
-	/* init to our chosen defaults, notably so that we NAK OUT
-	 * packets until the driver queues a read (+note erratum 0112)
-	 */
-	if (!ep->is_in || ep->dev->pdev->device == 0x2280) {
-		tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
-		| (1 << SET_NAK_OUT_PACKETS)
-		| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-		| (1 << CLEAR_INTERRUPT_MODE);
-	} else {
-		/* added for 2282 */
-		tmp = (1 << CLEAR_NAK_OUT_PACKETS_MODE)
-		| (1 << CLEAR_NAK_OUT_PACKETS)
-		| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-		| (1 << CLEAR_INTERRUPT_MODE);
-	}
-
-	if (ep->num != 0) {
-		tmp |= (1 << CLEAR_ENDPOINT_TOGGLE)
-			| (1 << CLEAR_ENDPOINT_HALT);
-	}
-	writel (tmp, &ep->regs->ep_rsp);
-
-	/* scrub most status bits, and flush any fifo state */
-	if (ep->dev->pdev->device == 0x2280)
-		tmp = (1 << FIFO_OVERFLOW)
-			| (1 << FIFO_UNDERFLOW);
-	else
-		tmp = 0;
-
-	writel (tmp | (1 << TIMEOUT)
-		| (1 << USB_STALL_SENT)
-		| (1 << USB_IN_NAK_SENT)
-		| (1 << USB_IN_ACK_RCVD)
-		| (1 << USB_OUT_PING_NAK_SENT)
-		| (1 << USB_OUT_ACK_SENT)
-		| (1 << FIFO_FLUSH)
-		| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
-		| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
-		| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-		| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-		| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-		| (1 << DATA_IN_TOKEN_INTERRUPT)
-		, &ep->regs->ep_stat);
-
-	/* fifo size is handled separately */
-}
-
-static void nuke (struct net2280_ep *);
-
-static int net2280_disable (struct usb_ep *_ep)
-{
-	struct net2280_ep	*ep;
-	unsigned long		flags;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || !ep->desc || _ep->name == ep0name)
-		return -EINVAL;
-
-	spin_lock_irqsave (&ep->dev->lock, flags);
-	nuke (ep);
-	ep_reset (ep->dev->regs, ep);
-
-	VDEBUG (ep->dev, "disabled %s %s\n",
-			ep->dma ? "dma" : "pio", _ep->name);
-
-	/* synch memory views with the device */
-	(void) readl (&ep->regs->ep_cfg);
-
-	if (use_dma && !ep->dma && ep->num >= 1 && ep->num <= 4)
-		ep->dma = &ep->dev->dma [ep->num - 1];
-
-	spin_unlock_irqrestore (&ep->dev->lock, flags);
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_request *
-net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
-{
-	struct net2280_ep	*ep;
-	struct net2280_request	*req;
-
-	if (!_ep)
-		return NULL;
-	ep = container_of (_ep, struct net2280_ep, ep);
-
-	req = kzalloc(sizeof(*req), gfp_flags);
-	if (!req)
-		return NULL;
-
-	INIT_LIST_HEAD (&req->queue);
-
-	/* this dma descriptor may be swapped with the previous dummy */
-	if (ep->dma) {
-		struct net2280_dma	*td;
-
-		td = pci_pool_alloc (ep->dev->requests, gfp_flags,
-				&req->td_dma);
-		if (!td) {
-			kfree (req);
-			return NULL;
-		}
-		td->dmacount = 0;	/* not VALID */
-		td->dmadesc = td->dmaaddr;
-		req->td = td;
-	}
-	return &req->req;
-}
-
-static void
-net2280_free_request (struct usb_ep *_ep, struct usb_request *_req)
-{
-	struct net2280_ep	*ep;
-	struct net2280_request	*req;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || !_req)
-		return;
-
-	req = container_of (_req, struct net2280_request, req);
-	WARN_ON (!list_empty (&req->queue));
-	if (req->td)
-		pci_pool_free (ep->dev->requests, req->td, req->td_dma);
-	kfree (req);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* load a packet into the fifo we use for usb IN transfers.
- * works for all endpoints.
- *
- * NOTE: pio with ep-a..ep-d could stuff multiple packets into the fifo
- * at a time, but this code is simpler because it knows it only writes
- * one packet.  ep-a..ep-d should use dma instead.
- */
-static void
-write_fifo (struct net2280_ep *ep, struct usb_request *req)
-{
-	struct net2280_ep_regs	__iomem *regs = ep->regs;
-	u8			*buf;
-	u32			tmp;
-	unsigned		count, total;
-
-	/* INVARIANT:  fifo is currently empty. (testable) */
-
-	if (req) {
-		buf = req->buf + req->actual;
-		prefetch (buf);
-		total = req->length - req->actual;
-	} else {
-		total = 0;
-		buf = NULL;
-	}
-
-	/* write just one packet at a time */
-	count = ep->ep.maxpacket;
-	if (count > total)	/* min() cannot be used on a bitfield */
-		count = total;
-
-	VDEBUG (ep->dev, "write %s fifo (IN) %d bytes%s req %p\n",
-			ep->ep.name, count,
-			(count != ep->ep.maxpacket) ? " (short)" : "",
-			req);
-	while (count >= 4) {
-		/* NOTE be careful if you try to align these. fifo lines
-		 * should normally be full (4 bytes) and successive partial
-		 * lines are ok only in certain cases.
-		 */
-		tmp = get_unaligned ((u32 *)buf);
-		cpu_to_le32s (&tmp);
-		writel (tmp, &regs->ep_data);
-		buf += 4;
-		count -= 4;
-	}
-
-	/* last fifo entry is "short" unless we wrote a full packet.
-	 * also explicitly validate last word in (periodic) transfers
-	 * when maxpacket is not a multiple of 4 bytes.
-	 */
-	if (count || total < ep->ep.maxpacket) {
-		tmp = count ? get_unaligned ((u32 *)buf) : count;
-		cpu_to_le32s (&tmp);
-		set_fifo_bytecount (ep, count & 0x03);
-		writel (tmp, &regs->ep_data);
-	}
-
-	/* pci writes may still be posted */
-}
-
-/* work around erratum 0106: PCI and USB race over the OUT fifo.
- * caller guarantees chiprev 0100, out endpoint is NAKing, and
- * there's no real data in the fifo.
- *
- * NOTE:  also used in cases where that erratum doesn't apply:
- * where the host wrote "too much" data to us.
- */
-static void out_flush (struct net2280_ep *ep)
-{
-	u32	__iomem *statp;
-	u32	tmp;
-
-	ASSERT_OUT_NAKING (ep);
-
-	statp = &ep->regs->ep_stat;
-	writel (  (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-		| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-		, statp);
-	writel ((1 << FIFO_FLUSH), statp);
-	mb ();
-	tmp = readl (statp);
-	if (tmp & (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-			/* high speed did bulk NYET; fifo isn't filling */
-			&& ep->dev->gadget.speed == USB_SPEED_FULL) {
-		unsigned	usec;
-
-		usec = 50;		/* 64 byte bulk/interrupt */
-		handshake (statp, (1 << USB_OUT_PING_NAK_SENT),
-				(1 << USB_OUT_PING_NAK_SENT), usec);
-		/* NAK done; now CLEAR_NAK_OUT_PACKETS is safe */
-	}
-}
-
-/* unload packet(s) from the fifo we use for usb OUT transfers.
- * returns true iff the request completed, because of short packet
- * or the request buffer having filled with full packets.
- *
- * for ep-a..ep-d this will read multiple packets out when they
- * have been accepted.
- */
-static int
-read_fifo (struct net2280_ep *ep, struct net2280_request *req)
-{
-	struct net2280_ep_regs	__iomem *regs = ep->regs;
-	u8			*buf = req->req.buf + req->req.actual;
-	unsigned		count, tmp, is_short;
-	unsigned		cleanup = 0, prevent = 0;
-
-	/* erratum 0106 ... packets coming in during fifo reads might
-	 * be incompletely rejected.  not all cases have workarounds.
-	 */
-	if (ep->dev->chiprev == 0x0100
-			&& ep->dev->gadget.speed == USB_SPEED_FULL) {
-		udelay (1);
-		tmp = readl (&ep->regs->ep_stat);
-		if ((tmp & (1 << NAK_OUT_PACKETS)))
-			cleanup = 1;
-		else if ((tmp & (1 << FIFO_FULL))) {
-			start_out_naking (ep);
-			prevent = 1;
-		}
-		/* else: hope we don't see the problem */
-	}
-
-	/* never overflow the rx buffer. the fifo reads packets until
-	 * it sees a short one; we might not be ready for them all.
-	 */
-	prefetchw (buf);
-	count = readl (&regs->ep_avail);
-	if (unlikely (count == 0)) {
-		udelay (1);
-		tmp = readl (&ep->regs->ep_stat);
-		count = readl (&regs->ep_avail);
-		/* handled that data already? */
-		if (count == 0 && (tmp & (1 << NAK_OUT_PACKETS)) == 0)
-			return 0;
-	}
-
-	tmp = req->req.length - req->req.actual;
-	if (count > tmp) {
-		/* as with DMA, data overflow gets flushed */
-		if ((tmp % ep->ep.maxpacket) != 0) {
-			ERROR (ep->dev,
-				"%s out fifo %d bytes, expected %d\n",
-				ep->ep.name, count, tmp);
-			req->req.status = -EOVERFLOW;
-			cleanup = 1;
-			/* NAK_OUT_PACKETS will be set, so flushing is safe;
-			 * the next read will start with the next packet
-			 */
-		} /* else it's a ZLP, no worries */
-		count = tmp;
-	}
-	req->req.actual += count;
-
-	is_short = (count == 0) || ((count % ep->ep.maxpacket) != 0);
-
-	VDEBUG (ep->dev, "read %s fifo (OUT) %d bytes%s%s%s req %p %d/%d\n",
-			ep->ep.name, count, is_short ? " (short)" : "",
-			cleanup ? " flush" : "", prevent ? " nak" : "",
-			req, req->req.actual, req->req.length);
-
-	while (count >= 4) {
-		tmp = readl (&regs->ep_data);
-		cpu_to_le32s (&tmp);
-		put_unaligned (tmp, (u32 *)buf);
-		buf += 4;
-		count -= 4;
-	}
-	if (count) {
-		tmp = readl (&regs->ep_data);
-		/* LE conversion is implicit here: */
-		do {
-			*buf++ = (u8) tmp;
-			tmp >>= 8;
-		} while (--count);
-	}
-	if (cleanup)
-		out_flush (ep);
-	if (prevent) {
-		writel ((1 << CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-		(void) readl (&ep->regs->ep_rsp);
-	}
-
-	return is_short || ((req->req.actual == req->req.length)
-				&& !req->req.zero);
-}
-
-/* fill out dma descriptor to match a given request */
-static void
-fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
-{
-	struct net2280_dma	*td = req->td;
-	u32			dmacount = req->req.length;
-
-	/* don't let DMA continue after a short OUT packet,
-	 * so overruns can't affect the next transfer.
-	 * in case of overruns on max-size packets, we can't
-	 * stop the fifo from filling but we can flush it.
-	 */
-	if (ep->is_in)
-		dmacount |= (1 << DMA_DIRECTION);
-	if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0)
-			|| ep->dev->pdev->device != 0x2280)
-		dmacount |= (1 << END_OF_CHAIN);
-
-	req->valid = valid;
-	if (valid)
-		dmacount |= (1 << VALID_BIT);
-	if (likely(!req->req.no_interrupt || !use_dma_chaining))
-		dmacount |= (1 << DMA_DONE_INTERRUPT_ENABLE);
-
-	/* td->dmadesc = previously set by caller */
-	td->dmaaddr = cpu_to_le32 (req->req.dma);
-
-	/* 2280 may be polling VALID_BIT through ep->dma->dmadesc */
-	wmb ();
-	td->dmacount = cpu_to_le32(dmacount);
-}
-
-static const u32 dmactl_default =
-		  (1 << DMA_SCATTER_GATHER_DONE_INTERRUPT)
-		| (1 << DMA_CLEAR_COUNT_ENABLE)
-		/* erratum 0116 workaround part 1 (use POLLING) */
-		| (POLL_100_USEC << DESCRIPTOR_POLLING_RATE)
-		| (1 << DMA_VALID_BIT_POLLING_ENABLE)
-		| (1 << DMA_VALID_BIT_ENABLE)
-		| (1 << DMA_SCATTER_GATHER_ENABLE)
-		/* erratum 0116 workaround part 2 (no AUTOSTART) */
-		| (1 << DMA_ENABLE);
-
-static inline void spin_stop_dma (struct net2280_dma_regs __iomem *dma)
-{
-	handshake (&dma->dmactl, (1 << DMA_ENABLE), 0, 50);
-}
-
-static inline void stop_dma (struct net2280_dma_regs __iomem *dma)
-{
-	writel (readl (&dma->dmactl) & ~(1 << DMA_ENABLE), &dma->dmactl);
-	spin_stop_dma (dma);
-}
-
-static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
-{
-	struct net2280_dma_regs	__iomem *dma = ep->dma;
-	unsigned int tmp = (1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION);
-
-	if (ep->dev->pdev->device != 0x2280)
-		tmp |= (1 << END_OF_CHAIN);
-
-	writel (tmp, &dma->dmacount);
-	writel (readl (&dma->dmastat), &dma->dmastat);
-
-	writel (td_dma, &dma->dmadesc);
-	writel (dmactl, &dma->dmactl);
-
-	/* erratum 0116 workaround part 3:  pci arbiter away from net2280 */
-	(void) readl (&ep->dev->pci->pcimstctl);
-
-	writel ((1 << DMA_START), &dma->dmastat);
-
-	if (!ep->is_in)
-		stop_out_naking (ep);
-}
-
-static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
-{
-	u32			tmp;
-	struct net2280_dma_regs	__iomem *dma = ep->dma;
-
-	/* FIXME can't use DMA for ZLPs */
-
-	/* on this path we "know" there's no dma active (yet) */
-	WARN_ON (readl (&dma->dmactl) & (1 << DMA_ENABLE));
-	writel (0, &ep->dma->dmactl);
-
-	/* previous OUT packet might have been short */
-	if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat))
-				& (1 << NAK_OUT_PACKETS)) != 0) {
-		writel ((1 << SHORT_PACKET_TRANSFERRED_INTERRUPT),
-			&ep->regs->ep_stat);
-
-		tmp = readl (&ep->regs->ep_avail);
-		if (tmp) {
-			writel (readl (&dma->dmastat), &dma->dmastat);
-
-			/* transfer all/some fifo data */
-			writel (req->req.dma, &dma->dmaaddr);
-			tmp = min (tmp, req->req.length);
-
-			/* dma irq, faking scatterlist status */
-			req->td->dmacount = cpu_to_le32 (req->req.length - tmp);
-			writel ((1 << DMA_DONE_INTERRUPT_ENABLE)
-				| tmp, &dma->dmacount);
-			req->td->dmadesc = 0;
-			req->valid = 1;
-
-			writel ((1 << DMA_ENABLE), &dma->dmactl);
-			writel ((1 << DMA_START), &dma->dmastat);
-			return;
-		}
-	}
-
-	tmp = dmactl_default;
-
-	/* force packet boundaries between dma requests, but prevent the
-	 * controller from automagically writing a last "short" packet
-	 * (zero length) unless the driver explicitly said to do that.
-	 */
-	if (ep->is_in) {
-		if (likely ((req->req.length % ep->ep.maxpacket) != 0
-				|| req->req.zero)) {
-			tmp |= (1 << DMA_FIFO_VALIDATE);
-			ep->in_fifo_validate = 1;
-		} else
-			ep->in_fifo_validate = 0;
-	}
-
-	/* init req->td, pointing to the current dummy */
-	req->td->dmadesc = cpu_to_le32 (ep->td_dma);
-	fill_dma_desc (ep, req, 1);
-
-	if (!use_dma_chaining)
-		req->td->dmacount |= cpu_to_le32 (1 << END_OF_CHAIN);
-
-	start_queue (ep, tmp, req->td_dma);
-}
-
-static inline void
-queue_dma (struct net2280_ep *ep, struct net2280_request *req, int valid)
-{
-	struct net2280_dma	*end;
-	dma_addr_t		tmp;
-
-	/* swap new dummy for old, link; fill and maybe activate */
-	end = ep->dummy;
-	ep->dummy = req->td;
-	req->td = end;
-
-	tmp = ep->td_dma;
-	ep->td_dma = req->td_dma;
-	req->td_dma = tmp;
-
-	end->dmadesc = cpu_to_le32 (ep->td_dma);
-
-	fill_dma_desc (ep, req, valid);
-}
-
-static void
-done (struct net2280_ep *ep, struct net2280_request *req, int status)
-{
-	struct net2280		*dev;
-	unsigned		stopped = ep->stopped;
-
-	list_del_init (&req->queue);
-
-	if (req->req.status == -EINPROGRESS)
-		req->req.status = status;
-	else
-		status = req->req.status;
-
-	dev = ep->dev;
-	if (ep->dma)
-		usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
-
-	if (status && status != -ESHUTDOWN)
-		VDEBUG (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;
-	spin_unlock (&dev->lock);
-	req->req.complete (&ep->ep, &req->req);
-	spin_lock (&dev->lock);
-	ep->stopped = stopped;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
-{
-	struct net2280_request	*req;
-	struct net2280_ep	*ep;
-	struct net2280		*dev;
-	unsigned long		flags;
-
-	/* we always require a cpu-view buffer, so that we can
-	 * always use pio (as fallback or whatever).
-	 */
-	req = container_of (_req, struct net2280_request, req);
-	if (!_req || !_req->complete || !_req->buf
-			|| !list_empty (&req->queue))
-		return -EINVAL;
-	if (_req->length > (~0 & DMA_BYTE_COUNT_MASK))
-		return -EDOM;
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0))
-		return -EINVAL;
-	dev = ep->dev;
-	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-
-	/* FIXME implement PIO fallback for ZLPs with DMA */
-	if (ep->dma && _req->length == 0)
-		return -EOPNOTSUPP;
-
-	/* set up dma mapping in case the caller didn't */
-	if (ep->dma) {
-		int ret;
-
-		ret = usb_gadget_map_request(&dev->gadget, _req,
-				ep->is_in);
-		if (ret)
-			return ret;
-	}
-
-#if 0
-	VDEBUG (dev, "%s queue req %p, len %d buf %p\n",
-			_ep->name, _req, _req->length, _req->buf);
-#endif
-
-	spin_lock_irqsave (&dev->lock, flags);
-
-	_req->status = -EINPROGRESS;
-	_req->actual = 0;
-
-	/* kickstart this i/o queue? */
-	if (list_empty (&ep->queue) && !ep->stopped) {
-		/* use DMA if the endpoint supports it, else pio */
-		if (ep->dma)
-			start_dma (ep, req);
-		else {
-			/* maybe there's no control data, just status ack */
-			if (ep->num == 0 && _req->length == 0) {
-				allow_status (ep);
-				done (ep, req, 0);
-				VDEBUG (dev, "%s status ack\n", ep->ep.name);
-				goto done;
-			}
-
-			/* PIO ... stuff the fifo, or unblock it.  */
-			if (ep->is_in)
-				write_fifo (ep, _req);
-			else if (list_empty (&ep->queue)) {
-				u32	s;
-
-				/* OUT FIFO might have packet(s) buffered */
-				s = readl (&ep->regs->ep_stat);
-				if ((s & (1 << FIFO_EMPTY)) == 0) {
-					/* note:  _req->short_not_ok is
-					 * ignored here since PIO _always_
-					 * stops queue advance here, and
-					 * _req->status doesn't change for
-					 * short reads (only _req->actual)
-					 */
-					if (read_fifo (ep, req)) {
-						done (ep, req, 0);
-						if (ep->num == 0)
-							allow_status (ep);
-						/* don't queue it */
-						req = NULL;
-					} else
-						s = readl (&ep->regs->ep_stat);
-				}
-
-				/* don't NAK, let the fifo fill */
-				if (req && (s & (1 << NAK_OUT_PACKETS)))
-					writel ((1 << CLEAR_NAK_OUT_PACKETS),
-							&ep->regs->ep_rsp);
-			}
-		}
-
-	} else if (ep->dma) {
-		int	valid = 1;
-
-		if (ep->is_in) {
-			int	expect;
-
-			/* preventing magic zlps is per-engine state, not
-			 * per-transfer; irq logic must recover hiccups.
-			 */
-			expect = likely (req->req.zero
-				|| (req->req.length % ep->ep.maxpacket) != 0);
-			if (expect != ep->in_fifo_validate)
-				valid = 0;
-		}
-		queue_dma (ep, req, valid);
-
-	} /* else the irq handler advances the queue. */
-
-	ep->responded = 1;
-	if (req)
-		list_add_tail (&req->queue, &ep->queue);
-done:
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	/* pci writes may still be posted */
-	return 0;
-}
-
-static inline void
-dma_done (
-	struct net2280_ep *ep,
-	struct net2280_request *req,
-	u32 dmacount,
-	int status
-)
-{
-	req->req.actual = req->req.length - (DMA_BYTE_COUNT_MASK & dmacount);
-	done (ep, req, status);
-}
-
-static void restart_dma (struct net2280_ep *ep);
-
-static void scan_dma_completions (struct net2280_ep *ep)
-{
-	/* only look at descriptors that were "naturally" retired,
-	 * so fifo and list head state won't matter
-	 */
-	while (!list_empty (&ep->queue)) {
-		struct net2280_request	*req;
-		u32			tmp;
-
-		req = list_entry (ep->queue.next,
-				struct net2280_request, queue);
-		if (!req->valid)
-			break;
-		rmb ();
-		tmp = le32_to_cpup (&req->td->dmacount);
-		if ((tmp & (1 << VALID_BIT)) != 0)
-			break;
-
-		/* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short"
-		 * cases where DMA must be aborted; this code handles
-		 * all non-abort DMA completions.
-		 */
-		if (unlikely (req->td->dmadesc == 0)) {
-			/* paranoia */
-			tmp = readl (&ep->dma->dmacount);
-			if (tmp & DMA_BYTE_COUNT_MASK)
-				break;
-			/* single transfer mode */
-			dma_done (ep, req, tmp, 0);
-			break;
-		} else if (!ep->is_in
-				&& (req->req.length % ep->ep.maxpacket) != 0) {
-			tmp = readl (&ep->regs->ep_stat);
-
-			/* AVOID TROUBLE HERE by not issuing short reads from
-			 * your gadget driver.  That helps avoids errata 0121,
-			 * 0122, and 0124; not all cases trigger the warning.
-			 */
-			if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
-				WARNING (ep->dev, "%s lost packet sync!\n",
-						ep->ep.name);
-				req->req.status = -EOVERFLOW;
-			} else if ((tmp = readl (&ep->regs->ep_avail)) != 0) {
-				/* fifo gets flushed later */
-				ep->out_overflow = 1;
-				DEBUG (ep->dev, "%s dma, discard %d len %d\n",
-						ep->ep.name, tmp,
-						req->req.length);
-				req->req.status = -EOVERFLOW;
-			}
-		}
-		dma_done (ep, req, tmp, 0);
-	}
-}
-
-static void restart_dma (struct net2280_ep *ep)
-{
-	struct net2280_request	*req;
-	u32			dmactl = dmactl_default;
-
-	if (ep->stopped)
-		return;
-	req = list_entry (ep->queue.next, struct net2280_request, queue);
-
-	if (!use_dma_chaining) {
-		start_dma (ep, req);
-		return;
-	}
-
-	/* the 2280 will be processing the queue unless queue hiccups after
-	 * the previous transfer:
-	 *  IN:   wanted automagic zlp, head doesn't (or vice versa)
-	 *        DMA_FIFO_VALIDATE doesn't init from dma descriptors.
-	 *  OUT:  was "usb-short", we must restart.
-	 */
-	if (ep->is_in && !req->valid) {
-		struct net2280_request	*entry, *prev = NULL;
-		int			reqmode, done = 0;
-
-		DEBUG (ep->dev, "%s dma hiccup td %p\n", ep->ep.name, req->td);
-		ep->in_fifo_validate = likely (req->req.zero
-			|| (req->req.length % ep->ep.maxpacket) != 0);
-		if (ep->in_fifo_validate)
-			dmactl |= (1 << DMA_FIFO_VALIDATE);
-		list_for_each_entry (entry, &ep->queue, queue) {
-			__le32		dmacount;
-
-			if (entry == req)
-				continue;
-			dmacount = entry->td->dmacount;
-			if (!done) {
-				reqmode = likely (entry->req.zero
-					|| (entry->req.length
-						% ep->ep.maxpacket) != 0);
-				if (reqmode == ep->in_fifo_validate) {
-					entry->valid = 1;
-					dmacount |= valid_bit;
-					entry->td->dmacount = dmacount;
-					prev = entry;
-					continue;
-				} else {
-					/* force a hiccup */
-					prev->td->dmacount |= dma_done_ie;
-					done = 1;
-				}
-			}
-
-			/* walk the rest of the queue so unlinks behave */
-			entry->valid = 0;
-			dmacount &= ~valid_bit;
-			entry->td->dmacount = dmacount;
-			prev = entry;
-		}
-	}
-
-	writel (0, &ep->dma->dmactl);
-	start_queue (ep, dmactl, req->td_dma);
-}
-
-static void abort_dma (struct net2280_ep *ep)
-{
-	/* abort the current transfer */
-	if (likely (!list_empty (&ep->queue))) {
-		/* FIXME work around errata 0121, 0122, 0124 */
-		writel ((1 << DMA_ABORT), &ep->dma->dmastat);
-		spin_stop_dma (ep->dma);
-	} else
-		stop_dma (ep->dma);
-	scan_dma_completions (ep);
-}
-
-/* dequeue ALL requests */
-static void nuke (struct net2280_ep *ep)
-{
-	struct net2280_request	*req;
-
-	/* called with spinlock held */
-	ep->stopped = 1;
-	if (ep->dma)
-		abort_dma (ep);
-	while (!list_empty (&ep->queue)) {
-		req = list_entry (ep->queue.next,
-				struct net2280_request,
-				queue);
-		done (ep, req, -ESHUTDOWN);
-	}
-}
-
-/* dequeue JUST ONE request */
-static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req)
-{
-	struct net2280_ep	*ep;
-	struct net2280_request	*req;
-	unsigned long		flags;
-	u32			dmactl;
-	int			stopped;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0) || !_req)
-		return -EINVAL;
-
-	spin_lock_irqsave (&ep->dev->lock, flags);
-	stopped = ep->stopped;
-
-	/* quiesce dma while we patch the queue */
-	dmactl = 0;
-	ep->stopped = 1;
-	if (ep->dma) {
-		dmactl = readl (&ep->dma->dmactl);
-		/* WARNING erratum 0127 may kick in ... */
-		stop_dma (ep->dma);
-		scan_dma_completions (ep);
-	}
-
-	/* make sure it's still queued on this endpoint */
-	list_for_each_entry (req, &ep->queue, queue) {
-		if (&req->req == _req)
-			break;
-	}
-	if (&req->req != _req) {
-		spin_unlock_irqrestore (&ep->dev->lock, flags);
-		return -EINVAL;
-	}
-
-	/* queue head may be partially complete. */
-	if (ep->queue.next == &req->queue) {
-		if (ep->dma) {
-			DEBUG (ep->dev, "unlink (%s) dma\n", _ep->name);
-			_req->status = -ECONNRESET;
-			abort_dma (ep);
-			if (likely (ep->queue.next == &req->queue)) {
-				// NOTE: misreports single-transfer mode
-				req->td->dmacount = 0;	/* invalidate */
-				dma_done (ep, req,
-					readl (&ep->dma->dmacount),
-					-ECONNRESET);
-			}
-		} else {
-			DEBUG (ep->dev, "unlink (%s) pio\n", _ep->name);
-			done (ep, req, -ECONNRESET);
-		}
-		req = NULL;
-
-	/* patch up hardware chaining data */
-	} else if (ep->dma && use_dma_chaining) {
-		if (req->queue.prev == ep->queue.next) {
-			writel (le32_to_cpu (req->td->dmadesc),
-				&ep->dma->dmadesc);
-			if (req->td->dmacount & dma_done_ie)
-				writel (readl (&ep->dma->dmacount)
-						| le32_to_cpu(dma_done_ie),
-					&ep->dma->dmacount);
-		} else {
-			struct net2280_request	*prev;
-
-			prev = list_entry (req->queue.prev,
-				struct net2280_request, queue);
-			prev->td->dmadesc = req->td->dmadesc;
-			if (req->td->dmacount & dma_done_ie)
-				prev->td->dmacount |= dma_done_ie;
-		}
-	}
-
-	if (req)
-		done (ep, req, -ECONNRESET);
-	ep->stopped = stopped;
-
-	if (ep->dma) {
-		/* turn off dma on inactive queues */
-		if (list_empty (&ep->queue))
-			stop_dma (ep->dma);
-		else if (!ep->stopped) {
-			/* resume current request, or start new one */
-			if (req)
-				writel (dmactl, &ep->dma->dmactl);
-			else
-				start_dma (ep, list_entry (ep->queue.next,
-					struct net2280_request, queue));
-		}
-	}
-
-	spin_unlock_irqrestore (&ep->dev->lock, flags);
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int net2280_fifo_status (struct usb_ep *_ep);
-
-static int
-net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
-{
-	struct net2280_ep	*ep;
-	unsigned long		flags;
-	int			retval = 0;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0))
-		return -EINVAL;
-	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-	if (ep->desc /* not ep0 */ && (ep->desc->bmAttributes & 0x03)
-						== USB_ENDPOINT_XFER_ISOC)
-		return -EINVAL;
-
-	spin_lock_irqsave (&ep->dev->lock, flags);
-	if (!list_empty (&ep->queue))
-		retval = -EAGAIN;
-	else if (ep->is_in && value && net2280_fifo_status (_ep) != 0)
-		retval = -EAGAIN;
-	else {
-		VDEBUG (ep->dev, "%s %s %s\n", _ep->name,
-				value ? "set" : "clear",
-				wedged ? "wedge" : "halt");
-		/* set/clear, then synch memory views with the device */
-		if (value) {
-			if (ep->num == 0)
-				ep->dev->protocol_stall = 1;
-			else
-				set_halt (ep);
-			if (wedged)
-				ep->wedged = 1;
-		} else {
-			clear_halt (ep);
-			ep->wedged = 0;
-		}
-		(void) readl (&ep->regs->ep_rsp);
-	}
-	spin_unlock_irqrestore (&ep->dev->lock, flags);
-
-	return retval;
-}
-
-static int
-net2280_set_halt(struct usb_ep *_ep, int value)
-{
-	return net2280_set_halt_and_wedge(_ep, value, 0);
-}
-
-static int
-net2280_set_wedge(struct usb_ep *_ep)
-{
-	if (!_ep || _ep->name == ep0name)
-		return -EINVAL;
-	return net2280_set_halt_and_wedge(_ep, 1, 1);
-}
-
-static int
-net2280_fifo_status (struct usb_ep *_ep)
-{
-	struct net2280_ep	*ep;
-	u32			avail;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0))
-		return -ENODEV;
-	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-
-	avail = readl (&ep->regs->ep_avail) & ((1 << 12) - 1);
-	if (avail > ep->fifo_size)
-		return -EOVERFLOW;
-	if (ep->is_in)
-		avail = ep->fifo_size - avail;
-	return avail;
-}
-
-static void
-net2280_fifo_flush (struct usb_ep *_ep)
-{
-	struct net2280_ep	*ep;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0))
-		return;
-	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return;
-
-	writel ((1 << FIFO_FLUSH), &ep->regs->ep_stat);
-	(void) readl (&ep->regs->ep_rsp);
-}
-
-static const struct usb_ep_ops net2280_ep_ops = {
-	.enable		= net2280_enable,
-	.disable	= net2280_disable,
-
-	.alloc_request	= net2280_alloc_request,
-	.free_request	= net2280_free_request,
-
-	.queue		= net2280_queue,
-	.dequeue	= net2280_dequeue,
-
-	.set_halt	= net2280_set_halt,
-	.set_wedge	= net2280_set_wedge,
-	.fifo_status	= net2280_fifo_status,
-	.fifo_flush	= net2280_fifo_flush,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int net2280_get_frame (struct usb_gadget *_gadget)
-{
-	struct net2280		*dev;
-	unsigned long		flags;
-	u16			retval;
-
-	if (!_gadget)
-		return -ENODEV;
-	dev = container_of (_gadget, struct net2280, gadget);
-	spin_lock_irqsave (&dev->lock, flags);
-	retval = get_idx_reg (dev->regs, REG_FRAME) & 0x03ff;
-	spin_unlock_irqrestore (&dev->lock, flags);
-	return retval;
-}
-
-static int net2280_wakeup (struct usb_gadget *_gadget)
-{
-	struct net2280		*dev;
-	u32			tmp;
-	unsigned long		flags;
-
-	if (!_gadget)
-		return 0;
-	dev = container_of (_gadget, struct net2280, gadget);
-
-	spin_lock_irqsave (&dev->lock, flags);
-	tmp = readl (&dev->usb->usbctl);
-	if (tmp & (1 << DEVICE_REMOTE_WAKEUP_ENABLE))
-		writel (1 << GENERATE_RESUME, &dev->usb->usbstat);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	/* pci writes may still be posted */
-	return 0;
-}
-
-static int net2280_set_selfpowered (struct usb_gadget *_gadget, int value)
-{
-	struct net2280		*dev;
-	u32			tmp;
-	unsigned long		flags;
-
-	if (!_gadget)
-		return 0;
-	dev = container_of (_gadget, struct net2280, gadget);
-
-	spin_lock_irqsave (&dev->lock, flags);
-	tmp = readl (&dev->usb->usbctl);
-	if (value)
-		tmp |= (1 << SELF_POWERED_STATUS);
-	else
-		tmp &= ~(1 << SELF_POWERED_STATUS);
-	writel (tmp, &dev->usb->usbctl);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	return 0;
-}
-
-static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
-{
-	struct net2280  *dev;
-	u32             tmp;
-	unsigned long   flags;
-
-	if (!_gadget)
-		return -ENODEV;
-	dev = container_of (_gadget, struct net2280, gadget);
-
-	spin_lock_irqsave (&dev->lock, flags);
-	tmp = readl (&dev->usb->usbctl);
-	dev->softconnect = (is_on != 0);
-	if (is_on)
-		tmp |= (1 << USB_DETECT_ENABLE);
-	else
-		tmp &= ~(1 << USB_DETECT_ENABLE);
-	writel (tmp, &dev->usb->usbctl);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	return 0;
-}
-
-static int net2280_start(struct usb_gadget *_gadget,
-		struct usb_gadget_driver *driver);
-static int net2280_stop(struct usb_gadget *_gadget,
-		struct usb_gadget_driver *driver);
-
-static const struct usb_gadget_ops net2280_ops = {
-	.get_frame	= net2280_get_frame,
-	.wakeup		= net2280_wakeup,
-	.set_selfpowered = net2280_set_selfpowered,
-	.pullup		= net2280_pullup,
-	.udc_start	= net2280_start,
-	.udc_stop	= net2280_stop,
-};
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	CONFIG_USB_GADGET_DEBUG_FILES
-
-/* FIXME move these into procfs, and use seq_file.
- * Sysfs _still_ doesn't behave for arbitrarily sized files,
- * and also doesn't help products using this with 2.4 kernels.
- */
-
-/* "function" sysfs attribute */
-static ssize_t function_show(struct device *_dev, struct device_attribute *attr,
-			     char *buf)
-{
-	struct net2280	*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_RO(function);
-
-static ssize_t registers_show(struct device *_dev,
-			      struct device_attribute *attr, char *buf)
-{
-	struct net2280		*dev;
-	char			*next;
-	unsigned		size, t;
-	unsigned long		flags;
-	int			i;
-	u32			t1, t2;
-	const char		*s;
-
-	dev = dev_get_drvdata (_dev);
-	next = buf;
-	size = PAGE_SIZE;
-	spin_lock_irqsave (&dev->lock, flags);
-
-	if (dev->driver)
-		s = dev->driver->driver.name;
-	else
-		s = "(none)";
-
-	/* Main Control Registers */
-	t = scnprintf (next, size, "%s version " DRIVER_VERSION
-			", chiprev %04x, dma %s\n\n"
-			"devinit %03x fifoctl %08x gadget '%s'\n"
-			"pci irqenb0 %02x irqenb1 %08x "
-			"irqstat0 %04x irqstat1 %08x\n",
-			driver_name, dev->chiprev,
-			use_dma
-				? (use_dma_chaining ? "chaining" : "enabled")
-				: "disabled",
-			readl (&dev->regs->devinit),
-			readl (&dev->regs->fifoctl),
-			s,
-			readl (&dev->regs->pciirqenb0),
-			readl (&dev->regs->pciirqenb1),
-			readl (&dev->regs->irqstat0),
-			readl (&dev->regs->irqstat1));
-	size -= t;
-	next += t;
-
-	/* USB Control Registers */
-	t1 = readl (&dev->usb->usbctl);
-	t2 = readl (&dev->usb->usbstat);
-	if (t1 & (1 << VBUS_PIN)) {
-		if (t2 & (1 << HIGH_SPEED))
-			s = "high speed";
-		else if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-			s = "powered";
-		else
-			s = "full speed";
-		/* full speed bit (6) not working?? */
-	} else
-			s = "not attached";
-	t = scnprintf (next, size,
-			"stdrsp %08x usbctl %08x usbstat %08x "
-				"addr 0x%02x (%s)\n",
-			readl (&dev->usb->stdrsp), t1, t2,
-			readl (&dev->usb->ouraddr), s);
-	size -= t;
-	next += t;
-
-	/* PCI Master Control Registers */
-
-	/* DMA Control Registers */
-
-	/* Configurable EP Control Registers */
-	for (i = 0; i < 7; i++) {
-		struct net2280_ep	*ep;
-
-		ep = &dev->ep [i];
-		if (i && !ep->desc)
-			continue;
-
-		t1 = readl (&ep->regs->ep_cfg);
-		t2 = readl (&ep->regs->ep_rsp) & 0xff;
-		t = scnprintf (next, size,
-				"\n%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s"
-					"irqenb %02x\n",
-				ep->ep.name, t1, t2,
-				(t2 & (1 << CLEAR_NAK_OUT_PACKETS))
-					? "NAK " : "",
-				(t2 & (1 << CLEAR_EP_HIDE_STATUS_PHASE))
-					? "hide " : "",
-				(t2 & (1 << CLEAR_EP_FORCE_CRC_ERROR))
-					? "CRC " : "",
-				(t2 & (1 << CLEAR_INTERRUPT_MODE))
-					? "interrupt " : "",
-				(t2 & (1<<CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE))
-					? "status " : "",
-				(t2 & (1 << CLEAR_NAK_OUT_PACKETS_MODE))
-					? "NAKmode " : "",
-				(t2 & (1 << CLEAR_ENDPOINT_TOGGLE))
-					? "DATA1 " : "DATA0 ",
-				(t2 & (1 << CLEAR_ENDPOINT_HALT))
-					? "HALT " : "",
-				readl (&ep->regs->ep_irqenb));
-		size -= t;
-		next += t;
-
-		t = scnprintf (next, size,
-				"\tstat %08x avail %04x "
-				"(ep%d%s-%s)%s\n",
-				readl (&ep->regs->ep_stat),
-				readl (&ep->regs->ep_avail),
-				t1 & 0x0f, DIR_STRING (t1),
-				type_string (t1 >> 8),
-				ep->stopped ? "*" : "");
-		size -= t;
-		next += t;
-
-		if (!ep->dma)
-			continue;
-
-		t = scnprintf (next, size,
-				"  dma\tctl %08x stat %08x count %08x\n"
-				"\taddr %08x desc %08x\n",
-				readl (&ep->dma->dmactl),
-				readl (&ep->dma->dmastat),
-				readl (&ep->dma->dmacount),
-				readl (&ep->dma->dmaaddr),
-				readl (&ep->dma->dmadesc));
-		size -= t;
-		next += t;
-
-	}
-
-	/* Indexed Registers */
-		// none yet
-
-	/* Statistics */
-	t = scnprintf (next, size, "\nirqs:  ");
-	size -= t;
-	next += t;
-	for (i = 0; i < 7; i++) {
-		struct net2280_ep	*ep;
-
-		ep = &dev->ep [i];
-		if (i && !ep->irqs)
-			continue;
-		t = scnprintf (next, size, " %s/%lu", ep->ep.name, ep->irqs);
-		size -= t;
-		next += t;
-
-	}
-	t = scnprintf (next, size, "\n");
-	size -= t;
-	next += t;
-
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	return PAGE_SIZE - size;
-}
-static DEVICE_ATTR_RO(registers);
-
-static ssize_t queues_show(struct device *_dev, struct device_attribute *attr,
-			   char *buf)
-{
-	struct net2280		*dev;
-	char			*next;
-	unsigned		size;
-	unsigned long		flags;
-	int			i;
-
-	dev = dev_get_drvdata (_dev);
-	next = buf;
-	size = PAGE_SIZE;
-	spin_lock_irqsave (&dev->lock, flags);
-
-	for (i = 0; i < 7; i++) {
-		struct net2280_ep		*ep = &dev->ep [i];
-		struct net2280_request		*req;
-		int				t;
-
-		if (i != 0) {
-			const struct usb_endpoint_descriptor	*d;
-
-			d = ep->desc;
-			if (!d)
-				continue;
-			t = d->bEndpointAddress;
-			t = scnprintf (next, size,
-				"\n%s (ep%d%s-%s) max %04x %s fifo %d\n",
-				ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK,
-				(t & USB_DIR_IN) ? "in" : "out",
-				({ char *val;
-				 switch (d->bmAttributes & 0x03) {
-				 case USB_ENDPOINT_XFER_BULK:
-					val = "bulk"; break;
-				 case USB_ENDPOINT_XFER_INT:
-					val = "intr"; break;
-				 default:
-					val = "iso"; break;
-				 } val; }),
-				usb_endpoint_maxp (d) & 0x1fff,
-				ep->dma ? "dma" : "pio", ep->fifo_size
-				);
-		} else /* ep0 should only have one transfer queued */
-			t = scnprintf (next, size, "ep0 max 64 pio %s\n",
-					ep->is_in ? "in" : "out");
-		if (t <= 0 || t > size)
-			goto done;
-		size -= t;
-		next += t;
-
-		if (list_empty (&ep->queue)) {
-			t = scnprintf (next, size, "\t(nothing queued)\n");
-			if (t <= 0 || t > size)
-				goto done;
-			size -= t;
-			next += t;
-			continue;
-		}
-		list_for_each_entry (req, &ep->queue, queue) {
-			if (ep->dma && req->td_dma == readl (&ep->dma->dmadesc))
-				t = scnprintf (next, size,
-					"\treq %p len %d/%d "
-					"buf %p (dmacount %08x)\n",
-					&req->req, req->req.actual,
-					req->req.length, req->req.buf,
-					readl (&ep->dma->dmacount));
-			else
-				t = scnprintf (next, size,
-					"\treq %p len %d/%d buf %p\n",
-					&req->req, req->req.actual,
-					req->req.length, req->req.buf);
-			if (t <= 0 || t > size)
-				goto done;
-			size -= t;
-			next += t;
-
-			if (ep->dma) {
-				struct net2280_dma	*td;
-
-				td = req->td;
-				t = scnprintf (next, size, "\t    td %08x "
-					" count %08x buf %08x desc %08x\n",
-					(u32) req->td_dma,
-					le32_to_cpu (td->dmacount),
-					le32_to_cpu (td->dmaaddr),
-					le32_to_cpu (td->dmadesc));
-				if (t <= 0 || t > size)
-					goto done;
-				size -= t;
-				next += t;
-			}
-		}
-	}
-
-done:
-	spin_unlock_irqrestore (&dev->lock, flags);
-	return PAGE_SIZE - size;
-}
-static DEVICE_ATTR_RO(queues);
-
-
-#else
-
-#define device_create_file(a,b)	(0)
-#define device_remove_file(a,b)	do { } while (0)
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/* another driver-specific mode might be a request type doing dma
- * to/from another device fifo instead of to/from memory.
- */
-
-static void set_fifo_mode (struct net2280 *dev, int mode)
-{
-	/* keeping high bits preserves BAR2 */
-	writel ((0xffff << PCI_BASE2_RANGE) | mode, &dev->regs->fifoctl);
-
-	/* always ep-{a,b,e,f} ... maybe not ep-c or ep-d */
-	INIT_LIST_HEAD (&dev->gadget.ep_list);
-	list_add_tail (&dev->ep [1].ep.ep_list, &dev->gadget.ep_list);
-	list_add_tail (&dev->ep [2].ep.ep_list, &dev->gadget.ep_list);
-	switch (mode) {
-	case 0:
-		list_add_tail (&dev->ep [3].ep.ep_list, &dev->gadget.ep_list);
-		list_add_tail (&dev->ep [4].ep.ep_list, &dev->gadget.ep_list);
-		dev->ep [1].fifo_size = dev->ep [2].fifo_size = 1024;
-		break;
-	case 1:
-		dev->ep [1].fifo_size = dev->ep [2].fifo_size = 2048;
-		break;
-	case 2:
-		list_add_tail (&dev->ep [3].ep.ep_list, &dev->gadget.ep_list);
-		dev->ep [1].fifo_size = 2048;
-		dev->ep [2].fifo_size = 1024;
-		break;
-	}
-	/* fifo sizes for ep0, ep-c, ep-d, ep-e, and ep-f never change */
-	list_add_tail (&dev->ep [5].ep.ep_list, &dev->gadget.ep_list);
-	list_add_tail (&dev->ep [6].ep.ep_list, &dev->gadget.ep_list);
-}
-
-/* keeping it simple:
- * - one bus driver, initted first;
- * - one function driver, initted second
- *
- * most of the work to support multiple net2280 controllers would
- * be to associate this gadget driver (yes?) with all of them, or
- * perhaps to bind specific drivers to specific devices.
- */
-
-static void usb_reset (struct net2280 *dev)
-{
-	u32	tmp;
-
-	dev->gadget.speed = USB_SPEED_UNKNOWN;
-	(void) readl (&dev->usb->usbctl);
-
-	net2280_led_init (dev);
-
-	/* disable automatic responses, and irqs */
-	writel (0, &dev->usb->stdrsp);
-	writel (0, &dev->regs->pciirqenb0);
-	writel (0, &dev->regs->pciirqenb1);
-
-	/* clear old dma and irq state */
-	for (tmp = 0; tmp < 4; tmp++) {
-		struct net2280_ep	*ep = &dev->ep [tmp + 1];
-
-		if (ep->dma)
-			abort_dma (ep);
-	}
-	writel (~0, &dev->regs->irqstat0),
-	writel (~(1 << SUSPEND_REQUEST_INTERRUPT), &dev->regs->irqstat1),
-
-	/* reset, and enable pci */
-	tmp = readl (&dev->regs->devinit)
-		| (1 << PCI_ENABLE)
-		| (1 << FIFO_SOFT_RESET)
-		| (1 << USB_SOFT_RESET)
-		| (1 << M8051_RESET);
-	writel (tmp, &dev->regs->devinit);
-
-	/* standard fifo and endpoint allocations */
-	set_fifo_mode (dev, (fifo_mode <= 2) ? fifo_mode : 0);
-}
-
-static void usb_reinit (struct net2280 *dev)
-{
-	u32	tmp;
-	int	init_dma;
-
-	/* use_dma changes are ignored till next device re-init */
-	init_dma = use_dma;
-
-	/* basic endpoint init */
-	for (tmp = 0; tmp < 7; tmp++) {
-		struct net2280_ep	*ep = &dev->ep [tmp];
-
-		ep->ep.name = ep_name [tmp];
-		ep->dev = dev;
-		ep->num = tmp;
-
-		if (tmp > 0 && tmp <= 4) {
-			ep->fifo_size = 1024;
-			if (init_dma)
-				ep->dma = &dev->dma [tmp - 1];
-		} else
-			ep->fifo_size = 64;
-		ep->regs = &dev->epregs [tmp];
-		ep_reset (dev->regs, ep);
-	}
-	usb_ep_set_maxpacket_limit(&dev->ep [0].ep, 64);
-	usb_ep_set_maxpacket_limit(&dev->ep [5].ep, 64);
-	usb_ep_set_maxpacket_limit(&dev->ep [6].ep, 64);
-
-	dev->gadget.ep0 = &dev->ep [0].ep;
-	dev->ep [0].stopped = 0;
-	INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
-
-	/* we want to prevent lowlevel/insecure access from the USB host,
-	 * but erratum 0119 means this enable bit is ignored
-	 */
-	for (tmp = 0; tmp < 5; tmp++)
-		writel (EP_DONTUSE, &dev->dep [tmp].dep_cfg);
-}
-
-static void ep0_start (struct net2280 *dev)
-{
-	writel (  (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-		| (1 << CLEAR_NAK_OUT_PACKETS)
-		| (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
-		, &dev->epregs [0].ep_rsp);
-
-	/*
-	 * hardware optionally handles a bunch of standard requests
-	 * that the API hides from drivers anyway.  have it do so.
-	 * endpoint status/features are handled in software, to
-	 * help pass tests for some dubious behavior.
-	 */
-	writel (  (1 << SET_TEST_MODE)
-		| (1 << SET_ADDRESS)
-		| (1 << DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP)
-		| (1 << GET_DEVICE_STATUS)
-		| (1 << GET_INTERFACE_STATUS)
-		, &dev->usb->stdrsp);
-	writel (  (1 << USB_ROOT_PORT_WAKEUP_ENABLE)
-		| (1 << SELF_POWERED_USB_DEVICE)
-		| (1 << REMOTE_WAKEUP_SUPPORT)
-		| (dev->softconnect << USB_DETECT_ENABLE)
-		| (1 << SELF_POWERED_STATUS)
-		, &dev->usb->usbctl);
-
-	/* enable irqs so we can see ep0 and general operation  */
-	writel (  (1 << SETUP_PACKET_INTERRUPT_ENABLE)
-		| (1 << ENDPOINT_0_INTERRUPT_ENABLE)
-		, &dev->regs->pciirqenb0);
-	writel (  (1 << PCI_INTERRUPT_ENABLE)
-		| (1 << PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE)
-		| (1 << PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE)
-		| (1 << PCI_RETRY_ABORT_INTERRUPT_ENABLE)
-		| (1 << VBUS_INTERRUPT_ENABLE)
-		| (1 << ROOT_PORT_RESET_INTERRUPT_ENABLE)
-		| (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE)
-		, &dev->regs->pciirqenb1);
-
-	/* don't leave any writes posted */
-	(void) readl (&dev->usb->usbctl);
-}
-
-/* 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.
- */
-static int net2280_start(struct usb_gadget *_gadget,
-		struct usb_gadget_driver *driver)
-{
-	struct net2280		*dev;
-	int			retval;
-	unsigned		i;
-
-	/* insist on high speed support from the driver, since
-	 * (dev->usb->xcvrdiag & FORCE_FULL_SPEED_MODE)
-	 * "must not be used in normal operation"
-	 */
-	if (!driver || driver->max_speed < USB_SPEED_HIGH
-			|| !driver->setup)
-		return -EINVAL;
-
-	dev = container_of (_gadget, struct net2280, gadget);
-
-	for (i = 0; i < 7; i++)
-		dev->ep [i].irqs = 0;
-
-	/* hook up the driver ... */
-	dev->softconnect = 1;
-	driver->driver.bus = NULL;
-	dev->driver = driver;
-
-	retval = device_create_file (&dev->pdev->dev, &dev_attr_function);
-	if (retval) goto err_unbind;
-	retval = device_create_file (&dev->pdev->dev, &dev_attr_queues);
-	if (retval) goto err_func;
-
-	/* Enable force-full-speed testing mode, if desired */
-	if (full_speed)
-		writel(1 << FORCE_FULL_SPEED_MODE, &dev->usb->xcvrdiag);
-
-	/* ... then enable host detection and ep0; and we're ready
-	 * for set_configuration as well as eventual disconnect.
-	 */
-	net2280_led_active (dev, 1);
-	ep0_start (dev);
-
-	DEBUG (dev, "%s ready, usbctl %08x stdrsp %08x\n",
-			driver->driver.name,
-			readl (&dev->usb->usbctl),
-			readl (&dev->usb->stdrsp));
-
-	/* pci writes may still be posted */
-	return 0;
-
-err_func:
-	device_remove_file (&dev->pdev->dev, &dev_attr_function);
-err_unbind:
-	dev->driver = NULL;
-	return retval;
-}
-
-static void
-stop_activity (struct net2280 *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;
-
-	/* stop hardware; prevent new request submissions;
-	 * and kill any outstanding requests.
-	 */
-	usb_reset (dev);
-	for (i = 0; i < 7; i++)
-		nuke (&dev->ep [i]);
-
-	/* report disconnect; the driver is already quiesced */
-	if (driver) {
-		spin_unlock(&dev->lock);
-		driver->disconnect(&dev->gadget);
-		spin_lock(&dev->lock);
-	}
-
-	usb_reinit (dev);
-}
-
-static int net2280_stop(struct usb_gadget *_gadget,
-		struct usb_gadget_driver *driver)
-{
-	struct net2280	*dev;
-	unsigned long	flags;
-
-	dev = container_of (_gadget, struct net2280, gadget);
-
-	spin_lock_irqsave (&dev->lock, flags);
-	stop_activity (dev, driver);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	dev->driver = NULL;
-
-	net2280_led_active (dev, 0);
-
-	/* Disable full-speed test mode */
-	writel(0, &dev->usb->xcvrdiag);
-
-	device_remove_file (&dev->pdev->dev, &dev_attr_function);
-	device_remove_file (&dev->pdev->dev, &dev_attr_queues);
-
-	DEBUG(dev, "unregistered driver '%s'\n",
-			driver ? driver->driver.name : "");
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* handle ep0, ep-e, ep-f with 64 byte packets: packet per irq.
- * also works for dma-capable endpoints, in pio mode or just
- * to manually advance the queue after short OUT transfers.
- */
-static void handle_ep_small (struct net2280_ep *ep)
-{
-	struct net2280_request	*req;
-	u32			t;
-	/* 0 error, 1 mid-data, 2 done */
-	int			mode = 1;
-
-	if (!list_empty (&ep->queue))
-		req = list_entry (ep->queue.next,
-			struct net2280_request, queue);
-	else
-		req = NULL;
-
-	/* ack all, and handle what we care about */
-	t = readl (&ep->regs->ep_stat);
-	ep->irqs++;
-#if 0
-	VDEBUG (ep->dev, "%s ack ep_stat %08x, req %p\n",
-			ep->ep.name, t, req ? &req->req : 0);
-#endif
-	if (!ep->is_in || ep->dev->pdev->device == 0x2280)
-		writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat);
-	else
-		/* Added for 2282 */
-		writel (t, &ep->regs->ep_stat);
-
-	/* for ep0, monitor token irqs to catch data stage length errors
-	 * and to synchronize on status.
-	 *
-	 * also, to defer reporting of protocol stalls ... here's where
-	 * data or status first appears, handling stalls here should never
-	 * cause trouble on the host side..
-	 *
-	 * control requests could be slightly faster without token synch for
-	 * status, but status can jam up that way.
-	 */
-	if (unlikely (ep->num == 0)) {
-		if (ep->is_in) {
-			/* status; stop NAKing */
-			if (t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT)) {
-				if (ep->dev->protocol_stall) {
-					ep->stopped = 1;
-					set_halt (ep);
-				}
-				if (!req)
-					allow_status (ep);
-				mode = 2;
-			/* reply to extra IN data tokens with a zlp */
-			} else if (t & (1 << DATA_IN_TOKEN_INTERRUPT)) {
-				if (ep->dev->protocol_stall) {
-					ep->stopped = 1;
-					set_halt (ep);
-					mode = 2;
-				} else if (ep->responded &&
-						!req && !ep->stopped)
-					write_fifo (ep, NULL);
-			}
-		} else {
-			/* status; stop NAKing */
-			if (t & (1 << DATA_IN_TOKEN_INTERRUPT)) {
-				if (ep->dev->protocol_stall) {
-					ep->stopped = 1;
-					set_halt (ep);
-				}
-				mode = 2;
-			/* an extra OUT token is an error */
-			} else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT))
-					&& req
-					&& req->req.actual == req->req.length)
-					|| (ep->responded && !req)) {
-				ep->dev->protocol_stall = 1;
-				set_halt (ep);
-				ep->stopped = 1;
-				if (req)
-					done (ep, req, -EOVERFLOW);
-				req = NULL;
-			}
-		}
-	}
-
-	if (unlikely (!req))
-		return;
-
-	/* manual DMA queue advance after short OUT */
-	if (likely (ep->dma)) {
-		if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
-			u32	count;
-			int	stopped = ep->stopped;
-
-			/* TRANSFERRED works around OUT_DONE erratum 0112.
-			 * we expect (N <= maxpacket) bytes; host wrote M.
-			 * iff (M < N) we won't ever see a DMA interrupt.
-			 */
-			ep->stopped = 1;
-			for (count = 0; ; t = readl (&ep->regs->ep_stat)) {
-
-				/* any preceding dma transfers must finish.
-				 * dma handles (M >= N), may empty the queue
-				 */
-				scan_dma_completions (ep);
-				if (unlikely (list_empty (&ep->queue)
-						|| ep->out_overflow)) {
-					req = NULL;
-					break;
-				}
-				req = list_entry (ep->queue.next,
-					struct net2280_request, queue);
-
-				/* here either (M < N), a "real" short rx;
-				 * or (M == N) and the queue didn't empty
-				 */
-				if (likely (t & (1 << FIFO_EMPTY))) {
-					count = readl (&ep->dma->dmacount);
-					count &= DMA_BYTE_COUNT_MASK;
-					if (readl (&ep->dma->dmadesc)
-							!= req->td_dma)
-						req = NULL;
-					break;
-				}
-				udelay(1);
-			}
-
-			/* stop DMA, leave ep NAKing */
-			writel ((1 << DMA_ABORT), &ep->dma->dmastat);
-			spin_stop_dma (ep->dma);
-
-			if (likely (req)) {
-				req->td->dmacount = 0;
-				t = readl (&ep->regs->ep_avail);
-				dma_done (ep, req, count,
-					(ep->out_overflow || t)
-						? -EOVERFLOW : 0);
-			}
-
-			/* also flush to prevent erratum 0106 trouble */
-			if (unlikely (ep->out_overflow
-					|| (ep->dev->chiprev == 0x0100
-						&& ep->dev->gadget.speed
-							== USB_SPEED_FULL))) {
-				out_flush (ep);
-				ep->out_overflow = 0;
-			}
-
-			/* (re)start dma if needed, stop NAKing */
-			ep->stopped = stopped;
-			if (!list_empty (&ep->queue))
-				restart_dma (ep);
-		} else
-			DEBUG (ep->dev, "%s dma ep_stat %08x ??\n",
-					ep->ep.name, t);
-		return;
-
-	/* data packet(s) received (in the fifo, OUT) */
-	} else if (t & (1 << DATA_PACKET_RECEIVED_INTERRUPT)) {
-		if (read_fifo (ep, req) && ep->num != 0)
-			mode = 2;
-
-	/* data packet(s) transmitted (IN) */
-	} else if (t & (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)) {
-		unsigned	len;
-
-		len = req->req.length - req->req.actual;
-		if (len > ep->ep.maxpacket)
-			len = ep->ep.maxpacket;
-		req->req.actual += len;
-
-		/* if we wrote it all, we're usually done */
-		if (req->req.actual == req->req.length) {
-			if (ep->num == 0) {
-				/* send zlps until the status stage */
-			} else if (!req->req.zero || len != ep->ep.maxpacket)
-				mode = 2;
-		}
-
-	/* there was nothing to do ...  */
-	} else if (mode == 1)
-		return;
-
-	/* done */
-	if (mode == 2) {
-		/* stream endpoints often resubmit/unlink in completion */
-		done (ep, req, 0);
-
-		/* maybe advance queue to next request */
-		if (ep->num == 0) {
-			/* NOTE:  net2280 could let gadget driver start the
-			 * status stage later. since not all controllers let
-			 * them control that, the api doesn't (yet) allow it.
-			 */
-			if (!ep->stopped)
-				allow_status (ep);
-			req = NULL;
-		} else {
-			if (!list_empty (&ep->queue) && !ep->stopped)
-				req = list_entry (ep->queue.next,
-					struct net2280_request, queue);
-			else
-				req = NULL;
-			if (req && !ep->is_in)
-				stop_out_naking (ep);
-		}
-	}
-
-	/* is there a buffer for the next packet?
-	 * for best streaming performance, make sure there is one.
-	 */
-	if (req && !ep->stopped) {
-
-		/* load IN fifo with next packet (may be zlp) */
-		if (t & (1 << DATA_PACKET_TRANSMITTED_INTERRUPT))
-			write_fifo (ep, &req->req);
-	}
-}
-
-static struct net2280_ep *
-get_ep_by_addr (struct net2280 *dev, u16 wIndex)
-{
-	struct net2280_ep	*ep;
-
-	if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
-		return &dev->ep [0];
-	list_for_each_entry (ep, &dev->gadget.ep_list, ep.ep_list) {
-		u8	bEndpointAddress;
-
-		if (!ep->desc)
-			continue;
-		bEndpointAddress = ep->desc->bEndpointAddress;
-		if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
-			continue;
-		if ((wIndex & 0x0f) == (bEndpointAddress & 0x0f))
-			return ep;
-	}
-	return NULL;
-}
-
-static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
-{
-	struct net2280_ep	*ep;
-	u32			num, scratch;
-
-	/* most of these don't need individual acks */
-	stat &= ~(1 << INTA_ASSERTED);
-	if (!stat)
-		return;
-	// DEBUG (dev, "irqstat0 %04x\n", stat);
-
-	/* starting a control request? */
-	if (unlikely (stat & (1 << SETUP_PACKET_INTERRUPT))) {
-		union {
-			u32			raw [2];
-			struct usb_ctrlrequest	r;
-		} u;
-		int				tmp;
-		struct net2280_request		*req;
-
-		if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
-			if (readl (&dev->usb->usbstat) & (1 << HIGH_SPEED))
-				dev->gadget.speed = USB_SPEED_HIGH;
-			else
-				dev->gadget.speed = USB_SPEED_FULL;
-			net2280_led_speed (dev, dev->gadget.speed);
-			DEBUG(dev, "%s\n", usb_speed_string(dev->gadget.speed));
-		}
-
-		ep = &dev->ep [0];
-		ep->irqs++;
-
-		/* make sure any leftover request state is cleared */
-		stat &= ~(1 << ENDPOINT_0_INTERRUPT);
-		while (!list_empty (&ep->queue)) {
-			req = list_entry (ep->queue.next,
-					struct net2280_request, queue);
-			done (ep, req, (req->req.actual == req->req.length)
-						? 0 : -EPROTO);
-		}
-		ep->stopped = 0;
-		dev->protocol_stall = 0;
-
-		if (ep->dev->pdev->device == 0x2280)
-			tmp = (1 << FIFO_OVERFLOW)
-				| (1 << FIFO_UNDERFLOW);
-		else
-			tmp = 0;
-
-		writel (tmp | (1 << TIMEOUT)
-			| (1 << USB_STALL_SENT)
-			| (1 << USB_IN_NAK_SENT)
-			| (1 << USB_IN_ACK_RCVD)
-			| (1 << USB_OUT_PING_NAK_SENT)
-			| (1 << USB_OUT_ACK_SENT)
-			| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
-			| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
-			| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-			| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-			| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-			| (1 << DATA_IN_TOKEN_INTERRUPT)
-			, &ep->regs->ep_stat);
-		u.raw [0] = readl (&dev->usb->setup0123);
-		u.raw [1] = readl (&dev->usb->setup4567);
-
-		cpu_to_le32s (&u.raw [0]);
-		cpu_to_le32s (&u.raw [1]);
-
-		tmp = 0;
-
-#define	w_value		le16_to_cpu(u.r.wValue)
-#define	w_index		le16_to_cpu(u.r.wIndex)
-#define	w_length	le16_to_cpu(u.r.wLength)
-
-		/* ack the irq */
-		writel (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0);
-		stat ^= (1 << SETUP_PACKET_INTERRUPT);
-
-		/* watch control traffic at the token level, and force
-		 * synchronization before letting the status stage happen.
-		 * FIXME ignore tokens we'll NAK, until driver responds.
-		 * that'll mean a lot less irqs for some drivers.
-		 */
-		ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0;
-		if (ep->is_in) {
-			scratch = (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-				| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-				| (1 << DATA_IN_TOKEN_INTERRUPT);
-			stop_out_naking (ep);
-		} else
-			scratch = (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-				| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-				| (1 << DATA_IN_TOKEN_INTERRUPT);
-		writel (scratch, &dev->epregs [0].ep_irqenb);
-
-		/* we made the hardware handle most lowlevel requests;
-		 * everything else goes uplevel to the gadget code.
-		 */
-		ep->responded = 1;
-		switch (u.r.bRequest) {
-		case USB_REQ_GET_STATUS: {
-			struct net2280_ep	*e;
-			__le32			status;
-
-			/* hw handles device and interface status */
-			if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
-				goto delegate;
-			if ((e = get_ep_by_addr (dev, w_index)) == NULL
-					|| w_length > 2)
-				goto do_stall;
-
-			if (readl (&e->regs->ep_rsp)
-					& (1 << SET_ENDPOINT_HALT))
-				status = cpu_to_le32 (1);
-			else
-				status = cpu_to_le32 (0);
-
-			/* don't bother with a request object! */
-			writel (0, &dev->epregs [0].ep_irqenb);
-			set_fifo_bytecount (ep, w_length);
-			writel ((__force u32)status, &dev->epregs [0].ep_data);
-			allow_status (ep);
-			VDEBUG (dev, "%s stat %02x\n", ep->ep.name, status);
-			goto next_endpoints;
-			}
-			break;
-		case USB_REQ_CLEAR_FEATURE: {
-			struct net2280_ep	*e;
-
-			/* hw handles device features */
-			if (u.r.bRequestType != USB_RECIP_ENDPOINT)
-				goto delegate;
-			if (w_value != USB_ENDPOINT_HALT
-					|| w_length != 0)
-				goto do_stall;
-			if ((e = get_ep_by_addr (dev, w_index)) == NULL)
-				goto do_stall;
-			if (e->wedged) {
-				VDEBUG(dev, "%s wedged, halt not cleared\n",
-						ep->ep.name);
-			} else {
-				VDEBUG(dev, "%s clear halt\n", ep->ep.name);
-				clear_halt(e);
-			}
-			allow_status (ep);
-			goto next_endpoints;
-			}
-			break;
-		case USB_REQ_SET_FEATURE: {
-			struct net2280_ep	*e;
-
-			/* hw handles device features */
-			if (u.r.bRequestType != USB_RECIP_ENDPOINT)
-				goto delegate;
-			if (w_value != USB_ENDPOINT_HALT
-					|| w_length != 0)
-				goto do_stall;
-			if ((e = get_ep_by_addr (dev, w_index)) == NULL)
-				goto do_stall;
-			if (e->ep.name == ep0name)
-				goto do_stall;
-			set_halt (e);
-			allow_status (ep);
-			VDEBUG (dev, "%s set halt\n", ep->ep.name);
-			goto next_endpoints;
-			}
-			break;
-		default:
-delegate:
-			VDEBUG (dev, "setup %02x.%02x v%04x i%04x l%04x "
-				"ep_cfg %08x\n",
-				u.r.bRequestType, u.r.bRequest,
-				w_value, w_index, w_length,
-				readl (&ep->regs->ep_cfg));
-			ep->responded = 0;
-			spin_unlock (&dev->lock);
-			tmp = dev->driver->setup (&dev->gadget, &u.r);
-			spin_lock (&dev->lock);
-		}
-
-		/* stall ep0 on error */
-		if (tmp < 0) {
-do_stall:
-			VDEBUG (dev, "req %02x.%02x protocol STALL; stat %d\n",
-					u.r.bRequestType, u.r.bRequest, tmp);
-			dev->protocol_stall = 1;
-		}
-
-		/* some in/out token irq should follow; maybe stall then.
-		 * driver must queue a request (even zlp) or halt ep0
-		 * before the host times out.
-		 */
-	}
-
-#undef	w_value
-#undef	w_index
-#undef	w_length
-
-next_endpoints:
-	/* endpoint data irq ? */
-	scratch = stat & 0x7f;
-	stat &= ~0x7f;
-	for (num = 0; scratch; num++) {
-		u32		t;
-
-		/* do this endpoint's FIFO and queue need tending? */
-		t = 1 << num;
-		if ((scratch & t) == 0)
-			continue;
-		scratch ^= t;
-
-		ep = &dev->ep [num];
-		handle_ep_small (ep);
-	}
-
-	if (stat)
-		DEBUG (dev, "unhandled irqstat0 %08x\n", stat);
-}
-
-#define DMA_INTERRUPTS ( \
-		  (1 << DMA_D_INTERRUPT) \
-		| (1 << DMA_C_INTERRUPT) \
-		| (1 << DMA_B_INTERRUPT) \
-		| (1 << DMA_A_INTERRUPT))
-#define	PCI_ERROR_INTERRUPTS ( \
-		  (1 << PCI_MASTER_ABORT_RECEIVED_INTERRUPT) \
-		| (1 << PCI_TARGET_ABORT_RECEIVED_INTERRUPT) \
-		| (1 << PCI_RETRY_ABORT_INTERRUPT))
-
-static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
-{
-	struct net2280_ep	*ep;
-	u32			tmp, num, mask, scratch;
-
-	/* after disconnect there's nothing else to do! */
-	tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT);
-	mask = (1 << HIGH_SPEED) | (1 << FULL_SPEED);
-
-	/* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
-	 * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRUPT set and
-	 * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT
-	 * only indicates a change in the reset state).
-	 */
-	if (stat & tmp) {
-		writel (tmp, &dev->regs->irqstat1);
-		if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT))
-					&& ((readl (&dev->usb->usbstat) & mask)
-							== 0))
-				|| ((readl (&dev->usb->usbctl)
-					& (1 << VBUS_PIN)) == 0)
-			    ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) {
-			DEBUG (dev, "disconnect %s\n",
-					dev->driver->driver.name);
-			stop_activity (dev, dev->driver);
-			ep0_start (dev);
-			return;
-		}
-		stat &= ~tmp;
-
-		/* vBUS can bounce ... one of many reasons to ignore the
-		 * notion of hotplug events on bus connect/disconnect!
-		 */
-		if (!stat)
-			return;
-	}
-
-	/* NOTE: chip stays in PCI D0 state for now, but it could
-	 * enter D1 to save more power
-	 */
-	tmp = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT);
-	if (stat & tmp) {
-		writel (tmp, &dev->regs->irqstat1);
-		if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
-			if (dev->driver->suspend)
-				dev->driver->suspend (&dev->gadget);
-			if (!enable_suspend)
-				stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
-		} else {
-			if (dev->driver->resume)
-				dev->driver->resume (&dev->gadget);
-			/* at high speed, note erratum 0133 */
-		}
-		stat &= ~tmp;
-	}
-
-	/* clear any other status/irqs */
-	if (stat)
-		writel (stat, &dev->regs->irqstat1);
-
-	/* some status we can just ignore */
-	if (dev->pdev->device == 0x2280)
-		stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
-			  | (1 << SUSPEND_REQUEST_INTERRUPT)
-			  | (1 << RESUME_INTERRUPT)
-			  | (1 << SOF_INTERRUPT));
-	else
-		stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
-			  | (1 << RESUME_INTERRUPT)
-			  | (1 << SOF_DOWN_INTERRUPT)
-			  | (1 << SOF_INTERRUPT));
-
-	if (!stat)
-		return;
-	// DEBUG (dev, "irqstat1 %08x\n", stat);
-
-	/* DMA status, for ep-{a,b,c,d} */
-	scratch = stat & DMA_INTERRUPTS;
-	stat &= ~DMA_INTERRUPTS;
-	scratch >>= 9;
-	for (num = 0; scratch; num++) {
-		struct net2280_dma_regs	__iomem *dma;
-
-		tmp = 1 << num;
-		if ((tmp & scratch) == 0)
-			continue;
-		scratch ^= tmp;
-
-		ep = &dev->ep [num + 1];
-		dma = ep->dma;
-
-		if (!dma)
-			continue;
-
-		/* clear ep's dma status */
-		tmp = readl (&dma->dmastat);
-		writel (tmp, &dma->dmastat);
-
-		/* chaining should stop on abort, short OUT from fifo,
-		 * or (stat0 codepath) short OUT transfer.
-		 */
-		if (!use_dma_chaining) {
-			if ((tmp & (1 << DMA_TRANSACTION_DONE_INTERRUPT))
-					== 0) {
-				DEBUG (ep->dev, "%s no xact done? %08x\n",
-					ep->ep.name, tmp);
-				continue;
-			}
-			stop_dma (ep->dma);
-		}
-
-		/* OUT transfers terminate when the data from the
-		 * host is in our memory.  Process whatever's done.
-		 * On this path, we know transfer's last packet wasn't
-		 * less than req->length. NAK_OUT_PACKETS may be set,
-		 * or the FIFO may already be holding new packets.
-		 *
-		 * IN transfers can linger in the FIFO for a very
-		 * long time ... we ignore that for now, accounting
-		 * precisely (like PIO does) needs per-packet irqs
-		 */
-		scan_dma_completions (ep);
-
-		/* disable dma on inactive queues; else maybe restart */
-		if (list_empty (&ep->queue)) {
-			if (use_dma_chaining)
-				stop_dma (ep->dma);
-		} else {
-			tmp = readl (&dma->dmactl);
-			if (!use_dma_chaining
-					|| (tmp & (1 << DMA_ENABLE)) == 0)
-				restart_dma (ep);
-			else if (ep->is_in && use_dma_chaining) {
-				struct net2280_request	*req;
-				__le32			dmacount;
-
-				/* the descriptor at the head of the chain
-				 * may still have VALID_BIT clear; that's
-				 * used to trigger changing DMA_FIFO_VALIDATE
-				 * (affects automagic zlp writes).
-				 */
-				req = list_entry (ep->queue.next,
-						struct net2280_request, queue);
-				dmacount = req->td->dmacount;
-				dmacount &= cpu_to_le32 (
-						(1 << VALID_BIT)
-						| DMA_BYTE_COUNT_MASK);
-				if (dmacount && (dmacount & valid_bit) == 0)
-					restart_dma (ep);
-			}
-		}
-		ep->irqs++;
-	}
-
-	/* NOTE:  there are other PCI errors we might usefully notice.
-	 * if they appear very often, here's where to try recovering.
-	 */
-	if (stat & PCI_ERROR_INTERRUPTS) {
-		ERROR (dev, "pci dma error; stat %08x\n", stat);
-		stat &= ~PCI_ERROR_INTERRUPTS;
-		/* these are fatal errors, but "maybe" they won't
-		 * happen again ...
-		 */
-		stop_activity (dev, dev->driver);
-		ep0_start (dev);
-		stat = 0;
-	}
-
-	if (stat)
-		DEBUG (dev, "unhandled irqstat1 %08x\n", stat);
-}
-
-static irqreturn_t net2280_irq (int irq, void *_dev)
-{
-	struct net2280		*dev = _dev;
-
-	/* shared interrupt, not ours */
-	if (!(readl(&dev->regs->irqstat0) & (1 << INTA_ASSERTED)))
-		return IRQ_NONE;
-
-	spin_lock (&dev->lock);
-
-	/* handle disconnect, dma, and more */
-	handle_stat1_irqs (dev, readl (&dev->regs->irqstat1));
-
-	/* control requests and PIO */
-	handle_stat0_irqs (dev, readl (&dev->regs->irqstat0));
-
-	spin_unlock (&dev->lock);
-
-	return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void gadget_release (struct device *_dev)
-{
-	struct net2280	*dev = dev_get_drvdata (_dev);
-
-	kfree (dev);
-}
-
-/* tear down the binding between this driver and the pci device */
-
-static void net2280_remove (struct pci_dev *pdev)
-{
-	struct net2280		*dev = pci_get_drvdata (pdev);
-
-	usb_del_gadget_udc(&dev->gadget);
-
-	BUG_ON(dev->driver);
-
-	/* then clean up the resources we allocated during probe() */
-	net2280_led_shutdown (dev);
-	if (dev->requests) {
-		int		i;
-		for (i = 1; i < 5; i++) {
-			if (!dev->ep [i].dummy)
-				continue;
-			pci_pool_free (dev->requests, dev->ep [i].dummy,
-					dev->ep [i].td_dma);
-		}
-		pci_pool_destroy (dev->requests);
-	}
-	if (dev->got_irq)
-		free_irq (pdev->irq, dev);
-	if (dev->regs)
-		iounmap (dev->regs);
-	if (dev->region)
-		release_mem_region (pci_resource_start (pdev, 0),
-				pci_resource_len (pdev, 0));
-	if (dev->enabled)
-		pci_disable_device (pdev);
-	device_remove_file (&pdev->dev, &dev_attr_registers);
-
-	INFO (dev, "unbind\n");
-}
-
-/* wrap this driver around the specified device, but
- * don't respond over USB until a gadget driver binds to us.
- */
-
-static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct net2280		*dev;
-	unsigned long		resource, len;
-	void			__iomem *base = NULL;
-	int			retval, i;
-
-	/* alloc, and start init */
-	dev = kzalloc (sizeof *dev, GFP_KERNEL);
-	if (dev == NULL){
-		retval = -ENOMEM;
-		goto done;
-	}
-
-	pci_set_drvdata (pdev, dev);
-	spin_lock_init (&dev->lock);
-	dev->pdev = pdev;
-	dev->gadget.ops = &net2280_ops;
-	dev->gadget.max_speed = USB_SPEED_HIGH;
-
-	/* the "gadget" abstracts/virtualizes the controller */
-	dev->gadget.name = driver_name;
-
-	/* now all the pci goodies ... */
-	if (pci_enable_device (pdev) < 0) {
-	        retval = -ENODEV;
-		goto done;
-	}
-	dev->enabled = 1;
-
-	/* BAR 0 holds all the registers
-	 * BAR 1 is 8051 memory; unused here (note erratum 0103)
-	 * BAR 2 is fifo memory; unused here
-	 */
-	resource = pci_resource_start (pdev, 0);
-	len = pci_resource_len (pdev, 0);
-	if (!request_mem_region (resource, len, driver_name)) {
-		DEBUG (dev, "controller already in use\n");
-		retval = -EBUSY;
-		goto done;
-	}
-	dev->region = 1;
-
-	/* FIXME provide firmware download interface to put
-	 * 8051 code into the chip, e.g. to turn on PCI PM.
-	 */
-
-	base = ioremap_nocache (resource, len);
-	if (base == NULL) {
-		DEBUG (dev, "can't map memory\n");
-		retval = -EFAULT;
-		goto done;
-	}
-	dev->regs = (struct net2280_regs __iomem *) base;
-	dev->usb = (struct net2280_usb_regs __iomem *) (base + 0x0080);
-	dev->pci = (struct net2280_pci_regs __iomem *) (base + 0x0100);
-	dev->dma = (struct net2280_dma_regs __iomem *) (base + 0x0180);
-	dev->dep = (struct net2280_dep_regs __iomem *) (base + 0x0200);
-	dev->epregs = (struct net2280_ep_regs __iomem *) (base + 0x0300);
-
-	/* put into initial config, link up all endpoints */
-	writel (0, &dev->usb->usbctl);
-	usb_reset (dev);
-	usb_reinit (dev);
-
-	/* irq setup after old hardware is cleaned up */
-	if (!pdev->irq) {
-		ERROR (dev, "No IRQ.  Check PCI setup!\n");
-		retval = -ENODEV;
-		goto done;
-	}
-
-	if (request_irq (pdev->irq, net2280_irq, IRQF_SHARED, driver_name, dev)
-			!= 0) {
-		ERROR (dev, "request interrupt %d failed\n", pdev->irq);
-		retval = -EBUSY;
-		goto done;
-	}
-	dev->got_irq = 1;
-
-	/* DMA setup */
-	/* NOTE:  we know only the 32 LSBs of dma addresses may be nonzero */
-	dev->requests = pci_pool_create ("requests", pdev,
-		sizeof (struct net2280_dma),
-		0 /* no alignment requirements */,
-		0 /* or page-crossing issues */);
-	if (!dev->requests) {
-		DEBUG (dev, "can't get request pool\n");
-		retval = -ENOMEM;
-		goto done;
-	}
-	for (i = 1; i < 5; i++) {
-		struct net2280_dma	*td;
-
-		td = pci_pool_alloc (dev->requests, GFP_KERNEL,
-				&dev->ep [i].td_dma);
-		if (!td) {
-			DEBUG (dev, "can't get dummy %d\n", i);
-			retval = -ENOMEM;
-			goto done;
-		}
-		td->dmacount = 0;	/* not VALID */
-		td->dmadesc = td->dmaaddr;
-		dev->ep [i].dummy = td;
-	}
-
-	/* enable lower-overhead pci memory bursts during DMA */
-	writel ( (1 << DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE)
-			// 256 write retries may not be enough...
-			// | (1 << PCI_RETRY_ABORT_ENABLE)
-			| (1 << DMA_READ_MULTIPLE_ENABLE)
-			| (1 << DMA_READ_LINE_ENABLE)
-			, &dev->pci->pcimstctl);
-	/* erratum 0115 shouldn't appear: Linux inits PCI_LATENCY_TIMER */
-	pci_set_master (pdev);
-	pci_try_set_mwi (pdev);
-
-	/* ... also flushes any posted pci writes */
-	dev->chiprev = get_idx_reg (dev->regs, REG_CHIPREV) & 0xffff;
-
-	/* done */
-	INFO (dev, "%s\n", driver_desc);
-	INFO (dev, "irq %d, pci mem %p, chip rev %04x\n",
-			pdev->irq, base, dev->chiprev);
-	INFO (dev, "version: " DRIVER_VERSION "; dma %s\n",
-			use_dma
-				? (use_dma_chaining ? "chaining" : "enabled")
-				: "disabled");
-	retval = device_create_file (&pdev->dev, &dev_attr_registers);
-	if (retval) goto done;
-
-	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
-			gadget_release);
-	if (retval)
-		goto done;
-	return 0;
-
-done:
-	if (dev)
-		net2280_remove (pdev);
-	return retval;
-}
-
-/* make sure the board is quiescent; otherwise it will continue
- * generating IRQs across the upcoming reboot.
- */
-
-static void net2280_shutdown (struct pci_dev *pdev)
-{
-	struct net2280		*dev = pci_get_drvdata (pdev);
-
-	/* disable IRQs */
-	writel (0, &dev->regs->pciirqenb0);
-	writel (0, &dev->regs->pciirqenb1);
-
-	/* disable the pullup so the host will think we're gone */
-	writel (0, &dev->usb->usbctl);
-
-	/* Disable full-speed test mode */
-	writel(0, &dev->usb->xcvrdiag);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static const struct pci_device_id pci_ids [] = { {
-	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-	.class_mask =	~0,
-	.vendor =	0x17cc,
-	.device =	0x2280,
-	.subvendor =	PCI_ANY_ID,
-	.subdevice =	PCI_ANY_ID,
-}, {
-	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-	.class_mask =	~0,
-	.vendor =	0x17cc,
-	.device =	0x2282,
-	.subvendor =	PCI_ANY_ID,
-	.subdevice =	PCI_ANY_ID,
-
-}, { /* end: all zeroes */ }
-};
-MODULE_DEVICE_TABLE (pci, pci_ids);
-
-/* pci driver glue; this is a "new style" PCI driver module */
-static struct pci_driver net2280_pci_driver = {
-	.name =		(char *) driver_name,
-	.id_table =	pci_ids,
-
-	.probe =	net2280_probe,
-	.remove =	net2280_remove,
-	.shutdown =	net2280_shutdown,
-
-	/* FIXME add power management support */
-};
-
-MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_AUTHOR ("David Brownell");
-MODULE_LICENSE ("GPL");
-
-static int __init init (void)
-{
-	if (!use_dma)
-		use_dma_chaining = 0;
-	return pci_register_driver (&net2280_pci_driver);
-}
-module_init (init);
-
-static void __exit cleanup (void)
-{
-	pci_unregister_driver (&net2280_pci_driver);
-}
-module_exit (cleanup);
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
deleted file mode 100644
index a844be0..0000000
--- a/drivers/usb/gadget/net2280.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * NetChip 2280 high/full speed USB device controller.
- * Unlike many such controllers, this one talks PCI.
- */
-
-/*
- * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
- * 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.
- */
-
-#include <linux/usb/net2280.h>
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	__KERNEL__
-
-/* indexed registers [11.10] are accessed indirectly
- * caller must own the device lock.
- */
-
-static inline u32
-get_idx_reg (struct net2280_regs __iomem *regs, u32 index)
-{
-	writel (index, &regs->idxaddr);
-	/* NOTE:  synchs device/cpu memory views */
-	return readl (&regs->idxdata);
-}
-
-static inline void
-set_idx_reg (struct net2280_regs __iomem *regs, u32 index, u32 value)
-{
-	writel (index, &regs->idxaddr);
-	writel (value, &regs->idxdata);
-	/* posted, may not be visible yet */
-}
-
-#endif	/* __KERNEL__ */
-
-
-#define REG_DIAG		0x0
-#define     RETRY_COUNTER                                       16
-#define     FORCE_PCI_SERR                                      11
-#define     FORCE_PCI_INTERRUPT                                 10
-#define     FORCE_USB_INTERRUPT                                 9
-#define     FORCE_CPU_INTERRUPT                                 8
-#define     ILLEGAL_BYTE_ENABLES                                5
-#define     FAST_TIMES                                          4
-#define     FORCE_RECEIVE_ERROR                                 2
-#define     FORCE_TRANSMIT_CRC_ERROR                            0
-#define REG_FRAME		0x02	/* from last sof */
-#define REG_CHIPREV		0x03	/* in bcd */
-#define	REG_HS_NAK_RATE		0x0a	/* NAK per N uframes */
-
-#define	CHIPREV_1	0x0100
-#define	CHIPREV_1A	0x0110
-
-#ifdef	__KERNEL__
-
-/* ep a-f highspeed and fullspeed maxpacket, addresses
- * computed from ep->num
- */
-#define REG_EP_MAXPKT(dev,num) (((num) + 1) * 0x10 + \
-		(((dev)->gadget.speed == USB_SPEED_HIGH) ? 0 : 1))
-
-/*-------------------------------------------------------------------------*/
-
-/* [8.3] for scatter/gather i/o
- * use struct net2280_dma_regs bitfields
- */
-struct net2280_dma {
-	__le32		dmacount;
-	__le32		dmaaddr;		/* the buffer */
-	__le32		dmadesc;		/* next dma descriptor */
-	__le32		_reserved;
-} __attribute__ ((aligned (16)));
-
-/*-------------------------------------------------------------------------*/
-
-/* DRIVER DATA STRUCTURES and UTILITIES */
-
-struct net2280_ep {
-	struct usb_ep				ep;
-	struct net2280_ep_regs			__iomem *regs;
-	struct net2280_dma_regs			__iomem *dma;
-	struct net2280_dma			*dummy;
-	dma_addr_t				td_dma;	/* of dummy */
-	struct net2280				*dev;
-	unsigned long				irqs;
-
-	/* analogous to a host-side qh */
-	struct list_head			queue;
-	const struct usb_endpoint_descriptor	*desc;
-	unsigned				num : 8,
-						fifo_size : 12,
-						in_fifo_validate : 1,
-						out_overflow : 1,
-						stopped : 1,
-						wedged : 1,
-						is_in : 1,
-						is_iso : 1,
-						responded : 1;
-};
-
-static inline void allow_status (struct net2280_ep *ep)
-{
-	/* ep0 only */
-	writel (  (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
-		| (1 << CLEAR_NAK_OUT_PACKETS)
-		| (1 << CLEAR_NAK_OUT_PACKETS_MODE)
-		, &ep->regs->ep_rsp);
-	ep->stopped = 1;
-}
-
-/* count (<= 4) bytes in the next fifo write will be valid */
-static inline void set_fifo_bytecount (struct net2280_ep *ep, unsigned count)
-{
-	writeb (count, 2 + (u8 __iomem *) &ep->regs->ep_cfg);
-}
-
-struct net2280_request {
-	struct usb_request		req;
-	struct net2280_dma		*td;
-	dma_addr_t			td_dma;
-	struct list_head		queue;
-	unsigned			mapped : 1,
-					valid : 1;
-};
-
-struct net2280 {
-	/* each pci device provides one gadget, several endpoints */
-	struct usb_gadget		gadget;
-	spinlock_t			lock;
-	struct net2280_ep		ep [7];
-	struct usb_gadget_driver 	*driver;
-	unsigned			enabled : 1,
-					protocol_stall : 1,
-					softconnect : 1,
-					got_irq : 1,
-					region : 1;
-	u16				chiprev;
-
-	/* pci state used to access those endpoints */
-	struct pci_dev			*pdev;
-	struct net2280_regs		__iomem *regs;
-	struct net2280_usb_regs		__iomem *usb;
-	struct net2280_pci_regs		__iomem *pci;
-	struct net2280_dma_regs		__iomem *dma;
-	struct net2280_dep_regs		__iomem *dep;
-	struct net2280_ep_regs		__iomem *epregs;
-
-	struct pci_pool			*requests;
-	// statistics...
-};
-
-static inline void set_halt (struct net2280_ep *ep)
-{
-	/* ep0 and bulk/intr endpoints */
-	writel (  (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
-		    /* set NAK_OUT for erratum 0114 */
-		| ((ep->dev->chiprev == CHIPREV_1) << SET_NAK_OUT_PACKETS)
-		| (1 << SET_ENDPOINT_HALT)
-		, &ep->regs->ep_rsp);
-}
-
-static inline void clear_halt (struct net2280_ep *ep)
-{
-	/* ep0 and bulk/intr endpoints */
-	writel (  (1 << CLEAR_ENDPOINT_HALT)
-		| (1 << CLEAR_ENDPOINT_TOGGLE)
-		    /* unless the gadget driver left a short packet in the
-		     * fifo, this reverses the erratum 0114 workaround.
-		     */
-		| ((ep->dev->chiprev == CHIPREV_1) << CLEAR_NAK_OUT_PACKETS)
-		, &ep->regs->ep_rsp);
-}
-
-#ifdef USE_RDK_LEDS
-
-static inline void net2280_led_init (struct net2280 *dev)
-{
-	/* LED3 (green) is on during USB activity. note erratum 0113. */
-	writel ((1 << GPIO3_LED_SELECT)
-		| (1 << GPIO3_OUTPUT_ENABLE)
-		| (1 << GPIO2_OUTPUT_ENABLE)
-		| (1 << GPIO1_OUTPUT_ENABLE)
-		| (1 << GPIO0_OUTPUT_ENABLE)
-		, &dev->regs->gpioctl);
-}
-
-/* indicate speed with bi-color LED 0/1 */
-static inline
-void net2280_led_speed (struct net2280 *dev, enum usb_device_speed speed)
-{
-	u32	val = readl (&dev->regs->gpioctl);
-	switch (speed) {
-	case USB_SPEED_HIGH:		/* green */
-		val &= ~(1 << GPIO0_DATA);
-		val |= (1 << GPIO1_DATA);
-		break;
-	case USB_SPEED_FULL:		/* red */
-		val &= ~(1 << GPIO1_DATA);
-		val |= (1 << GPIO0_DATA);
-		break;
-	default:			/* (off/black) */
-		val &= ~((1 << GPIO1_DATA) | (1 << GPIO0_DATA));
-		break;
-	}
-	writel (val, &dev->regs->gpioctl);
-}
-
-/* indicate power with LED 2 */
-static inline void net2280_led_active (struct net2280 *dev, int is_active)
-{
-	u32	val = readl (&dev->regs->gpioctl);
-
-	// FIXME this LED never seems to turn on.
-	if (is_active)
-		val |= GPIO2_DATA;
-	else
-		val &= ~GPIO2_DATA;
-	writel (val, &dev->regs->gpioctl);
-}
-static inline void net2280_led_shutdown (struct net2280 *dev)
-{
-	/* turn off all four GPIO*_DATA bits */
-	writel (readl (&dev->regs->gpioctl) & ~0x0f,
-			&dev->regs->gpioctl);
-}
-
-#else
-
-#define net2280_led_init(dev)		do { } while (0)
-#define net2280_led_speed(dev, speed)	do { } while (0)
-#define net2280_led_shutdown(dev)	do { } while (0)
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-#define xprintk(dev,level,fmt,args...) \
-	printk(level "%s %s: " fmt , driver_name , \
-			pci_name(dev->pdev) , ## 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 WARNING(dev,fmt,args...) \
-	xprintk(dev , KERN_WARNING , fmt , ## args)
-#define INFO(dev,fmt,args...) \
-	xprintk(dev , KERN_INFO , fmt , ## args)
-
-/*-------------------------------------------------------------------------*/
-
-static inline void start_out_naking (struct net2280_ep *ep)
-{
-	/* NOTE:  hardware races lurk here, and PING protocol issues */
-	writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-	/* synch with device */
-	readl (&ep->regs->ep_rsp);
-}
-
-#ifdef DEBUG
-static inline void assert_out_naking (struct net2280_ep *ep, const char *where)
-{
-	u32	tmp = readl (&ep->regs->ep_stat);
-
-	if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
-		DEBUG (ep->dev, "%s %s %08x !NAK\n",
-				ep->ep.name, where, tmp);
-		writel ((1 << SET_NAK_OUT_PACKETS),
-			&ep->regs->ep_rsp);
-	}
-}
-#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep,__func__)
-#else
-#define ASSERT_OUT_NAKING(ep) do {} while (0)
-#endif
-
-static inline void stop_out_naking (struct net2280_ep *ep)
-{
-	u32	tmp;
-
-	tmp = readl (&ep->regs->ep_stat);
-	if ((tmp & (1 << NAK_OUT_PACKETS)) != 0)
-		writel ((1 << CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-}
-
-#endif	/* __KERNEL__ */
diff --git a/drivers/usb/gadget/u_os_desc.h b/drivers/usb/gadget/u_os_desc.h
index ea5cf8c..947b7dd 100644
--- a/drivers/usb/gadget/u_os_desc.h
+++ b/drivers/usb/gadget/u_os_desc.h
@@ -35,27 +35,63 @@
 #define USB_EXT_PROP_UNICODE_LINK		6
 #define USB_EXT_PROP_UNICODE_MULTI		7
 
+static inline u8 *__usb_ext_prop_ptr(u8 *buf, size_t offset)
+{
+	return buf + offset;
+}
+
+static inline u8 *usb_ext_prop_size_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_SIZE);
+}
+
+static inline u8 *usb_ext_prop_type_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_PROPERTY_DATA_TYPE);
+}
+
+static inline u8 *usb_ext_prop_name_len_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_W_PROPERTY_NAME_LENGTH);
+}
+
+static inline u8 *usb_ext_prop_name_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_NAME);
+}
+
+static inline u8 *usb_ext_prop_data_len_ptr(u8 *buf, size_t off)
+{
+	return __usb_ext_prop_ptr(buf,
+				  USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + off);
+}
+
+static inline u8 *usb_ext_prop_data_ptr(u8 *buf, size_t off)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_DATA + off);
+}
+
 static inline void usb_ext_prop_put_size(u8 *buf, int dw_size)
 {
-	put_unaligned_le32(dw_size, &buf[USB_EXT_PROP_DW_SIZE]);
+	put_unaligned_le32(dw_size, usb_ext_prop_size_ptr(buf));
 }
 
 static inline void usb_ext_prop_put_type(u8 *buf, int type)
 {
-	put_unaligned_le32(type, &buf[USB_EXT_PROP_DW_PROPERTY_DATA_TYPE]);
+	put_unaligned_le32(type, usb_ext_prop_type_ptr(buf));
 }
 
 static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl)
 {
 	int result;
 
-	put_unaligned_le16(pnl, &buf[USB_EXT_PROP_W_PROPERTY_NAME_LENGTH]);
+	put_unaligned_le16(pnl, usb_ext_prop_name_len_ptr(buf));
 	result = utf8s_to_utf16s(name, strlen(name), UTF16_LITTLE_ENDIAN,
-		(wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_NAME], pnl - 2);
+		(wchar_t *) usb_ext_prop_name_ptr(buf), pnl - 2);
 	if (result < 0)
 		return result;
 
-	put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl]);
+	put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl - 2]);
 
 	return pnl;
 }
@@ -63,26 +99,23 @@
 static inline void usb_ext_prop_put_binary(u8 *buf, int pnl, const u8 *data,
 					   int data_len)
 {
-	put_unaligned_le32(data_len,
-			   &buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
-	memcpy(&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl], data, data_len);
+	put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
+	memcpy(usb_ext_prop_data_ptr(buf, pnl), data, data_len);
 }
 
 static inline int usb_ext_prop_put_unicode(u8 *buf, int pnl, const char *string,
 					   int data_len)
 {
 	int result;
-	put_unaligned_le32(data_len,
-			&buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
-
+	put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
 	result = utf8s_to_utf16s(string, data_len >> 1, UTF16_LITTLE_ENDIAN,
-			(wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl],
+			(wchar_t *) usb_ext_prop_data_ptr(buf, pnl),
 			data_len - 2);
 	if (result < 0)
 		return result;
 
 	put_unaligned_le16(0,
-			&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len]);
+		&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len - 2]);
 
 	return data_len;
 }
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
new file mode 100644
index 0000000..5151f94
--- /dev/null
+++ b/drivers/usb/gadget/udc/Kconfig
@@ -0,0 +1,385 @@
+#
+# USB Gadget support on a system involves
+#    (a) a peripheral controller, and
+#    (b) the gadget driver using it.
+#
+# NOTE:  Gadget support ** DOES NOT ** depend on host-side CONFIG_USB !!
+#
+#  - Host systems (like PCs) need CONFIG_USB (with "A" jacks).
+#  - Peripherals (like PDAs) need CONFIG_USB_GADGET (with "B" jacks).
+#  - Some systems have both kinds of controllers.
+#
+# With help from a special transceiver and a "Mini-AB" jack, systems with
+# both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
+#
+
+#
+# USB Peripheral Controller Support
+#
+# The order here is alphabetical, except that integrated controllers go
+# before discrete ones so they will be the initial/default value:
+#   - integrated/SOC controllers first
+#   - licensed IP used in both SOC and discrete versions
+#   - discrete ones (including all PCI-only controllers)
+#   - debug/dummy gadget+hcd is last.
+#
+menu "USB Peripheral Controller"
+
+#
+# Integrated controllers
+#
+
+config USB_AT91
+	tristate "Atmel AT91 USB Device Port"
+	depends on ARCH_AT91
+	help
+	   Many Atmel AT91 processors (such as the AT91RM2000) have a
+	   full speed USB Device Port with support for five configurable
+	   endpoints (plus endpoint zero).
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "at91_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_LPC32XX
+	tristate "LPC32XX USB Peripheral Controller"
+	depends on ARCH_LPC32XX && I2C
+	select USB_ISP1301
+	help
+	   This option selects the USB device controller in the LPC32xx SoC.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "lpc32xx_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_ATMEL_USBA
+	tristate "Atmel USBA"
+	depends on AVR32 || ARCH_AT91
+	help
+	  USBA is the integrated high-speed USB Device controller on
+	  the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
+
+config USB_BCM63XX_UDC
+	tristate "Broadcom BCM63xx Peripheral Controller"
+	depends on BCM63XX
+	help
+	   Many Broadcom BCM63xx chipsets (such as the BCM6328) have a
+	   high speed USB Device Port with support for four fixed endpoints
+	   (plus endpoint zero).
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "bcm63xx_udc".
+
+config USB_FSL_USB2
+	tristate "Freescale Highspeed USB DR Peripheral Controller"
+	depends on FSL_SOC || ARCH_MXC
+	select USB_FSL_MPH_DR_OF if OF
+	help
+	   Some of Freescale PowerPC and i.MX processors have a High Speed
+	   Dual-Role(DR) USB controller, which supports device mode.
+
+	   The number of programmable endpoints is different through
+	   SOC revisions.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "fsl_usb2_udc" and force
+	   all gadget drivers to also be dynamically linked.
+
+config USB_FUSB300
+	tristate "Faraday FUSB300 USB Peripheral Controller"
+	depends on !PHYS_ADDR_T_64BIT && HAS_DMA
+	help
+	   Faraday usb device controller FUSB300 driver
+
+config USB_FOTG210_UDC
+	depends on HAS_DMA
+	tristate "Faraday FOTG210 USB Peripheral Controller"
+	help
+	   Faraday USB2.0 OTG controller which can be configured as
+	   high speed or full speed USB device. This driver supppors
+	   Bulk Transfer so far.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "fotg210_udc".
+
+config USB_GR_UDC
+       tristate "Aeroflex Gaisler GRUSBDC USB Peripheral Controller Driver"
+       depends on HAS_DMA
+       help
+          Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB
+	  VHDL IP core library.
+
+config USB_OMAP
+	tristate "OMAP USB Device Controller"
+	depends on ARCH_OMAP1
+	depends on ISP1301_OMAP || !(MACH_OMAP_H2 || MACH_OMAP_H3)
+	help
+	   Many Texas Instruments OMAP processors have flexible full
+	   speed USB device controllers, with support for up to 30
+	   endpoints (plus endpoint zero).  This driver supports the
+	   controller in the OMAP 1611, and should work with controllers
+	   in other OMAP processors too, given minor tweaks.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "omap_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_PXA25X
+	tristate "PXA 25x or IXP 4xx"
+	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
+	help
+	   Intel's PXA 25x series XScale ARM-5TE processors include
+	   an integrated full speed USB 1.1 device controller.  The
+	   controller in the IXP 4xx series is register-compatible.
+
+	   It has fifteen fixed-function endpoints, as well as endpoint
+	   zero (for control transfers).
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "pxa25x_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+# if there's only one gadget driver, using only two bulk endpoints,
+# don't waste memory for the other endpoints
+config USB_PXA25X_SMALL
+	depends on USB_PXA25X
+	bool
+	default n if USB_ETH_RNDIS
+	default y if USB_ZERO
+	default y if USB_ETH
+	default y if USB_G_SERIAL
+
+config USB_R8A66597
+	tristate "Renesas R8A66597 USB Peripheral Controller"
+	depends on HAS_DMA
+	help
+	   R8A66597 is a discrete USB host and peripheral controller chip that
+	   supports both full and high speed USB 2.0 data transfers.
+	   It has nine configurable endpoints, and endpoint zero.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "r8a66597_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_RENESAS_USBHS_UDC
+	tristate 'Renesas USBHS controller'
+	depends on USB_RENESAS_USBHS
+	help
+	   Renesas USBHS is a discrete USB host and peripheral controller chip
+	   that supports both full and high speed USB 2.0 data transfers.
+	   It has nine or more configurable endpoints, and endpoint zero.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "renesas_usbhs" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_PXA27X
+	tristate "PXA 27x"
+	help
+	   Intel's PXA 27x series XScale ARM v5TE processors include
+	   an integrated full speed USB 1.1 device controller.
+
+	   It has up to 23 endpoints, as well as endpoint zero (for
+	   control transfers).
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "pxa27x_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_S3C2410
+	tristate "S3C2410 USB Device Controller"
+	depends on ARCH_S3C24XX
+	help
+	  Samsung's S3C2410 is an ARM-4 processor with an integrated
+	  full speed USB 1.1 device controller.  It has 4 configurable
+	  endpoints, as well as endpoint zero (for control transfers).
+
+	  This driver has been tested on the S3C2410, S3C2412, and
+	  S3C2440 processors.
+
+config USB_S3C2410_DEBUG
+	boolean "S3C2410 udc debug messages"
+	depends on USB_S3C2410
+
+config USB_S3C_HSUDC
+	tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller"
+	depends on ARCH_S3C24XX
+	help
+	  Samsung's S3C2416, S3C2443 and S3C2450 is an ARM9 based SoC
+	  integrated with dual speed USB 2.0 device controller. It has
+	  8 endpoints, as well as endpoint zero.
+
+	  This driver has been tested on S3C2416 and S3C2450 processors.
+
+config USB_MV_UDC
+	tristate "Marvell USB2.0 Device Controller"
+	depends on HAS_DMA
+	help
+	  Marvell Socs (including PXA and MMP series) include a high speed
+	  USB2.0 OTG controller, which can be configured as high speed or
+	  full speed USB peripheral.
+
+config USB_MV_U3D
+	depends on HAS_DMA
+	tristate "MARVELL PXA2128 USB 3.0 controller"
+	help
+	  MARVELL PXA2128 Processor series include a super speed USB3.0 device
+	  controller, which support super speed USB peripheral.
+
+#
+# Controllers available in both integrated and discrete versions
+#
+
+config USB_M66592
+	tristate "Renesas M66592 USB Peripheral Controller"
+	help
+	   M66592 is a discrete USB peripheral controller chip that
+	   supports both full and high speed USB 2.0 data transfers.
+	   It has seven configurable endpoints, and endpoint zero.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "m66592_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+#
+# Controllers available only in discrete form (and all PCI controllers)
+#
+
+config USB_AMD5536UDC
+	tristate "AMD5536 UDC"
+	depends on PCI
+	help
+	   The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
+	   It is a USB Highspeed DMA capable USB device controller. Beside ep0
+	   it provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
+	   The UDC port supports OTG operation, and may be used as a host port
+	   if it's not being used to implement peripheral or OTG roles.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "amd5536udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_FSL_QE
+	tristate "Freescale QE/CPM USB Device Controller"
+	depends on FSL_SOC && (QUICC_ENGINE || CPM)
+	help
+	   Some of Freescale PowerPC processors have a Full Speed
+	   QE/CPM2 USB controller, which support device mode with 4
+	   programmable endpoints. This driver supports the
+	   controller in the MPC8360 and MPC8272, and should work with
+	   controllers having QE or CPM2, given minor tweaks.
+
+	   Set CONFIG_USB_GADGET to "m" to build this driver as a
+	   dynamically linked module called "fsl_qe_udc".
+
+config USB_NET2272
+	tristate "PLX NET2272"
+	help
+	  PLX NET2272 is a USB peripheral controller which supports
+	  both full and high speed USB 2.0 data transfers.
+
+	  It has three configurable endpoints, as well as endpoint zero
+	  (for control transfer).
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "net2272" and force all
+	  gadget drivers to also be dynamically linked.
+
+config USB_NET2272_DMA
+	boolean "Support external DMA controller"
+	depends on USB_NET2272 && HAS_DMA
+	help
+	  The NET2272 part can optionally support an external DMA
+	  controller, but your board has to have support in the
+	  driver itself.
+
+	  If unsure, say "N" here.  The driver works fine in PIO mode.
+
+config USB_NET2280
+	tristate "NetChip 228x / PLX USB338x"
+	depends on PCI
+	help
+	   NetChip 2280 / 2282 is a PCI based USB peripheral controller which
+	   supports both full and high speed USB 2.0 data transfers.
+
+	   It has six configurable endpoints, as well as endpoint zero
+	   (for control transfers) and several endpoints with dedicated
+	   functions.
+
+	   PLX 3380 / 3382 is a PCIe based USB peripheral controller which
+	   supports full, high speed USB 2.0 and super speed USB 3.0
+	   data transfers.
+
+	   It has eight configurable endpoints, as well as endpoint zero
+	   (for control transfers) and several endpoints with dedicated
+	   functions.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "net2280" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_GOKU
+	tristate "Toshiba TC86C001 'Goku-S'"
+	depends on PCI
+	help
+	   The Toshiba TC86C001 is a PCI device which includes controllers
+	   for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
+
+	   The device controller has three configurable (bulk or interrupt)
+	   endpoints, plus endpoint zero (for control transfers).
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "goku_udc" and to force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_EG20T
+	tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
+	depends on PCI
+	help
+	  This is a USB device driver for EG20T PCH.
+	  EG20T PCH is the platform controller hub that is used in Intel's
+	  general embedded platform. EG20T PCH has USB device interface.
+	  Using this interface, it is able to access system devices connected
+	  to USB device.
+	  This driver enables USB device function.
+	  USB device is a USB peripheral controller which
+	  supports both full and high speed USB 2.0 data transfers.
+	  This driver supports both control transfer and bulk transfer modes.
+	  This driver dose not support interrupt transfer or isochronous
+	  transfer modes.
+
+	  This driver also can be used for LAPIS Semiconductor's ML7213 which is
+	  for IVI(In-Vehicle Infotainment) use.
+	  ML7831 is for general purpose use.
+	  ML7213/ML7831 is companion chip for Intel Atom E6xx series.
+	  ML7213/ML7831 is completely compatible for Intel EG20T PCH.
+
+#
+# LAST -- dummy/emulated controller
+#
+
+config USB_DUMMY_HCD
+	tristate "Dummy HCD (DEVELOPMENT)"
+	depends on USB=y || (USB=m && USB_GADGET=m)
+	help
+	  This host controller driver emulates USB, looping all data transfer
+	  requests back to a USB "gadget driver" in the same host.  The host
+	  side is the master; the gadget side is the slave.  Gadget drivers
+	  can be high, full, or low speed; and they have access to endpoints
+	  like those from NET2280, PXA2xx, or SA1100 hardware.
+
+	  This may help in some stages of creating a driver to embed in a
+	  Linux device, since it lets you debug several parts of the gadget
+	  driver without its hardware or drivers being involved.
+
+	  Since such a gadget side driver needs to interoperate with a host
+	  side Linux-USB device driver, this may help to debug both sides
+	  of a USB protocol stack.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "dummy_hcd" and force all
+	  gadget drivers to also be dynamically linked.
+
+# NOTE:  Please keep dummy_hcd LAST so that "real hardware" appears
+# first and will be selected by default.
+
+endmenu
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
new file mode 100644
index 0000000..4096122
--- /dev/null
+++ b/drivers/usb/gadget/udc/Makefile
@@ -0,0 +1,31 @@
+#
+# USB peripheral controller drivers
+#
+obj-$(CONFIG_USB_GADGET)	+= udc-core.o
+obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
+obj-$(CONFIG_USB_NET2272)	+= net2272.o
+obj-$(CONFIG_USB_NET2280)	+= net2280.o
+obj-$(CONFIG_USB_AMD5536UDC)	+= amd5536udc.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
+obj-$(CONFIG_USB_S3C2410)	+= s3c2410_udc.o
+obj-$(CONFIG_USB_AT91)		+= at91_udc.o
+obj-$(CONFIG_USB_ATMEL_USBA)	+= atmel_usba_udc.o
+obj-$(CONFIG_USB_BCM63XX_UDC)	+= bcm63xx_udc.o
+obj-$(CONFIG_USB_FSL_USB2)	+= fsl_usb2_udc.o
+fsl_usb2_udc-y			:= fsl_udc_core.o
+fsl_usb2_udc-$(CONFIG_ARCH_MXC)	+= fsl_mxc_udc.o
+obj-$(CONFIG_USB_M66592)	+= m66592-udc.o
+obj-$(CONFIG_USB_R8A66597)	+= r8a66597-udc.o
+obj-$(CONFIG_USB_FSL_QE)	+= fsl_qe_udc.o
+obj-$(CONFIG_USB_S3C_HSUDC)	+= s3c-hsudc.o
+obj-$(CONFIG_USB_LPC32XX)	+= lpc32xx_udc.o
+obj-$(CONFIG_USB_EG20T)		+= pch_udc.o
+obj-$(CONFIG_USB_MV_UDC)	+= mv_udc.o
+mv_udc-y			:= mv_udc_core.o
+obj-$(CONFIG_USB_FUSB300)	+= fusb300_udc.o
+obj-$(CONFIG_USB_FOTG210_UDC)	+= fotg210-udc.o
+obj-$(CONFIG_USB_MV_U3D)	+= mv_u3d_core.o
+obj-$(CONFIG_USB_GR_UDC)	+= gr_udc.o
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/udc/amd5536udc.c
similarity index 100%
rename from drivers/usb/gadget/amd5536udc.c
rename to drivers/usb/gadget/udc/amd5536udc.c
diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/udc/amd5536udc.h
similarity index 100%
rename from drivers/usb/gadget/amd5536udc.h
rename to drivers/usb/gadget/udc/amd5536udc.h
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c
similarity index 100%
rename from drivers/usb/gadget/at91_udc.c
rename to drivers/usb/gadget/udc/at91_udc.c
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/udc/at91_udc.h
similarity index 100%
rename from drivers/usb/gadget/at91_udc.h
rename to drivers/usb/gadget/udc/at91_udc.h
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
similarity index 99%
rename from drivers/usb/gadget/atmel_usba_udc.c
rename to drivers/usb/gadget/udc/atmel_usba_udc.c
index 76023ce..906e65f 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -1979,7 +1979,7 @@
 	return eps;
 }
 
-static int __init usba_udc_probe(struct platform_device *pdev)
+static int usba_udc_probe(struct platform_device *pdev)
 {
 	struct resource *regs, *fifo;
 	struct clk *pclk, *hclk;
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h
similarity index 100%
rename from drivers/usb/gadget/atmel_usba_udc.h
rename to drivers/usb/gadget/udc/atmel_usba_udc.h
diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c
similarity index 100%
rename from drivers/usb/gadget/bcm63xx_udc.c
rename to drivers/usb/gadget/udc/bcm63xx_udc.c
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
similarity index 100%
rename from drivers/usb/gadget/dummy_hcd.c
rename to drivers/usb/gadget/udc/dummy_hcd.c
diff --git a/drivers/usb/gadget/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c
similarity index 100%
rename from drivers/usb/gadget/fotg210-udc.c
rename to drivers/usb/gadget/udc/fotg210-udc.c
diff --git a/drivers/usb/gadget/fotg210.h b/drivers/usb/gadget/udc/fotg210.h
similarity index 100%
rename from drivers/usb/gadget/fotg210.h
rename to drivers/usb/gadget/udc/fotg210.h
diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/udc/fsl_mxc_udc.c
similarity index 98%
rename from drivers/usb/gadget/fsl_mxc_udc.c
rename to drivers/usb/gadget/udc/fsl_mxc_udc.c
index 9b140fc..f16e149 100644
--- a/drivers/usb/gadget/fsl_mxc_udc.c
+++ b/drivers/usb/gadget/udc/fsl_mxc_udc.c
@@ -18,6 +18,8 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
+#include "fsl_usb2_udc.h"
+
 static struct clk *mxc_ahb_clk;
 static struct clk *mxc_per_clk;
 static struct clk *mxc_ipg_clk;
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
similarity index 99%
rename from drivers/usb/gadget/fsl_qe_udc.c
rename to drivers/usb/gadget/udc/fsl_qe_udc.c
index ad54833..7324308 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -2539,7 +2539,7 @@
 		goto err2;
 
 	/* create a buf for ZLP send, need to remain zeroed */
-	udc->nullbuf = kzalloc(256, GFP_KERNEL);
+	udc->nullbuf = devm_kzalloc(&ofdev->dev, 256, GFP_KERNEL);
 	if (udc->nullbuf == NULL) {
 		dev_err(udc->dev, "cannot alloc nullbuf\n");
 		ret = -ENOMEM;
@@ -2547,10 +2547,10 @@
 	}
 
 	/* buffer for data of get_status request */
-	udc->statusbuf = kzalloc(2, GFP_KERNEL);
+	udc->statusbuf = devm_kzalloc(&ofdev->dev, 2, GFP_KERNEL);
 	if (udc->statusbuf == NULL) {
 		ret = -ENOMEM;
-		goto err4;
+		goto err3;
 	}
 
 	udc->nullp = virt_to_phys((void *)udc->nullbuf);
@@ -2581,13 +2581,13 @@
 	if (ret) {
 		dev_err(udc->dev, "cannot request irq %d err %d\n",
 				udc->usb_irq, ret);
-		goto err5;
+		goto err4;
 	}
 
 	ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
 			qe_udc_release);
 	if (ret)
-		goto err6;
+		goto err5;
 
 	platform_set_drvdata(ofdev, udc);
 	dev_info(udc->dev,
@@ -2595,9 +2595,9 @@
 			(udc->soc_type == PORT_QE) ? "QE" : "CPM");
 	return 0;
 
-err6:
-	free_irq(udc->usb_irq, udc);
 err5:
+	free_irq(udc->usb_irq, udc);
+err4:
 	irq_dispose_mapping(udc->usb_irq);
 err_noirq:
 	if (udc->nullmap) {
@@ -2610,9 +2610,6 @@
 			udc->nullp, 256,
 				DMA_TO_DEVICE);
 	}
-	kfree(udc->statusbuf);
-err4:
-	kfree(udc->nullbuf);
 err3:
 	ep = &udc->eps[0];
 	cpm_muram_free(cpm_muram_offset(ep->rxbase));
@@ -2660,8 +2657,6 @@
 			udc->nullp, 256,
 				DMA_TO_DEVICE);
 	}
-	kfree(udc->statusbuf);
-	kfree(udc->nullbuf);
 
 	ep = &udc->eps[0];
 	cpm_muram_free(cpm_muram_offset(ep->rxbase));
diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/udc/fsl_qe_udc.h
similarity index 100%
rename from drivers/usb/gadget/fsl_qe_udc.h
rename to drivers/usb/gadget/udc/fsl_qe_udc.h
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
similarity index 99%
rename from drivers/usb/gadget/fsl_udc_core.c
rename to drivers/usb/gadget/udc/fsl_udc_core.c
index 28e4fc9..75b23ea 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -59,9 +59,9 @@
 static const char driver_name[] = "fsl-usb2-udc";
 static const char driver_desc[] = DRIVER_DESC;
 
-static struct usb_dr_device *dr_regs;
+static struct usb_dr_device __iomem *dr_regs;
 
-static struct usb_sys_interface *usb_sys_regs;
+static struct usb_sys_interface __iomem *usb_sys_regs;
 
 /* it is initialized in probe()  */
 static struct fsl_udc *udc_controller = NULL;
@@ -159,6 +159,8 @@
  *	request is still in progress.
  *--------------------------------------------------------------*/
 static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
+__releases(ep->udc->lock)
+__acquires(ep->udc->lock)
 {
 	struct fsl_udc *udc = NULL;
 	unsigned char stopped = ep->stopped;
@@ -1392,6 +1394,8 @@
 
 static void setup_received_irq(struct fsl_udc *udc,
 		struct usb_ctrlrequest *setup)
+__releases(udc->lock)
+__acquires(udc->lock)
 {
 	u16 wValue = le16_to_cpu(setup->wValue);
 	u16 wIndex = le16_to_cpu(setup->wIndex);
@@ -1957,8 +1961,7 @@
 						    &udc_controller->gadget);
 			if (retval < 0) {
 				ERR("can't bind to transceiver\n");
-				driver->unbind(&udc_controller->gadget);
-				udc_controller->driver = 0;
+				udc_controller->driver = NULL;
 				return retval;
 			}
 		}
@@ -2246,7 +2249,7 @@
  * init resource for globle controller
  * Return the udc handle on success or NULL on failure
  ------------------------------------------------------------------*/
-static int __init struct_udc_setup(struct fsl_udc *udc,
+static int struct_udc_setup(struct fsl_udc *udc,
 		struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata;
@@ -2298,7 +2301,7 @@
  * ep0out is not used so do nothing here
  * ep0in should be taken care
  *--------------------------------------------------------------*/
-static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
+static int struct_ep_setup(struct fsl_udc *udc, unsigned char index,
 		char *name, int link)
 {
 	struct fsl_ep *ep = &udc->eps[index];
@@ -2331,7 +2334,7 @@
  * all intialization operations implemented here except enabling usb_intr reg
  * board setup should have been done in the platform code
  */
-static int __init fsl_udc_probe(struct platform_device *pdev)
+static int fsl_udc_probe(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata;
 	struct resource *res;
@@ -2380,7 +2383,7 @@
 		goto err_release_mem_region;
 	}
 
-	pdata->regs = (void *)dr_regs;
+	pdata->regs = (void __iomem *)dr_regs;
 
 	/*
 	 * do platform specific init: check the clock, grab/config pins, etc.
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/udc/fsl_usb2_udc.h
similarity index 99%
rename from drivers/usb/gadget/fsl_usb2_udc.h
rename to drivers/usb/gadget/udc/fsl_usb2_udc.h
index c6703bb..8471562 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/udc/fsl_usb2_udc.h
@@ -12,6 +12,9 @@
 #ifndef __FSL_USB2_UDC_H
 #define __FSL_USB2_UDC_H
 
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
 /* ### define USB registers here
  */
 #define USB_MAX_CTRL_PAYLOAD		64
diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c
similarity index 99%
rename from drivers/usb/gadget/fusb300_udc.c
rename to drivers/usb/gadget/udc/fusb300_udc.c
index 3deb4e9..d40255f 100644
--- a/drivers/usb/gadget/fusb300_udc.c
+++ b/drivers/usb/gadget/udc/fusb300_udc.c
@@ -1325,8 +1325,6 @@
 {
 	struct fusb300 *fusb300 = to_fusb300(g);
 
-	driver->unbind(&fusb300->gadget);
-
 	init_controller(fusb300);
 	fusb300->driver = NULL;
 
@@ -1359,7 +1357,7 @@
 	return 0;
 }
 
-static int __init fusb300_probe(struct platform_device *pdev)
+static int fusb300_probe(struct platform_device *pdev)
 {
 	struct resource *res, *ires, *ires1;
 	void __iomem *reg = NULL;
diff --git a/drivers/usb/gadget/fusb300_udc.h b/drivers/usb/gadget/udc/fusb300_udc.h
similarity index 100%
rename from drivers/usb/gadget/fusb300_udc.h
rename to drivers/usb/gadget/udc/fusb300_udc.h
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/udc/gadget_chips.h
similarity index 100%
rename from drivers/usb/gadget/gadget_chips.h
rename to drivers/usb/gadget/udc/gadget_chips.h
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/udc/goku_udc.c
similarity index 100%
rename from drivers/usb/gadget/goku_udc.c
rename to drivers/usb/gadget/udc/goku_udc.c
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/udc/goku_udc.h
similarity index 100%
rename from drivers/usb/gadget/goku_udc.h
rename to drivers/usb/gadget/udc/goku_udc.h
diff --git a/drivers/usb/gadget/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c
similarity index 99%
rename from drivers/usb/gadget/gr_udc.c
rename to drivers/usb/gadget/udc/gr_udc.c
index c7004ee..08df5c4 100644
--- a/drivers/usb/gadget/gr_udc.c
+++ b/drivers/usb/gadget/udc/gr_udc.c
@@ -2213,7 +2213,7 @@
 	return retval;
 }
 
-static struct of_device_id gr_match[] = {
+static const struct of_device_id gr_match[] = {
 	{.name = "GAISLER_USBDC"},
 	{.name = "01_021"},
 	{},
diff --git a/drivers/usb/gadget/gr_udc.h b/drivers/usb/gadget/udc/gr_udc.h
similarity index 100%
rename from drivers/usb/gadget/gr_udc.h
rename to drivers/usb/gadget/udc/gr_udc.h
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
similarity index 99%
rename from drivers/usb/gadget/lpc32xx_udc.c
rename to drivers/usb/gadget/udc/lpc32xx_udc.c
index e471580..1629ad7 100644
--- a/drivers/usb/gadget/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -3036,7 +3036,7 @@
 
 static u64 lpc32xx_usbd_dmamask = ~(u32) 0x7F;
 
-static int __init lpc32xx_udc_probe(struct platform_device *pdev)
+static int lpc32xx_udc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct lpc32xx_udc *udc;
@@ -3045,11 +3045,10 @@
 	dma_addr_t dma_handle;
 	struct device_node *isp1301_node;
 
-	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
+	udc = kmemdup(&controller_template, sizeof(*udc), GFP_KERNEL);
 	if (!udc)
 		return -ENOMEM;
 
-	memcpy(udc, &controller_template, sizeof(*udc));
 	for (i = 0; i <= 15; i++)
 		udc->ep[i].udc = udc;
 	udc->gadget.ep0 = &udc->ep[0].ep;
@@ -3397,7 +3396,7 @@
 #endif
 
 #ifdef CONFIG_OF
-static struct of_device_id lpc32xx_udc_of_match[] = {
+static const struct of_device_id lpc32xx_udc_of_match[] = {
 	{ .compatible = "nxp,lpc3220-udc", },
 	{ },
 };
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c
similarity index 99%
rename from drivers/usb/gadget/m66592-udc.c
rename to drivers/usb/gadget/udc/m66592-udc.c
index 0d17174..de88d33 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/udc/m66592-udc.c
@@ -1492,8 +1492,6 @@
 
 	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 
-	driver->unbind(&m66592->gadget);
-
 	init_controller(m66592);
 	disable_controller(m66592);
 
@@ -1553,7 +1551,7 @@
 {
 }
 
-static int __init m66592_probe(struct platform_device *pdev)
+static int m66592_probe(struct platform_device *pdev)
 {
 	struct resource *res, *ires;
 	void __iomem *reg = NULL;
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/udc/m66592-udc.h
similarity index 100%
rename from drivers/usb/gadget/m66592-udc.h
rename to drivers/usb/gadget/udc/m66592-udc.h
diff --git a/drivers/usb/gadget/mv_u3d.h b/drivers/usb/gadget/udc/mv_u3d.h
similarity index 100%
rename from drivers/usb/gadget/mv_u3d.h
rename to drivers/usb/gadget/udc/mv_u3d.h
diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c
similarity index 100%
rename from drivers/usb/gadget/mv_u3d_core.c
rename to drivers/usb/gadget/udc/mv_u3d_core.c
diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/udc/mv_udc.h
similarity index 100%
rename from drivers/usb/gadget/mv_udc.h
rename to drivers/usb/gadget/udc/mv_udc.h
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c
similarity index 100%
rename from drivers/usb/gadget/mv_udc_core.c
rename to drivers/usb/gadget/udc/mv_udc_core.c
diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/udc/net2272.c
similarity index 99%
rename from drivers/usb/gadget/net2272.c
rename to drivers/usb/gadget/udc/net2272.c
index ca15405..059cfe5 100644
--- a/drivers/usb/gadget/net2272.c
+++ b/drivers/usb/gadget/udc/net2272.c
@@ -1453,7 +1453,7 @@
 	struct net2272 *dev;
 	unsigned i;
 
-	if (!driver || !driver->unbind || !driver->setup ||
+	if (!driver || !driver->setup ||
 	    driver->max_speed != USB_SPEED_HIGH)
 		return -EINVAL;
 
diff --git a/drivers/usb/gadget/net2272.h b/drivers/usb/gadget/udc/net2272.h
similarity index 100%
rename from drivers/usb/gadget/net2272.h
rename to drivers/usb/gadget/udc/net2272.h
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
new file mode 100644
index 0000000..f4eac11
--- /dev/null
+++ b/drivers/usb/gadget/udc/net2280.c
@@ -0,0 +1,3827 @@
+/*
+ * Driver for the PLX NET2280 USB device controller.
+ * Specs and errata are available from <http://www.plxtech.com>.
+ *
+ * PLX Technology Inc. (formerly NetChip Technology) supported the
+ * development of this driver.
+ *
+ *
+ * CODE STATUS HIGHLIGHTS
+ *
+ * This driver should work well with most "gadget" drivers, including
+ * the Mass Storage, Serial, and Ethernet/RNDIS gadget drivers
+ * as well as Gadget Zero and Gadgetfs.
+ *
+ * DMA is enabled by default.  Drivers using transfer queues might use
+ * DMA chaining to remove IRQ latencies between transfers.  (Except when
+ * short OUT transfers happen.)  Drivers can use the req->no_interrupt
+ * hint to completely eliminate some IRQs, if a later IRQ is guaranteed
+ * and DMA chaining is enabled.
+ *
+ * MSI is enabled by default.  The legacy IRQ is used if MSI couldn't
+ * be enabled.
+ *
+ * Note that almost all the errata workarounds here are only needed for
+ * rev1 chips.  Rev1a silicon (0110) fixes almost all of them.
+ */
+
+/*
+ * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2003-2005 PLX Technology, Inc.
+ * Copyright (C) 2014 Ricardo Ribalda - Qtechnology/AS
+ *
+ * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility
+ *	with 2282 chip
+ *
+ * Modified Ricardo Ribalda Qtechnology AS  to provide compatibility
+ *	with usb 338x chip. Based on PLX driver
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/prefetch.h>
+#include <linux/io.h>
+
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/unaligned.h>
+
+#define	DRIVER_DESC		"PLX NET228x/USB338x USB Peripheral Controller"
+#define	DRIVER_VERSION		"2005 Sept 27/v3.0"
+
+#define	EP_DONTUSE		13	/* nonzero */
+
+#define USE_RDK_LEDS		/* GPIO pins control three LEDs */
+
+
+static const char driver_name[] = "net2280";
+static const char driver_desc[] = DRIVER_DESC;
+
+static const u32 ep_bit[9] = { 0, 17, 2, 19, 4, 1, 18, 3, 20 };
+static const char ep0name[] = "ep0";
+static const char *const ep_name[] = {
+	ep0name,
+	"ep-a", "ep-b", "ep-c", "ep-d",
+	"ep-e", "ep-f", "ep-g", "ep-h",
+};
+
+/* use_dma -- general goodness, fewer interrupts, less cpu load (vs PIO)
+ * use_dma_chaining -- dma descriptor queueing gives even more irq reduction
+ *
+ * The net2280 DMA engines are not tightly integrated with their FIFOs;
+ * not all cases are (yet) handled well in this driver or the silicon.
+ * Some gadget drivers work better with the dma support here than others.
+ * These two parameters let you use PIO or more aggressive DMA.
+ */
+static bool use_dma = true;
+static bool use_dma_chaining;
+static bool use_msi = true;
+
+/* "modprobe net2280 use_dma=n" etc */
+module_param(use_dma, bool, 0444);
+module_param(use_dma_chaining, bool, 0444);
+module_param(use_msi, bool, 0444);
+
+/* mode 0 == ep-{a,b,c,d} 1K fifo each
+ * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable
+ * mode 2 == ep-a 2K fifo, ep-{b,c} 1K each, ep-d unavailable
+ */
+static ushort fifo_mode;
+
+/* "modprobe net2280 fifo_mode=1" etc */
+module_param(fifo_mode, ushort, 0644);
+
+/* enable_suspend -- When enabled, the driver will respond to
+ * USB suspend requests by powering down the NET2280.  Otherwise,
+ * USB suspend requests will be ignored.  This is acceptable for
+ * self-powered devices
+ */
+static bool enable_suspend;
+
+/* "modprobe net2280 enable_suspend=1" etc */
+module_param(enable_suspend, bool, 0444);
+
+/* force full-speed operation */
+static bool full_speed;
+module_param(full_speed, bool, 0444);
+MODULE_PARM_DESC(full_speed, "force full-speed mode -- for testing only!");
+
+#define	DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out")
+
+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";
+}
+
+#include "net2280.h"
+
+#define valid_bit	cpu_to_le32(BIT(VALID_BIT))
+#define dma_done_ie	cpu_to_le32(BIT(DMA_DONE_INTERRUPT_ENABLE))
+
+/*-------------------------------------------------------------------------*/
+static inline void enable_pciirqenb(struct net2280_ep *ep)
+{
+	u32 tmp = readl(&ep->dev->regs->pciirqenb0);
+
+	if (ep->dev->quirks & PLX_LEGACY)
+		tmp |= BIT(ep->num);
+	else
+		tmp |= BIT(ep_bit[ep->num]);
+	writel(tmp, &ep->dev->regs->pciirqenb0);
+
+	return;
+}
+
+static int
+net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+{
+	struct net2280		*dev;
+	struct net2280_ep	*ep;
+	u32			max, tmp;
+	unsigned long		flags;
+	static const u32 ep_key[9] = { 1, 0, 1, 0, 1, 1, 0, 1, 0 };
+
+	ep = container_of(_ep, struct net2280_ep, ep);
+	if (!_ep || !desc || ep->desc || _ep->name == ep0name ||
+			desc->bDescriptorType != USB_DT_ENDPOINT)
+		return -EINVAL;
+	dev = ep->dev;
+	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	/* erratum 0119 workaround ties up an endpoint number */
+	if ((desc->bEndpointAddress & 0x0f) == EP_DONTUSE)
+		return -EDOM;
+
+	if (dev->quirks & PLX_SUPERSPEED) {
+		if ((desc->bEndpointAddress & 0x0f) >= 0x0c)
+			return -EDOM;
+		ep->is_in = !!usb_endpoint_dir_in(desc);
+		if (dev->enhanced_mode && ep->is_in && ep_key[ep->num])
+			return -EINVAL;
+	}
+
+	/* sanity check ep-e/ep-f since their fifos are small */
+	max = usb_endpoint_maxp(desc) & 0x1fff;
+	if (ep->num > 4 && max > 64 && (dev->quirks & PLX_LEGACY))
+		return -ERANGE;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	_ep->maxpacket = max & 0x7ff;
+	ep->desc = desc;
+
+	/* ep_reset() has already been called */
+	ep->stopped = 0;
+	ep->wedged = 0;
+	ep->out_overflow = 0;
+
+	/* set speed-dependent max packet; may kick in high bandwidth */
+	set_max_speed(ep, max);
+
+	/* FIFO lines can't go to different packets.  PIO is ok, so
+	 * use it instead of troublesome (non-bulk) multi-packet DMA.
+	 */
+	if (ep->dma && (max % 4) != 0 && use_dma_chaining) {
+		ep_dbg(ep->dev, "%s, no dma for maxpacket %d\n",
+			ep->ep.name, ep->ep.maxpacket);
+		ep->dma = NULL;
+	}
+
+	/* set type, direction, address; reset fifo counters */
+	writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat);
+	tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+	if (tmp == USB_ENDPOINT_XFER_INT) {
+		/* erratum 0105 workaround prevents hs NYET */
+		if (dev->chiprev == 0100 &&
+				dev->gadget.speed == USB_SPEED_HIGH &&
+				!(desc->bEndpointAddress & USB_DIR_IN))
+			writel(BIT(CLEAR_NAK_OUT_PACKETS_MODE),
+				&ep->regs->ep_rsp);
+	} else if (tmp == USB_ENDPOINT_XFER_BULK) {
+		/* catch some particularly blatant driver bugs */
+		if ((dev->gadget.speed == USB_SPEED_SUPER && max != 1024) ||
+		    (dev->gadget.speed == USB_SPEED_HIGH && max != 512) ||
+		    (dev->gadget.speed == USB_SPEED_FULL && max > 64)) {
+			spin_unlock_irqrestore(&dev->lock, flags);
+			return -ERANGE;
+		}
+	}
+	ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC);
+	/* Enable this endpoint */
+	if (dev->quirks & PLX_LEGACY) {
+		tmp <<= ENDPOINT_TYPE;
+		tmp |= desc->bEndpointAddress;
+		/* default full fifo lines */
+		tmp |= (4 << ENDPOINT_BYTE_COUNT);
+		tmp |= BIT(ENDPOINT_ENABLE);
+		ep->is_in = (tmp & USB_DIR_IN) != 0;
+	} else {
+		/* In Legacy mode, only OUT endpoints are used */
+		if (dev->enhanced_mode && ep->is_in) {
+			tmp <<= IN_ENDPOINT_TYPE;
+			tmp |= BIT(IN_ENDPOINT_ENABLE);
+			/* Not applicable to Legacy */
+			tmp |= BIT(ENDPOINT_DIRECTION);
+		} else {
+			tmp <<= OUT_ENDPOINT_TYPE;
+			tmp |= BIT(OUT_ENDPOINT_ENABLE);
+			tmp |= (ep->is_in << ENDPOINT_DIRECTION);
+		}
+
+		tmp |= usb_endpoint_num(desc);
+		tmp |= (ep->ep.maxburst << MAX_BURST_SIZE);
+	}
+
+	/* Make sure all the registers are written before ep_rsp*/
+	wmb();
+
+	/* for OUT transfers, block the rx fifo until a read is posted */
+	if (!ep->is_in)
+		writel(BIT(SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
+	else if (!(dev->quirks & PLX_2280)) {
+		/* Added for 2282, Don't use nak packets on an in endpoint,
+		 * this was ignored on 2280
+		 */
+		writel(BIT(CLEAR_NAK_OUT_PACKETS) |
+			BIT(CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
+	}
+
+	writel(tmp, &ep->cfg->ep_cfg);
+
+	/* enable irqs */
+	if (!ep->dma) {				/* pio, per-packet */
+		enable_pciirqenb(ep);
+
+		tmp = BIT(DATA_PACKET_RECEIVED_INTERRUPT_ENABLE) |
+			BIT(DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE);
+		if (dev->quirks & PLX_2280)
+			tmp |= readl(&ep->regs->ep_irqenb);
+		writel(tmp, &ep->regs->ep_irqenb);
+	} else {				/* dma, per-request */
+		tmp = BIT((8 + ep->num));	/* completion */
+		tmp |= readl(&dev->regs->pciirqenb1);
+		writel(tmp, &dev->regs->pciirqenb1);
+
+		/* for short OUT transfers, dma completions can't
+		 * advance the queue; do it pio-style, by hand.
+		 * NOTE erratum 0112 workaround #2
+		 */
+		if ((desc->bEndpointAddress & USB_DIR_IN) == 0) {
+			tmp = BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE);
+			writel(tmp, &ep->regs->ep_irqenb);
+
+			enable_pciirqenb(ep);
+		}
+	}
+
+	tmp = desc->bEndpointAddress;
+	ep_dbg(dev, "enabled %s (ep%d%s-%s) %s max %04x\n",
+		_ep->name, tmp & 0x0f, DIR_STRING(tmp),
+		type_string(desc->bmAttributes),
+		ep->dma ? "dma" : "pio", max);
+
+	/* pci writes may still be posted */
+	spin_unlock_irqrestore(&dev->lock, flags);
+	return 0;
+}
+
+static int handshake(u32 __iomem *ptr, u32 mask, u32 done, int usec)
+{
+	u32	result;
+
+	do {
+		result = readl(ptr);
+		if (result == ~(u32)0)		/* "device unplugged" */
+			return -ENODEV;
+		result &= mask;
+		if (result == done)
+			return 0;
+		udelay(1);
+		usec--;
+	} while (usec > 0);
+	return -ETIMEDOUT;
+}
+
+static const struct usb_ep_ops net2280_ep_ops;
+
+static void ep_reset_228x(struct net2280_regs __iomem *regs,
+			  struct net2280_ep *ep)
+{
+	u32		tmp;
+
+	ep->desc = NULL;
+	INIT_LIST_HEAD(&ep->queue);
+
+	usb_ep_set_maxpacket_limit(&ep->ep, ~0);
+	ep->ep.ops = &net2280_ep_ops;
+
+	/* disable the dma, irqs, endpoint... */
+	if (ep->dma) {
+		writel(0, &ep->dma->dmactl);
+		writel(BIT(DMA_SCATTER_GATHER_DONE_INTERRUPT) |
+			BIT(DMA_TRANSACTION_DONE_INTERRUPT) |
+			BIT(DMA_ABORT),
+			&ep->dma->dmastat);
+
+		tmp = readl(&regs->pciirqenb0);
+		tmp &= ~BIT(ep->num);
+		writel(tmp, &regs->pciirqenb0);
+	} else {
+		tmp = readl(&regs->pciirqenb1);
+		tmp &= ~BIT((8 + ep->num));	/* completion */
+		writel(tmp, &regs->pciirqenb1);
+	}
+	writel(0, &ep->regs->ep_irqenb);
+
+	/* init to our chosen defaults, notably so that we NAK OUT
+	 * packets until the driver queues a read (+note erratum 0112)
+	 */
+	if (!ep->is_in || (ep->dev->quirks & PLX_2280)) {
+		tmp = BIT(SET_NAK_OUT_PACKETS_MODE) |
+		BIT(SET_NAK_OUT_PACKETS) |
+		BIT(CLEAR_EP_HIDE_STATUS_PHASE) |
+		BIT(CLEAR_INTERRUPT_MODE);
+	} else {
+		/* added for 2282 */
+		tmp = BIT(CLEAR_NAK_OUT_PACKETS_MODE) |
+		BIT(CLEAR_NAK_OUT_PACKETS) |
+		BIT(CLEAR_EP_HIDE_STATUS_PHASE) |
+		BIT(CLEAR_INTERRUPT_MODE);
+	}
+
+	if (ep->num != 0) {
+		tmp |= BIT(CLEAR_ENDPOINT_TOGGLE) |
+			BIT(CLEAR_ENDPOINT_HALT);
+	}
+	writel(tmp, &ep->regs->ep_rsp);
+
+	/* scrub most status bits, and flush any fifo state */
+	if (ep->dev->quirks & PLX_2280)
+		tmp = BIT(FIFO_OVERFLOW) |
+			BIT(FIFO_UNDERFLOW);
+	else
+		tmp = 0;
+
+	writel(tmp | BIT(TIMEOUT) |
+		BIT(USB_STALL_SENT) |
+		BIT(USB_IN_NAK_SENT) |
+		BIT(USB_IN_ACK_RCVD) |
+		BIT(USB_OUT_PING_NAK_SENT) |
+		BIT(USB_OUT_ACK_SENT) |
+		BIT(FIFO_FLUSH) |
+		BIT(SHORT_PACKET_OUT_DONE_INTERRUPT) |
+		BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT) |
+		BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
+		BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
+		BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
+		BIT(DATA_IN_TOKEN_INTERRUPT),
+		&ep->regs->ep_stat);
+
+	/* fifo size is handled separately */
+}
+
+static void ep_reset_338x(struct net2280_regs __iomem *regs,
+					struct net2280_ep *ep)
+{
+	u32 tmp, dmastat;
+
+	ep->desc = NULL;
+	INIT_LIST_HEAD(&ep->queue);
+
+	usb_ep_set_maxpacket_limit(&ep->ep, ~0);
+	ep->ep.ops = &net2280_ep_ops;
+
+	/* disable the dma, irqs, endpoint... */
+	if (ep->dma) {
+		writel(0, &ep->dma->dmactl);
+		writel(BIT(DMA_ABORT_DONE_INTERRUPT) |
+		       BIT(DMA_PAUSE_DONE_INTERRUPT) |
+		       BIT(DMA_SCATTER_GATHER_DONE_INTERRUPT) |
+		       BIT(DMA_TRANSACTION_DONE_INTERRUPT),
+		       /* | BIT(DMA_ABORT), */
+		       &ep->dma->dmastat);
+
+		dmastat = readl(&ep->dma->dmastat);
+		if (dmastat == 0x5002) {
+			ep_warn(ep->dev, "The dmastat return = %x!!\n",
+			       dmastat);
+			writel(0x5a, &ep->dma->dmastat);
+		}
+
+		tmp = readl(&regs->pciirqenb0);
+		tmp &= ~BIT(ep_bit[ep->num]);
+		writel(tmp, &regs->pciirqenb0);
+	} else {
+		if (ep->num < 5) {
+			tmp = readl(&regs->pciirqenb1);
+			tmp &= ~BIT((8 + ep->num));	/* completion */
+			writel(tmp, &regs->pciirqenb1);
+		}
+	}
+	writel(0, &ep->regs->ep_irqenb);
+
+	writel(BIT(SHORT_PACKET_OUT_DONE_INTERRUPT) |
+	       BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT) |
+	       BIT(FIFO_OVERFLOW) |
+	       BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
+	       BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
+	       BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
+	       BIT(DATA_IN_TOKEN_INTERRUPT), &ep->regs->ep_stat);
+}
+
+static void nuke(struct net2280_ep *);
+
+static int net2280_disable(struct usb_ep *_ep)
+{
+	struct net2280_ep	*ep;
+	unsigned long		flags;
+
+	ep = container_of(_ep, struct net2280_ep, ep);
+	if (!_ep || !ep->desc || _ep->name == ep0name)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ep->dev->lock, flags);
+	nuke(ep);
+
+	if (ep->dev->quirks & PLX_SUPERSPEED)
+		ep_reset_338x(ep->dev->regs, ep);
+	else
+		ep_reset_228x(ep->dev->regs, ep);
+
+	ep_vdbg(ep->dev, "disabled %s %s\n",
+			ep->dma ? "dma" : "pio", _ep->name);
+
+	/* synch memory views with the device */
+	(void)readl(&ep->cfg->ep_cfg);
+
+	if (use_dma && !ep->dma && ep->num >= 1 && ep->num <= 4)
+		ep->dma = &ep->dev->dma[ep->num - 1];
+
+	spin_unlock_irqrestore(&ep->dev->lock, flags);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_request
+*net2280_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+	struct net2280_ep	*ep;
+	struct net2280_request	*req;
+
+	if (!_ep)
+		return NULL;
+	ep = container_of(_ep, struct net2280_ep, ep);
+
+	req = kzalloc(sizeof(*req), gfp_flags);
+	if (!req)
+		return NULL;
+
+	INIT_LIST_HEAD(&req->queue);
+
+	/* this dma descriptor may be swapped with the previous dummy */
+	if (ep->dma) {
+		struct net2280_dma	*td;
+
+		td = pci_pool_alloc(ep->dev->requests, gfp_flags,
+				&req->td_dma);
+		if (!td) {
+			kfree(req);
+			return NULL;
+		}
+		td->dmacount = 0;	/* not VALID */
+		td->dmadesc = td->dmaaddr;
+		req->td = td;
+	}
+	return &req->req;
+}
+
+static void net2280_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct net2280_ep	*ep;
+	struct net2280_request	*req;
+
+	ep = container_of(_ep, struct net2280_ep, ep);
+	if (!_ep || !_req)
+		return;
+
+	req = container_of(_req, struct net2280_request, req);
+	WARN_ON(!list_empty(&req->queue));
+	if (req->td)
+		pci_pool_free(ep->dev->requests, req->td, req->td_dma);
+	kfree(req);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* load a packet into the fifo we use for usb IN transfers.
+ * works for all endpoints.
+ *
+ * NOTE: pio with ep-a..ep-d could stuff multiple packets into the fifo
+ * at a time, but this code is simpler because it knows it only writes
+ * one packet.  ep-a..ep-d should use dma instead.
+ */
+static void write_fifo(struct net2280_ep *ep, struct usb_request *req)
+{
+	struct net2280_ep_regs	__iomem *regs = ep->regs;
+	u8			*buf;
+	u32			tmp;
+	unsigned		count, total;
+
+	/* INVARIANT:  fifo is currently empty. (testable) */
+
+	if (req) {
+		buf = req->buf + req->actual;
+		prefetch(buf);
+		total = req->length - req->actual;
+	} else {
+		total = 0;
+		buf = NULL;
+	}
+
+	/* write just one packet at a time */
+	count = ep->ep.maxpacket;
+	if (count > total)	/* min() cannot be used on a bitfield */
+		count = total;
+
+	ep_vdbg(ep->dev, "write %s fifo (IN) %d bytes%s req %p\n",
+			ep->ep.name, count,
+			(count != ep->ep.maxpacket) ? " (short)" : "",
+			req);
+	while (count >= 4) {
+		/* NOTE be careful if you try to align these. fifo lines
+		 * should normally be full (4 bytes) and successive partial
+		 * lines are ok only in certain cases.
+		 */
+		tmp = get_unaligned((u32 *)buf);
+		cpu_to_le32s(&tmp);
+		writel(tmp, &regs->ep_data);
+		buf += 4;
+		count -= 4;
+	}
+
+	/* last fifo entry is "short" unless we wrote a full packet.
+	 * also explicitly validate last word in (periodic) transfers
+	 * when maxpacket is not a multiple of 4 bytes.
+	 */
+	if (count || total < ep->ep.maxpacket) {
+		tmp = count ? get_unaligned((u32 *)buf) : count;
+		cpu_to_le32s(&tmp);
+		set_fifo_bytecount(ep, count & 0x03);
+		writel(tmp, &regs->ep_data);
+	}
+
+	/* pci writes may still be posted */
+}
+
+/* work around erratum 0106: PCI and USB race over the OUT fifo.
+ * caller guarantees chiprev 0100, out endpoint is NAKing, and
+ * there's no real data in the fifo.
+ *
+ * NOTE:  also used in cases where that erratum doesn't apply:
+ * where the host wrote "too much" data to us.
+ */
+static void out_flush(struct net2280_ep *ep)
+{
+	u32	__iomem *statp;
+	u32	tmp;
+
+	ASSERT_OUT_NAKING(ep);
+
+	statp = &ep->regs->ep_stat;
+	writel(BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
+		BIT(DATA_PACKET_RECEIVED_INTERRUPT),
+		statp);
+	writel(BIT(FIFO_FLUSH), statp);
+	/* Make sure that stap is written */
+	mb();
+	tmp = readl(statp);
+	if (tmp & BIT(DATA_OUT_PING_TOKEN_INTERRUPT) &&
+			/* high speed did bulk NYET; fifo isn't filling */
+			ep->dev->gadget.speed == USB_SPEED_FULL) {
+		unsigned	usec;
+
+		usec = 50;		/* 64 byte bulk/interrupt */
+		handshake(statp, BIT(USB_OUT_PING_NAK_SENT),
+				BIT(USB_OUT_PING_NAK_SENT), usec);
+		/* NAK done; now CLEAR_NAK_OUT_PACKETS is safe */
+	}
+}
+
+/* unload packet(s) from the fifo we use for usb OUT transfers.
+ * returns true iff the request completed, because of short packet
+ * or the request buffer having filled with full packets.
+ *
+ * for ep-a..ep-d this will read multiple packets out when they
+ * have been accepted.
+ */
+static int read_fifo(struct net2280_ep *ep, struct net2280_request *req)
+{
+	struct net2280_ep_regs	__iomem *regs = ep->regs;
+	u8			*buf = req->req.buf + req->req.actual;
+	unsigned		count, tmp, is_short;
+	unsigned		cleanup = 0, prevent = 0;
+
+	/* erratum 0106 ... packets coming in during fifo reads might
+	 * be incompletely rejected.  not all cases have workarounds.
+	 */
+	if (ep->dev->chiprev == 0x0100 &&
+			ep->dev->gadget.speed == USB_SPEED_FULL) {
+		udelay(1);
+		tmp = readl(&ep->regs->ep_stat);
+		if ((tmp & BIT(NAK_OUT_PACKETS)))
+			cleanup = 1;
+		else if ((tmp & BIT(FIFO_FULL))) {
+			start_out_naking(ep);
+			prevent = 1;
+		}
+		/* else: hope we don't see the problem */
+	}
+
+	/* never overflow the rx buffer. the fifo reads packets until
+	 * it sees a short one; we might not be ready for them all.
+	 */
+	prefetchw(buf);
+	count = readl(&regs->ep_avail);
+	if (unlikely(count == 0)) {
+		udelay(1);
+		tmp = readl(&ep->regs->ep_stat);
+		count = readl(&regs->ep_avail);
+		/* handled that data already? */
+		if (count == 0 && (tmp & BIT(NAK_OUT_PACKETS)) == 0)
+			return 0;
+	}
+
+	tmp = req->req.length - req->req.actual;
+	if (count > tmp) {
+		/* as with DMA, data overflow gets flushed */
+		if ((tmp % ep->ep.maxpacket) != 0) {
+			ep_err(ep->dev,
+				"%s out fifo %d bytes, expected %d\n",
+				ep->ep.name, count, tmp);
+			req->req.status = -EOVERFLOW;
+			cleanup = 1;
+			/* NAK_OUT_PACKETS will be set, so flushing is safe;
+			 * the next read will start with the next packet
+			 */
+		} /* else it's a ZLP, no worries */
+		count = tmp;
+	}
+	req->req.actual += count;
+
+	is_short = (count == 0) || ((count % ep->ep.maxpacket) != 0);
+
+	ep_vdbg(ep->dev, "read %s fifo (OUT) %d bytes%s%s%s req %p %d/%d\n",
+			ep->ep.name, count, is_short ? " (short)" : "",
+			cleanup ? " flush" : "", prevent ? " nak" : "",
+			req, req->req.actual, req->req.length);
+
+	while (count >= 4) {
+		tmp = readl(&regs->ep_data);
+		cpu_to_le32s(&tmp);
+		put_unaligned(tmp, (u32 *)buf);
+		buf += 4;
+		count -= 4;
+	}
+	if (count) {
+		tmp = readl(&regs->ep_data);
+		/* LE conversion is implicit here: */
+		do {
+			*buf++ = (u8) tmp;
+			tmp >>= 8;
+		} while (--count);
+	}
+	if (cleanup)
+		out_flush(ep);
+	if (prevent) {
+		writel(BIT(CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
+		(void) readl(&ep->regs->ep_rsp);
+	}
+
+	return is_short || ((req->req.actual == req->req.length) &&
+			!req->req.zero);
+}
+
+/* fill out dma descriptor to match a given request */
+static void fill_dma_desc(struct net2280_ep *ep,
+					struct net2280_request *req, int valid)
+{
+	struct net2280_dma	*td = req->td;
+	u32			dmacount = req->req.length;
+
+	/* don't let DMA continue after a short OUT packet,
+	 * so overruns can't affect the next transfer.
+	 * in case of overruns on max-size packets, we can't
+	 * stop the fifo from filling but we can flush it.
+	 */
+	if (ep->is_in)
+		dmacount |= BIT(DMA_DIRECTION);
+	if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) ||
+					!(ep->dev->quirks & PLX_2280))
+		dmacount |= BIT(END_OF_CHAIN);
+
+	req->valid = valid;
+	if (valid)
+		dmacount |= BIT(VALID_BIT);
+	if (likely(!req->req.no_interrupt || !use_dma_chaining))
+		dmacount |= BIT(DMA_DONE_INTERRUPT_ENABLE);
+
+	/* td->dmadesc = previously set by caller */
+	td->dmaaddr = cpu_to_le32 (req->req.dma);
+
+	/* 2280 may be polling VALID_BIT through ep->dma->dmadesc */
+	wmb();
+	td->dmacount = cpu_to_le32(dmacount);
+}
+
+static const u32 dmactl_default =
+		BIT(DMA_SCATTER_GATHER_DONE_INTERRUPT) |
+		BIT(DMA_CLEAR_COUNT_ENABLE) |
+		/* erratum 0116 workaround part 1 (use POLLING) */
+		(POLL_100_USEC << DESCRIPTOR_POLLING_RATE) |
+		BIT(DMA_VALID_BIT_POLLING_ENABLE) |
+		BIT(DMA_VALID_BIT_ENABLE) |
+		BIT(DMA_SCATTER_GATHER_ENABLE) |
+		/* erratum 0116 workaround part 2 (no AUTOSTART) */
+		BIT(DMA_ENABLE);
+
+static inline void spin_stop_dma(struct net2280_dma_regs __iomem *dma)
+{
+	handshake(&dma->dmactl, BIT(DMA_ENABLE), 0, 50);
+}
+
+static inline void stop_dma(struct net2280_dma_regs __iomem *dma)
+{
+	writel(readl(&dma->dmactl) & ~BIT(DMA_ENABLE), &dma->dmactl);
+	spin_stop_dma(dma);
+}
+
+static void start_queue(struct net2280_ep *ep, u32 dmactl, u32 td_dma)
+{
+	struct net2280_dma_regs	__iomem *dma = ep->dma;
+	unsigned int tmp = BIT(VALID_BIT) | (ep->is_in << DMA_DIRECTION);
+
+	if (!(ep->dev->quirks & PLX_2280))
+		tmp |= BIT(END_OF_CHAIN);
+
+	writel(tmp, &dma->dmacount);
+	writel(readl(&dma->dmastat), &dma->dmastat);
+
+	writel(td_dma, &dma->dmadesc);
+	if (ep->dev->quirks & PLX_SUPERSPEED)
+		dmactl |= BIT(DMA_REQUEST_OUTSTANDING);
+	writel(dmactl, &dma->dmactl);
+
+	/* erratum 0116 workaround part 3:  pci arbiter away from net2280 */
+	(void) readl(&ep->dev->pci->pcimstctl);
+
+	writel(BIT(DMA_START), &dma->dmastat);
+
+	if (!ep->is_in)
+		stop_out_naking(ep);
+}
+
+static void start_dma(struct net2280_ep *ep, struct net2280_request *req)
+{
+	u32			tmp;
+	struct net2280_dma_regs	__iomem *dma = ep->dma;
+
+	/* FIXME can't use DMA for ZLPs */
+
+	/* on this path we "know" there's no dma active (yet) */
+	WARN_ON(readl(&dma->dmactl) & BIT(DMA_ENABLE));
+	writel(0, &ep->dma->dmactl);
+
+	/* previous OUT packet might have been short */
+	if (!ep->is_in && (readl(&ep->regs->ep_stat) &
+				BIT(NAK_OUT_PACKETS))) {
+		writel(BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT),
+			&ep->regs->ep_stat);
+
+		tmp = readl(&ep->regs->ep_avail);
+		if (tmp) {
+			writel(readl(&dma->dmastat), &dma->dmastat);
+
+			/* transfer all/some fifo data */
+			writel(req->req.dma, &dma->dmaaddr);
+			tmp = min(tmp, req->req.length);
+
+			/* dma irq, faking scatterlist status */
+			req->td->dmacount = cpu_to_le32(req->req.length - tmp);
+			writel(BIT(DMA_DONE_INTERRUPT_ENABLE) | tmp,
+					&dma->dmacount);
+			req->td->dmadesc = 0;
+			req->valid = 1;
+
+			writel(BIT(DMA_ENABLE), &dma->dmactl);
+			writel(BIT(DMA_START), &dma->dmastat);
+			return;
+		}
+	}
+
+	tmp = dmactl_default;
+
+	/* force packet boundaries between dma requests, but prevent the
+	 * controller from automagically writing a last "short" packet
+	 * (zero length) unless the driver explicitly said to do that.
+	 */
+	if (ep->is_in) {
+		if (likely((req->req.length % ep->ep.maxpacket) ||
+							req->req.zero)){
+			tmp |= BIT(DMA_FIFO_VALIDATE);
+			ep->in_fifo_validate = 1;
+		} else
+			ep->in_fifo_validate = 0;
+	}
+
+	/* init req->td, pointing to the current dummy */
+	req->td->dmadesc = cpu_to_le32 (ep->td_dma);
+	fill_dma_desc(ep, req, 1);
+
+	if (!use_dma_chaining)
+		req->td->dmacount |= cpu_to_le32(BIT(END_OF_CHAIN));
+
+	start_queue(ep, tmp, req->td_dma);
+}
+
+static inline void resume_dma(struct net2280_ep *ep)
+{
+	writel(readl(&ep->dma->dmactl) | BIT(DMA_ENABLE), &ep->dma->dmactl);
+
+	ep->dma_started = true;
+}
+
+static inline void ep_stop_dma(struct net2280_ep *ep)
+{
+	writel(readl(&ep->dma->dmactl) & ~BIT(DMA_ENABLE), &ep->dma->dmactl);
+	spin_stop_dma(ep->dma);
+
+	ep->dma_started = false;
+}
+
+static inline void
+queue_dma(struct net2280_ep *ep, struct net2280_request *req, int valid)
+{
+	struct net2280_dma	*end;
+	dma_addr_t		tmp;
+
+	/* swap new dummy for old, link; fill and maybe activate */
+	end = ep->dummy;
+	ep->dummy = req->td;
+	req->td = end;
+
+	tmp = ep->td_dma;
+	ep->td_dma = req->td_dma;
+	req->td_dma = tmp;
+
+	end->dmadesc = cpu_to_le32 (ep->td_dma);
+
+	fill_dma_desc(ep, req, valid);
+}
+
+static void
+done(struct net2280_ep *ep, struct net2280_request *req, int status)
+{
+	struct net2280		*dev;
+	unsigned		stopped = ep->stopped;
+
+	list_del_init(&req->queue);
+
+	if (req->req.status == -EINPROGRESS)
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	dev = ep->dev;
+	if (ep->dma)
+		usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
+
+	if (status && status != -ESHUTDOWN)
+		ep_vdbg(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;
+	spin_unlock(&dev->lock);
+	req->req.complete(&ep->ep, &req->req);
+	spin_lock(&dev->lock);
+	ep->stopped = stopped;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+net2280_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+	struct net2280_request	*req;
+	struct net2280_ep	*ep;
+	struct net2280		*dev;
+	unsigned long		flags;
+
+	/* we always require a cpu-view buffer, so that we can
+	 * always use pio (as fallback or whatever).
+	 */
+	req = container_of(_req, struct net2280_request, req);
+	if (!_req || !_req->complete || !_req->buf ||
+				!list_empty(&req->queue))
+		return -EINVAL;
+	if (_req->length > (~0 & DMA_BYTE_COUNT_MASK))
+		return -EDOM;
+	ep = container_of(_ep, struct net2280_ep, ep);
+	if (!_ep || (!ep->desc && ep->num != 0))
+		return -EINVAL;
+	dev = ep->dev;
+	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	/* FIXME implement PIO fallback for ZLPs with DMA */
+	if (ep->dma && _req->length == 0)
+		return -EOPNOTSUPP;
+
+	/* set up dma mapping in case the caller didn't */
+	if (ep->dma) {
+		int ret;
+
+		ret = usb_gadget_map_request(&dev->gadget, _req,
+				ep->is_in);
+		if (ret)
+			return ret;
+	}
+
+#if 0
+	ep_vdbg(dev, "%s queue req %p, len %d buf %p\n",
+			_ep->name, _req, _req->length, _req->buf);
+#endif
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	_req->status = -EINPROGRESS;
+	_req->actual = 0;
+
+	/* kickstart this i/o queue? */
+	if (list_empty(&ep->queue) && !ep->stopped) {
+		/* DMA request while EP halted */
+		if (ep->dma &&
+		    (readl(&ep->regs->ep_rsp) & BIT(CLEAR_ENDPOINT_HALT)) &&
+			(dev->quirks & PLX_SUPERSPEED)) {
+			int valid = 1;
+			if (ep->is_in) {
+				int expect;
+				expect = likely(req->req.zero ||
+						((req->req.length %
+						  ep->ep.maxpacket) != 0));
+				if (expect != ep->in_fifo_validate)
+					valid = 0;
+			}
+			queue_dma(ep, req, valid);
+		}
+		/* use DMA if the endpoint supports it, else pio */
+		else if (ep->dma)
+			start_dma(ep, req);
+		else {
+			/* maybe there's no control data, just status ack */
+			if (ep->num == 0 && _req->length == 0) {
+				allow_status(ep);
+				done(ep, req, 0);
+				ep_vdbg(dev, "%s status ack\n", ep->ep.name);
+				goto done;
+			}
+
+			/* PIO ... stuff the fifo, or unblock it.  */
+			if (ep->is_in)
+				write_fifo(ep, _req);
+			else if (list_empty(&ep->queue)) {
+				u32	s;
+
+				/* OUT FIFO might have packet(s) buffered */
+				s = readl(&ep->regs->ep_stat);
+				if ((s & BIT(FIFO_EMPTY)) == 0) {
+					/* note:  _req->short_not_ok is
+					 * ignored here since PIO _always_
+					 * stops queue advance here, and
+					 * _req->status doesn't change for
+					 * short reads (only _req->actual)
+					 */
+					if (read_fifo(ep, req) &&
+							ep->num == 0) {
+						done(ep, req, 0);
+						allow_status(ep);
+						/* don't queue it */
+						req = NULL;
+					} else if (read_fifo(ep, req) &&
+							ep->num != 0) {
+						done(ep, req, 0);
+						req = NULL;
+					} else
+						s = readl(&ep->regs->ep_stat);
+				}
+
+				/* don't NAK, let the fifo fill */
+				if (req && (s & BIT(NAK_OUT_PACKETS)))
+					writel(BIT(CLEAR_NAK_OUT_PACKETS),
+							&ep->regs->ep_rsp);
+			}
+		}
+
+	} else if (ep->dma) {
+		int	valid = 1;
+
+		if (ep->is_in) {
+			int	expect;
+
+			/* preventing magic zlps is per-engine state, not
+			 * per-transfer; irq logic must recover hiccups.
+			 */
+			expect = likely(req->req.zero ||
+				(req->req.length % ep->ep.maxpacket));
+			if (expect != ep->in_fifo_validate)
+				valid = 0;
+		}
+		queue_dma(ep, req, valid);
+
+	} /* else the irq handler advances the queue. */
+
+	ep->responded = 1;
+	if (req)
+		list_add_tail(&req->queue, &ep->queue);
+done:
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	/* pci writes may still be posted */
+	return 0;
+}
+
+static inline void
+dma_done(struct net2280_ep *ep,	struct net2280_request *req, u32 dmacount,
+		int status)
+{
+	req->req.actual = req->req.length - (DMA_BYTE_COUNT_MASK & dmacount);
+	done(ep, req, status);
+}
+
+static void restart_dma(struct net2280_ep *ep);
+
+static void scan_dma_completions(struct net2280_ep *ep)
+{
+	/* only look at descriptors that were "naturally" retired,
+	 * so fifo and list head state won't matter
+	 */
+	while (!list_empty(&ep->queue)) {
+		struct net2280_request	*req;
+		u32			tmp;
+
+		req = list_entry(ep->queue.next,
+				struct net2280_request, queue);
+		if (!req->valid)
+			break;
+		rmb();
+		tmp = le32_to_cpup(&req->td->dmacount);
+		if ((tmp & BIT(VALID_BIT)) != 0)
+			break;
+
+		/* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short"
+		 * cases where DMA must be aborted; this code handles
+		 * all non-abort DMA completions.
+		 */
+		if (unlikely(req->td->dmadesc == 0)) {
+			/* paranoia */
+			tmp = readl(&ep->dma->dmacount);
+			if (tmp & DMA_BYTE_COUNT_MASK)
+				break;
+			/* single transfer mode */
+			dma_done(ep, req, tmp, 0);
+			break;
+		} else if (!ep->is_in &&
+				(req->req.length % ep->ep.maxpacket) != 0) {
+			tmp = readl(&ep->regs->ep_stat);
+			if (ep->dev->quirks & PLX_SUPERSPEED)
+				return dma_done(ep, req, tmp, 0);
+
+			/* AVOID TROUBLE HERE by not issuing short reads from
+			 * your gadget driver.  That helps avoids errata 0121,
+			 * 0122, and 0124; not all cases trigger the warning.
+			 */
+			if ((tmp & BIT(NAK_OUT_PACKETS)) == 0) {
+				ep_warn(ep->dev, "%s lost packet sync!\n",
+						ep->ep.name);
+				req->req.status = -EOVERFLOW;
+			} else {
+				tmp = readl(&ep->regs->ep_avail);
+				if (tmp) {
+					/* fifo gets flushed later */
+					ep->out_overflow = 1;
+					ep_dbg(ep->dev,
+						"%s dma, discard %d len %d\n",
+						ep->ep.name, tmp,
+						req->req.length);
+					req->req.status = -EOVERFLOW;
+				}
+			}
+		}
+		dma_done(ep, req, tmp, 0);
+	}
+}
+
+static void restart_dma(struct net2280_ep *ep)
+{
+	struct net2280_request	*req;
+	u32			dmactl = dmactl_default;
+
+	if (ep->stopped)
+		return;
+	req = list_entry(ep->queue.next, struct net2280_request, queue);
+
+	if (!use_dma_chaining) {
+		start_dma(ep, req);
+		return;
+	}
+
+	/* the 2280 will be processing the queue unless queue hiccups after
+	 * the previous transfer:
+	 *  IN:   wanted automagic zlp, head doesn't (or vice versa)
+	 *        DMA_FIFO_VALIDATE doesn't init from dma descriptors.
+	 *  OUT:  was "usb-short", we must restart.
+	 */
+	if (ep->is_in && !req->valid) {
+		struct net2280_request	*entry, *prev = NULL;
+		int			reqmode, done = 0;
+
+		ep_dbg(ep->dev, "%s dma hiccup td %p\n", ep->ep.name, req->td);
+		ep->in_fifo_validate = likely(req->req.zero ||
+				(req->req.length % ep->ep.maxpacket) != 0);
+		if (ep->in_fifo_validate)
+			dmactl |= BIT(DMA_FIFO_VALIDATE);
+		list_for_each_entry(entry, &ep->queue, queue) {
+			__le32		dmacount;
+
+			if (entry == req)
+				continue;
+			dmacount = entry->td->dmacount;
+			if (!done) {
+				reqmode = likely(entry->req.zero ||
+				   (entry->req.length % ep->ep.maxpacket));
+				if (reqmode == ep->in_fifo_validate) {
+					entry->valid = 1;
+					dmacount |= valid_bit;
+					entry->td->dmacount = dmacount;
+					prev = entry;
+					continue;
+				} else {
+					/* force a hiccup */
+					prev->td->dmacount |= dma_done_ie;
+					done = 1;
+				}
+			}
+
+			/* walk the rest of the queue so unlinks behave */
+			entry->valid = 0;
+			dmacount &= ~valid_bit;
+			entry->td->dmacount = dmacount;
+			prev = entry;
+		}
+	}
+
+	writel(0, &ep->dma->dmactl);
+	start_queue(ep, dmactl, req->td_dma);
+}
+
+static void abort_dma_228x(struct net2280_ep *ep)
+{
+	/* abort the current transfer */
+	if (likely(!list_empty(&ep->queue))) {
+		/* FIXME work around errata 0121, 0122, 0124 */
+		writel(BIT(DMA_ABORT), &ep->dma->dmastat);
+		spin_stop_dma(ep->dma);
+	} else
+		stop_dma(ep->dma);
+	scan_dma_completions(ep);
+}
+
+static void abort_dma_338x(struct net2280_ep *ep)
+{
+	writel(BIT(DMA_ABORT), &ep->dma->dmastat);
+	spin_stop_dma(ep->dma);
+}
+
+static void abort_dma(struct net2280_ep *ep)
+{
+	if (ep->dev->quirks & PLX_LEGACY)
+		return abort_dma_228x(ep);
+	return abort_dma_338x(ep);
+}
+
+/* dequeue ALL requests */
+static void nuke(struct net2280_ep *ep)
+{
+	struct net2280_request	*req;
+
+	/* called with spinlock held */
+	ep->stopped = 1;
+	if (ep->dma)
+		abort_dma(ep);
+	while (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next,
+				struct net2280_request,
+				queue);
+		done(ep, req, -ESHUTDOWN);
+	}
+}
+
+/* dequeue JUST ONE request */
+static int net2280_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct net2280_ep	*ep;
+	struct net2280_request	*req;
+	unsigned long		flags;
+	u32			dmactl;
+	int			stopped;
+
+	ep = container_of(_ep, struct net2280_ep, ep);
+	if (!_ep || (!ep->desc && ep->num != 0) || !_req)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ep->dev->lock, flags);
+	stopped = ep->stopped;
+
+	/* quiesce dma while we patch the queue */
+	dmactl = 0;
+	ep->stopped = 1;
+	if (ep->dma) {
+		dmactl = readl(&ep->dma->dmactl);
+		/* WARNING erratum 0127 may kick in ... */
+		stop_dma(ep->dma);
+		scan_dma_completions(ep);
+	}
+
+	/* make sure it's still queued on this endpoint */
+	list_for_each_entry(req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+	if (&req->req != _req) {
+		spin_unlock_irqrestore(&ep->dev->lock, flags);
+		return -EINVAL;
+	}
+
+	/* queue head may be partially complete. */
+	if (ep->queue.next == &req->queue) {
+		if (ep->dma) {
+			ep_dbg(ep->dev, "unlink (%s) dma\n", _ep->name);
+			_req->status = -ECONNRESET;
+			abort_dma(ep);
+			if (likely(ep->queue.next == &req->queue)) {
+				/* NOTE: misreports single-transfer mode*/
+				req->td->dmacount = 0;	/* invalidate */
+				dma_done(ep, req,
+					readl(&ep->dma->dmacount),
+					-ECONNRESET);
+			}
+		} else {
+			ep_dbg(ep->dev, "unlink (%s) pio\n", _ep->name);
+			done(ep, req, -ECONNRESET);
+		}
+		req = NULL;
+
+	/* patch up hardware chaining data */
+	} else if (ep->dma && use_dma_chaining) {
+		if (req->queue.prev == ep->queue.next) {
+			writel(le32_to_cpu(req->td->dmadesc),
+				&ep->dma->dmadesc);
+			if (req->td->dmacount & dma_done_ie)
+				writel(readl(&ep->dma->dmacount) |
+						le32_to_cpu(dma_done_ie),
+					&ep->dma->dmacount);
+		} else {
+			struct net2280_request	*prev;
+
+			prev = list_entry(req->queue.prev,
+				struct net2280_request, queue);
+			prev->td->dmadesc = req->td->dmadesc;
+			if (req->td->dmacount & dma_done_ie)
+				prev->td->dmacount |= dma_done_ie;
+		}
+	}
+
+	if (req)
+		done(ep, req, -ECONNRESET);
+	ep->stopped = stopped;
+
+	if (ep->dma) {
+		/* turn off dma on inactive queues */
+		if (list_empty(&ep->queue))
+			stop_dma(ep->dma);
+		else if (!ep->stopped) {
+			/* resume current request, or start new one */
+			if (req)
+				writel(dmactl, &ep->dma->dmactl);
+			else
+				start_dma(ep, list_entry(ep->queue.next,
+					struct net2280_request, queue));
+		}
+	}
+
+	spin_unlock_irqrestore(&ep->dev->lock, flags);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int net2280_fifo_status(struct usb_ep *_ep);
+
+static int
+net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
+{
+	struct net2280_ep	*ep;
+	unsigned long		flags;
+	int			retval = 0;
+
+	ep = container_of(_ep, struct net2280_ep, ep);
+	if (!_ep || (!ep->desc && ep->num != 0))
+		return -EINVAL;
+	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+	if (ep->desc /* not ep0 */ && (ep->desc->bmAttributes & 0x03)
+						== USB_ENDPOINT_XFER_ISOC)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ep->dev->lock, flags);
+	if (!list_empty(&ep->queue))
+		retval = -EAGAIN;
+	else if (ep->is_in && value && net2280_fifo_status(_ep) != 0)
+		retval = -EAGAIN;
+	else {
+		ep_vdbg(ep->dev, "%s %s %s\n", _ep->name,
+				value ? "set" : "clear",
+				wedged ? "wedge" : "halt");
+		/* set/clear, then synch memory views with the device */
+		if (value) {
+			if (ep->num == 0)
+				ep->dev->protocol_stall = 1;
+			else
+				set_halt(ep);
+			if (wedged)
+				ep->wedged = 1;
+		} else {
+			clear_halt(ep);
+			if (ep->dev->quirks & PLX_SUPERSPEED &&
+				!list_empty(&ep->queue) && ep->td_dma)
+					restart_dma(ep);
+			ep->wedged = 0;
+		}
+		(void) readl(&ep->regs->ep_rsp);
+	}
+	spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+	return retval;
+}
+
+static int net2280_set_halt(struct usb_ep *_ep, int value)
+{
+	return net2280_set_halt_and_wedge(_ep, value, 0);
+}
+
+static int net2280_set_wedge(struct usb_ep *_ep)
+{
+	if (!_ep || _ep->name == ep0name)
+		return -EINVAL;
+	return net2280_set_halt_and_wedge(_ep, 1, 1);
+}
+
+static int net2280_fifo_status(struct usb_ep *_ep)
+{
+	struct net2280_ep	*ep;
+	u32			avail;
+
+	ep = container_of(_ep, struct net2280_ep, ep);
+	if (!_ep || (!ep->desc && ep->num != 0))
+		return -ENODEV;
+	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	avail = readl(&ep->regs->ep_avail) & (BIT(12) - 1);
+	if (avail > ep->fifo_size)
+		return -EOVERFLOW;
+	if (ep->is_in)
+		avail = ep->fifo_size - avail;
+	return avail;
+}
+
+static void net2280_fifo_flush(struct usb_ep *_ep)
+{
+	struct net2280_ep	*ep;
+
+	ep = container_of(_ep, struct net2280_ep, ep);
+	if (!_ep || (!ep->desc && ep->num != 0))
+		return;
+	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return;
+
+	writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat);
+	(void) readl(&ep->regs->ep_rsp);
+}
+
+static const struct usb_ep_ops net2280_ep_ops = {
+	.enable		= net2280_enable,
+	.disable	= net2280_disable,
+
+	.alloc_request	= net2280_alloc_request,
+	.free_request	= net2280_free_request,
+
+	.queue		= net2280_queue,
+	.dequeue	= net2280_dequeue,
+
+	.set_halt	= net2280_set_halt,
+	.set_wedge	= net2280_set_wedge,
+	.fifo_status	= net2280_fifo_status,
+	.fifo_flush	= net2280_fifo_flush,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int net2280_get_frame(struct usb_gadget *_gadget)
+{
+	struct net2280		*dev;
+	unsigned long		flags;
+	u16			retval;
+
+	if (!_gadget)
+		return -ENODEV;
+	dev = container_of(_gadget, struct net2280, gadget);
+	spin_lock_irqsave(&dev->lock, flags);
+	retval = get_idx_reg(dev->regs, REG_FRAME) & 0x03ff;
+	spin_unlock_irqrestore(&dev->lock, flags);
+	return retval;
+}
+
+static int net2280_wakeup(struct usb_gadget *_gadget)
+{
+	struct net2280		*dev;
+	u32			tmp;
+	unsigned long		flags;
+
+	if (!_gadget)
+		return 0;
+	dev = container_of(_gadget, struct net2280, gadget);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	tmp = readl(&dev->usb->usbctl);
+	if (tmp & BIT(DEVICE_REMOTE_WAKEUP_ENABLE))
+		writel(BIT(GENERATE_RESUME), &dev->usb->usbstat);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	/* pci writes may still be posted */
+	return 0;
+}
+
+static int net2280_set_selfpowered(struct usb_gadget *_gadget, int value)
+{
+	struct net2280		*dev;
+	u32			tmp;
+	unsigned long		flags;
+
+	if (!_gadget)
+		return 0;
+	dev = container_of(_gadget, struct net2280, gadget);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	tmp = readl(&dev->usb->usbctl);
+	if (value) {
+		tmp |= BIT(SELF_POWERED_STATUS);
+		dev->selfpowered = 1;
+	} else {
+		tmp &= ~BIT(SELF_POWERED_STATUS);
+		dev->selfpowered = 0;
+	}
+	writel(tmp, &dev->usb->usbctl);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
+{
+	struct net2280  *dev;
+	u32             tmp;
+	unsigned long   flags;
+
+	if (!_gadget)
+		return -ENODEV;
+	dev = container_of(_gadget, struct net2280, gadget);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	tmp = readl(&dev->usb->usbctl);
+	dev->softconnect = (is_on != 0);
+	if (is_on)
+		tmp |= BIT(USB_DETECT_ENABLE);
+	else
+		tmp &= ~BIT(USB_DETECT_ENABLE);
+	writel(tmp, &dev->usb->usbctl);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+static int net2280_start(struct usb_gadget *_gadget,
+		struct usb_gadget_driver *driver);
+static int net2280_stop(struct usb_gadget *_gadget,
+		struct usb_gadget_driver *driver);
+
+static const struct usb_gadget_ops net2280_ops = {
+	.get_frame	= net2280_get_frame,
+	.wakeup		= net2280_wakeup,
+	.set_selfpowered = net2280_set_selfpowered,
+	.pullup		= net2280_pullup,
+	.udc_start	= net2280_start,
+	.udc_stop	= net2280_stop,
+};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_USB_GADGET_DEBUG_FILES
+
+/* FIXME move these into procfs, and use seq_file.
+ * Sysfs _still_ doesn't behave for arbitrarily sized files,
+ * and also doesn't help products using this with 2.4 kernels.
+ */
+
+/* "function" sysfs attribute */
+static ssize_t function_show(struct device *_dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct net2280	*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_RO(function);
+
+static ssize_t registers_show(struct device *_dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct net2280		*dev;
+	char			*next;
+	unsigned		size, t;
+	unsigned long		flags;
+	int			i;
+	u32			t1, t2;
+	const char		*s;
+
+	dev = dev_get_drvdata(_dev);
+	next = buf;
+	size = PAGE_SIZE;
+	spin_lock_irqsave(&dev->lock, flags);
+
+	if (dev->driver)
+		s = dev->driver->driver.name;
+	else
+		s = "(none)";
+
+	/* Main Control Registers */
+	t = scnprintf(next, size, "%s version " DRIVER_VERSION
+			", chiprev %04x, dma %s\n\n"
+			"devinit %03x fifoctl %08x gadget '%s'\n"
+			"pci irqenb0 %02x irqenb1 %08x "
+			"irqstat0 %04x irqstat1 %08x\n",
+			driver_name, dev->chiprev,
+			use_dma
+				? (use_dma_chaining ? "chaining" : "enabled")
+				: "disabled",
+			readl(&dev->regs->devinit),
+			readl(&dev->regs->fifoctl),
+			s,
+			readl(&dev->regs->pciirqenb0),
+			readl(&dev->regs->pciirqenb1),
+			readl(&dev->regs->irqstat0),
+			readl(&dev->regs->irqstat1));
+	size -= t;
+	next += t;
+
+	/* USB Control Registers */
+	t1 = readl(&dev->usb->usbctl);
+	t2 = readl(&dev->usb->usbstat);
+	if (t1 & BIT(VBUS_PIN)) {
+		if (t2 & BIT(HIGH_SPEED))
+			s = "high speed";
+		else if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+			s = "powered";
+		else
+			s = "full speed";
+		/* full speed bit (6) not working?? */
+	} else
+			s = "not attached";
+	t = scnprintf(next, size,
+			"stdrsp %08x usbctl %08x usbstat %08x "
+				"addr 0x%02x (%s)\n",
+			readl(&dev->usb->stdrsp), t1, t2,
+			readl(&dev->usb->ouraddr), s);
+	size -= t;
+	next += t;
+
+	/* PCI Master Control Registers */
+
+	/* DMA Control Registers */
+
+	/* Configurable EP Control Registers */
+	for (i = 0; i < dev->n_ep; i++) {
+		struct net2280_ep	*ep;
+
+		ep = &dev->ep[i];
+		if (i && !ep->desc)
+			continue;
+
+		t1 = readl(&ep->cfg->ep_cfg);
+		t2 = readl(&ep->regs->ep_rsp) & 0xff;
+		t = scnprintf(next, size,
+				"\n%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s"
+					"irqenb %02x\n",
+				ep->ep.name, t1, t2,
+				(t2 & BIT(CLEAR_NAK_OUT_PACKETS))
+					? "NAK " : "",
+				(t2 & BIT(CLEAR_EP_HIDE_STATUS_PHASE))
+					? "hide " : "",
+				(t2 & BIT(CLEAR_EP_FORCE_CRC_ERROR))
+					? "CRC " : "",
+				(t2 & BIT(CLEAR_INTERRUPT_MODE))
+					? "interrupt " : "",
+				(t2 & BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE))
+					? "status " : "",
+				(t2 & BIT(CLEAR_NAK_OUT_PACKETS_MODE))
+					? "NAKmode " : "",
+				(t2 & BIT(CLEAR_ENDPOINT_TOGGLE))
+					? "DATA1 " : "DATA0 ",
+				(t2 & BIT(CLEAR_ENDPOINT_HALT))
+					? "HALT " : "",
+				readl(&ep->regs->ep_irqenb));
+		size -= t;
+		next += t;
+
+		t = scnprintf(next, size,
+				"\tstat %08x avail %04x "
+				"(ep%d%s-%s)%s\n",
+				readl(&ep->regs->ep_stat),
+				readl(&ep->regs->ep_avail),
+				t1 & 0x0f, DIR_STRING(t1),
+				type_string(t1 >> 8),
+				ep->stopped ? "*" : "");
+		size -= t;
+		next += t;
+
+		if (!ep->dma)
+			continue;
+
+		t = scnprintf(next, size,
+				"  dma\tctl %08x stat %08x count %08x\n"
+				"\taddr %08x desc %08x\n",
+				readl(&ep->dma->dmactl),
+				readl(&ep->dma->dmastat),
+				readl(&ep->dma->dmacount),
+				readl(&ep->dma->dmaaddr),
+				readl(&ep->dma->dmadesc));
+		size -= t;
+		next += t;
+
+	}
+
+	/* Indexed Registers (none yet) */
+
+	/* Statistics */
+	t = scnprintf(next, size, "\nirqs:  ");
+	size -= t;
+	next += t;
+	for (i = 0; i < dev->n_ep; i++) {
+		struct net2280_ep	*ep;
+
+		ep = &dev->ep[i];
+		if (i && !ep->irqs)
+			continue;
+		t = scnprintf(next, size, " %s/%lu", ep->ep.name, ep->irqs);
+		size -= t;
+		next += t;
+
+	}
+	t = scnprintf(next, size, "\n");
+	size -= t;
+	next += t;
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return PAGE_SIZE - size;
+}
+static DEVICE_ATTR_RO(registers);
+
+static ssize_t queues_show(struct device *_dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct net2280		*dev;
+	char			*next;
+	unsigned		size;
+	unsigned long		flags;
+	int			i;
+
+	dev = dev_get_drvdata(_dev);
+	next = buf;
+	size = PAGE_SIZE;
+	spin_lock_irqsave(&dev->lock, flags);
+
+	for (i = 0; i < dev->n_ep; i++) {
+		struct net2280_ep		*ep = &dev->ep[i];
+		struct net2280_request		*req;
+		int				t;
+
+		if (i != 0) {
+			const struct usb_endpoint_descriptor	*d;
+
+			d = ep->desc;
+			if (!d)
+				continue;
+			t = d->bEndpointAddress;
+			t = scnprintf(next, size,
+				"\n%s (ep%d%s-%s) max %04x %s fifo %d\n",
+				ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK,
+				(t & USB_DIR_IN) ? "in" : "out",
+				type_string(d->bmAttributes),
+				usb_endpoint_maxp(d) & 0x1fff,
+				ep->dma ? "dma" : "pio", ep->fifo_size
+				);
+		} else /* ep0 should only have one transfer queued */
+			t = scnprintf(next, size, "ep0 max 64 pio %s\n",
+					ep->is_in ? "in" : "out");
+		if (t <= 0 || t > size)
+			goto done;
+		size -= t;
+		next += t;
+
+		if (list_empty(&ep->queue)) {
+			t = scnprintf(next, size, "\t(nothing queued)\n");
+			if (t <= 0 || t > size)
+				goto done;
+			size -= t;
+			next += t;
+			continue;
+		}
+		list_for_each_entry(req, &ep->queue, queue) {
+			if (ep->dma && req->td_dma == readl(&ep->dma->dmadesc))
+				t = scnprintf(next, size,
+					"\treq %p len %d/%d "
+					"buf %p (dmacount %08x)\n",
+					&req->req, req->req.actual,
+					req->req.length, req->req.buf,
+					readl(&ep->dma->dmacount));
+			else
+				t = scnprintf(next, size,
+					"\treq %p len %d/%d buf %p\n",
+					&req->req, req->req.actual,
+					req->req.length, req->req.buf);
+			if (t <= 0 || t > size)
+				goto done;
+			size -= t;
+			next += t;
+
+			if (ep->dma) {
+				struct net2280_dma	*td;
+
+				td = req->td;
+				t = scnprintf(next, size, "\t    td %08x "
+					" count %08x buf %08x desc %08x\n",
+					(u32) req->td_dma,
+					le32_to_cpu(td->dmacount),
+					le32_to_cpu(td->dmaaddr),
+					le32_to_cpu(td->dmadesc));
+				if (t <= 0 || t > size)
+					goto done;
+				size -= t;
+				next += t;
+			}
+		}
+	}
+
+done:
+	spin_unlock_irqrestore(&dev->lock, flags);
+	return PAGE_SIZE - size;
+}
+static DEVICE_ATTR_RO(queues);
+
+
+#else
+
+#define device_create_file(a, b)	(0)
+#define device_remove_file(a, b)	do { } while (0)
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* another driver-specific mode might be a request type doing dma
+ * to/from another device fifo instead of to/from memory.
+ */
+
+static void set_fifo_mode(struct net2280 *dev, int mode)
+{
+	/* keeping high bits preserves BAR2 */
+	writel((0xffff << PCI_BASE2_RANGE) | mode, &dev->regs->fifoctl);
+
+	/* always ep-{a,b,e,f} ... maybe not ep-c or ep-d */
+	INIT_LIST_HEAD(&dev->gadget.ep_list);
+	list_add_tail(&dev->ep[1].ep.ep_list, &dev->gadget.ep_list);
+	list_add_tail(&dev->ep[2].ep.ep_list, &dev->gadget.ep_list);
+	switch (mode) {
+	case 0:
+		list_add_tail(&dev->ep[3].ep.ep_list, &dev->gadget.ep_list);
+		list_add_tail(&dev->ep[4].ep.ep_list, &dev->gadget.ep_list);
+		dev->ep[1].fifo_size = dev->ep[2].fifo_size = 1024;
+		break;
+	case 1:
+		dev->ep[1].fifo_size = dev->ep[2].fifo_size = 2048;
+		break;
+	case 2:
+		list_add_tail(&dev->ep[3].ep.ep_list, &dev->gadget.ep_list);
+		dev->ep[1].fifo_size = 2048;
+		dev->ep[2].fifo_size = 1024;
+		break;
+	}
+	/* fifo sizes for ep0, ep-c, ep-d, ep-e, and ep-f never change */
+	list_add_tail(&dev->ep[5].ep.ep_list, &dev->gadget.ep_list);
+	list_add_tail(&dev->ep[6].ep.ep_list, &dev->gadget.ep_list);
+}
+
+static void defect7374_disable_data_eps(struct net2280 *dev)
+{
+	/*
+	 * For Defect 7374, disable data EPs (and more):
+	 *  - This phase undoes the earlier phase of the Defect 7374 workaround,
+	 *    returing ep regs back to normal.
+	 */
+	struct net2280_ep *ep;
+	int i;
+	unsigned char ep_sel;
+	u32 tmp_reg;
+
+	for (i = 1; i < 5; i++) {
+		ep = &dev->ep[i];
+		writel(0, &ep->cfg->ep_cfg);
+	}
+
+	/* CSROUT, CSRIN, PCIOUT, PCIIN, STATIN, RCIN */
+	for (i = 0; i < 6; i++)
+		writel(0, &dev->dep[i].dep_cfg);
+
+	for (ep_sel = 0; ep_sel <= 21; ep_sel++) {
+		/* Select an endpoint for subsequent operations: */
+		tmp_reg = readl(&dev->plregs->pl_ep_ctrl);
+		writel(((tmp_reg & ~0x1f) | ep_sel), &dev->plregs->pl_ep_ctrl);
+
+		if (ep_sel < 2 || (ep_sel > 9 && ep_sel < 14) ||
+					ep_sel == 18 || ep_sel == 20)
+			continue;
+
+		/* Change settings on some selected endpoints */
+		tmp_reg = readl(&dev->plregs->pl_ep_cfg_4);
+		tmp_reg &= ~BIT(NON_CTRL_IN_TOLERATE_BAD_DIR);
+		writel(tmp_reg, &dev->plregs->pl_ep_cfg_4);
+		tmp_reg = readl(&dev->plregs->pl_ep_ctrl);
+		tmp_reg |= BIT(EP_INITIALIZED);
+		writel(tmp_reg, &dev->plregs->pl_ep_ctrl);
+	}
+}
+
+static void defect7374_enable_data_eps_zero(struct net2280 *dev)
+{
+	u32 tmp = 0, tmp_reg;
+	u32 fsmvalue, scratch;
+	int i;
+	unsigned char ep_sel;
+
+	scratch = get_idx_reg(dev->regs, SCRATCH);
+	fsmvalue = scratch & (0xf << DEFECT7374_FSM_FIELD);
+	scratch &= ~(0xf << DEFECT7374_FSM_FIELD);
+
+	/*See if firmware needs to set up for workaround*/
+	if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ) {
+		ep_warn(dev, "Operate Defect 7374 workaround soft this time");
+		ep_warn(dev, "It will operate on cold-reboot and SS connect");
+
+		/*GPEPs:*/
+		tmp = ((0 << ENDPOINT_NUMBER) | BIT(ENDPOINT_DIRECTION) |
+		       (2 << OUT_ENDPOINT_TYPE) | (2 << IN_ENDPOINT_TYPE) |
+		       ((dev->enhanced_mode) ?
+		       BIT(OUT_ENDPOINT_ENABLE) : BIT(ENDPOINT_ENABLE)) |
+		       BIT(IN_ENDPOINT_ENABLE));
+
+		for (i = 1; i < 5; i++)
+			writel(tmp, &dev->ep[i].cfg->ep_cfg);
+
+		/* CSRIN, PCIIN, STATIN, RCIN*/
+		tmp = ((0 << ENDPOINT_NUMBER) | BIT(ENDPOINT_ENABLE));
+		writel(tmp, &dev->dep[1].dep_cfg);
+		writel(tmp, &dev->dep[3].dep_cfg);
+		writel(tmp, &dev->dep[4].dep_cfg);
+		writel(tmp, &dev->dep[5].dep_cfg);
+
+		/*Implemented for development and debug.
+		 * Can be refined/tuned later.*/
+		for (ep_sel = 0; ep_sel <= 21; ep_sel++) {
+			/* Select an endpoint for subsequent operations: */
+			tmp_reg = readl(&dev->plregs->pl_ep_ctrl);
+			writel(((tmp_reg & ~0x1f) | ep_sel),
+			       &dev->plregs->pl_ep_ctrl);
+
+			if (ep_sel == 1) {
+				tmp =
+				    (readl(&dev->plregs->pl_ep_ctrl) |
+				     BIT(CLEAR_ACK_ERROR_CODE) | 0);
+				writel(tmp, &dev->plregs->pl_ep_ctrl);
+				continue;
+			}
+
+			if (ep_sel == 0 || (ep_sel > 9 && ep_sel < 14) ||
+					ep_sel == 18  || ep_sel == 20)
+				continue;
+
+			tmp = (readl(&dev->plregs->pl_ep_cfg_4) |
+				 BIT(NON_CTRL_IN_TOLERATE_BAD_DIR) | 0);
+			writel(tmp, &dev->plregs->pl_ep_cfg_4);
+
+			tmp = readl(&dev->plregs->pl_ep_ctrl) &
+				~BIT(EP_INITIALIZED);
+			writel(tmp, &dev->plregs->pl_ep_ctrl);
+
+		}
+
+		/* Set FSM to focus on the first Control Read:
+		 * - Tip: Connection speed is known upon the first
+		 * setup request.*/
+		scratch |= DEFECT7374_FSM_WAITING_FOR_CONTROL_READ;
+		set_idx_reg(dev->regs, SCRATCH, scratch);
+
+	} else{
+		ep_warn(dev, "Defect 7374 workaround soft will NOT operate");
+		ep_warn(dev, "It will operate on cold-reboot and SS connect");
+	}
+}
+
+/* keeping it simple:
+ * - one bus driver, initted first;
+ * - one function driver, initted second
+ *
+ * most of the work to support multiple net2280 controllers would
+ * be to associate this gadget driver (yes?) with all of them, or
+ * perhaps to bind specific drivers to specific devices.
+ */
+
+static void usb_reset_228x(struct net2280 *dev)
+{
+	u32	tmp;
+
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+	(void) readl(&dev->usb->usbctl);
+
+	net2280_led_init(dev);
+
+	/* disable automatic responses, and irqs */
+	writel(0, &dev->usb->stdrsp);
+	writel(0, &dev->regs->pciirqenb0);
+	writel(0, &dev->regs->pciirqenb1);
+
+	/* clear old dma and irq state */
+	for (tmp = 0; tmp < 4; tmp++) {
+		struct net2280_ep       *ep = &dev->ep[tmp + 1];
+		if (ep->dma)
+			abort_dma(ep);
+	}
+
+	writel(~0, &dev->regs->irqstat0),
+	writel(~(u32)BIT(SUSPEND_REQUEST_INTERRUPT), &dev->regs->irqstat1),
+
+	/* reset, and enable pci */
+	tmp = readl(&dev->regs->devinit) |
+		BIT(PCI_ENABLE) |
+		BIT(FIFO_SOFT_RESET) |
+		BIT(USB_SOFT_RESET) |
+		BIT(M8051_RESET);
+	writel(tmp, &dev->regs->devinit);
+
+	/* standard fifo and endpoint allocations */
+	set_fifo_mode(dev, (fifo_mode <= 2) ? fifo_mode : 0);
+}
+
+static void usb_reset_338x(struct net2280 *dev)
+{
+	u32 tmp;
+	u32 fsmvalue;
+
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+	(void)readl(&dev->usb->usbctl);
+
+	net2280_led_init(dev);
+
+	fsmvalue = get_idx_reg(dev->regs, SCRATCH) &
+			(0xf << DEFECT7374_FSM_FIELD);
+
+	/* See if firmware needs to set up for workaround: */
+	if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ) {
+		ep_info(dev, "%s: Defect 7374 FsmValue 0x%08x\n", __func__,
+		     fsmvalue);
+	} else {
+		/* disable automatic responses, and irqs */
+		writel(0, &dev->usb->stdrsp);
+		writel(0, &dev->regs->pciirqenb0);
+		writel(0, &dev->regs->pciirqenb1);
+	}
+
+	/* clear old dma and irq state */
+	for (tmp = 0; tmp < 4; tmp++) {
+		struct net2280_ep *ep = &dev->ep[tmp + 1];
+
+		if (ep->dma)
+			abort_dma(ep);
+	}
+
+	writel(~0, &dev->regs->irqstat0), writel(~0, &dev->regs->irqstat1);
+
+	if (fsmvalue == DEFECT7374_FSM_SS_CONTROL_READ) {
+		/* reset, and enable pci */
+		tmp = readl(&dev->regs->devinit) |
+		    BIT(PCI_ENABLE) |
+		    BIT(FIFO_SOFT_RESET) |
+		    BIT(USB_SOFT_RESET) |
+		    BIT(M8051_RESET);
+
+		writel(tmp, &dev->regs->devinit);
+	}
+
+	/* always ep-{1,2,3,4} ... maybe not ep-3 or ep-4 */
+	INIT_LIST_HEAD(&dev->gadget.ep_list);
+
+	for (tmp = 1; tmp < dev->n_ep; tmp++)
+		list_add_tail(&dev->ep[tmp].ep.ep_list, &dev->gadget.ep_list);
+
+}
+
+static void usb_reset(struct net2280 *dev)
+{
+	if (dev->quirks & PLX_LEGACY)
+		return usb_reset_228x(dev);
+	return usb_reset_338x(dev);
+}
+
+static void usb_reinit_228x(struct net2280 *dev)
+{
+	u32	tmp;
+	int	init_dma;
+
+	/* use_dma changes are ignored till next device re-init */
+	init_dma = use_dma;
+
+	/* basic endpoint init */
+	for (tmp = 0; tmp < 7; tmp++) {
+		struct net2280_ep	*ep = &dev->ep[tmp];
+
+		ep->ep.name = ep_name[tmp];
+		ep->dev = dev;
+		ep->num = tmp;
+
+		if (tmp > 0 && tmp <= 4) {
+			ep->fifo_size = 1024;
+			if (init_dma)
+				ep->dma = &dev->dma[tmp - 1];
+		} else
+			ep->fifo_size = 64;
+		ep->regs = &dev->epregs[tmp];
+		ep->cfg = &dev->epregs[tmp];
+		ep_reset_228x(dev->regs, ep);
+	}
+	usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64);
+	usb_ep_set_maxpacket_limit(&dev->ep[5].ep, 64);
+	usb_ep_set_maxpacket_limit(&dev->ep[6].ep, 64);
+
+	dev->gadget.ep0 = &dev->ep[0].ep;
+	dev->ep[0].stopped = 0;
+	INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+
+	/* we want to prevent lowlevel/insecure access from the USB host,
+	 * but erratum 0119 means this enable bit is ignored
+	 */
+	for (tmp = 0; tmp < 5; tmp++)
+		writel(EP_DONTUSE, &dev->dep[tmp].dep_cfg);
+}
+
+static void usb_reinit_338x(struct net2280 *dev)
+{
+	int init_dma;
+	int i;
+	u32 tmp, val;
+	u32 fsmvalue;
+	static const u32 ne[9] = { 0, 1, 2, 3, 4, 1, 2, 3, 4 };
+	static const u32 ep_reg_addr[9] = { 0x00, 0xC0, 0x00, 0xC0, 0x00,
+						0x00, 0xC0, 0x00, 0xC0 };
+
+	/* use_dma changes are ignored till next device re-init */
+	init_dma = use_dma;
+
+	/* basic endpoint init */
+	for (i = 0; i < dev->n_ep; i++) {
+		struct net2280_ep *ep = &dev->ep[i];
+
+		ep->ep.name = ep_name[i];
+		ep->dev = dev;
+		ep->num = i;
+
+		if (i > 0 && i <= 4 && init_dma)
+			ep->dma = &dev->dma[i - 1];
+
+		if (dev->enhanced_mode) {
+			ep->cfg = &dev->epregs[ne[i]];
+			ep->regs = (struct net2280_ep_regs __iomem *)
+				(((void __iomem *)&dev->epregs[ne[i]]) +
+				ep_reg_addr[i]);
+			ep->fiforegs = &dev->fiforegs[i];
+		} else {
+			ep->cfg = &dev->epregs[i];
+			ep->regs = &dev->epregs[i];
+			ep->fiforegs = &dev->fiforegs[i];
+		}
+
+		ep->fifo_size = (i != 0) ? 2048 : 512;
+
+		ep_reset_338x(dev->regs, ep);
+	}
+	usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 512);
+
+	dev->gadget.ep0 = &dev->ep[0].ep;
+	dev->ep[0].stopped = 0;
+
+	/* Link layer set up */
+	fsmvalue = get_idx_reg(dev->regs, SCRATCH) &
+				(0xf << DEFECT7374_FSM_FIELD);
+
+	/* See if driver needs to set up for workaround: */
+	if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ)
+		ep_info(dev, "%s: Defect 7374 FsmValue %08x\n",
+						__func__, fsmvalue);
+	else {
+		tmp = readl(&dev->usb_ext->usbctl2) &
+		    ~(BIT(U1_ENABLE) | BIT(U2_ENABLE) | BIT(LTM_ENABLE));
+		writel(tmp, &dev->usb_ext->usbctl2);
+	}
+
+	/* Hardware Defect and Workaround */
+	val = readl(&dev->ll_lfps_regs->ll_lfps_5);
+	val &= ~(0xf << TIMER_LFPS_6US);
+	val |= 0x5 << TIMER_LFPS_6US;
+	writel(val, &dev->ll_lfps_regs->ll_lfps_5);
+
+	val = readl(&dev->ll_lfps_regs->ll_lfps_6);
+	val &= ~(0xffff << TIMER_LFPS_80US);
+	val |= 0x0100 << TIMER_LFPS_80US;
+	writel(val, &dev->ll_lfps_regs->ll_lfps_6);
+
+	/*
+	 * AA_AB Errata. Issue 4. Workaround for SuperSpeed USB
+	 * Hot Reset Exit Handshake may Fail in Specific Case using
+	 * Default Register Settings. Workaround for Enumeration test.
+	 */
+	val = readl(&dev->ll_tsn_regs->ll_tsn_counters_2);
+	val &= ~(0x1f << HOT_TX_NORESET_TS2);
+	val |= 0x10 << HOT_TX_NORESET_TS2;
+	writel(val, &dev->ll_tsn_regs->ll_tsn_counters_2);
+
+	val = readl(&dev->ll_tsn_regs->ll_tsn_counters_3);
+	val &= ~(0x1f << HOT_RX_RESET_TS2);
+	val |= 0x3 << HOT_RX_RESET_TS2;
+	writel(val, &dev->ll_tsn_regs->ll_tsn_counters_3);
+
+	/*
+	 * Set Recovery Idle to Recover bit:
+	 * - On SS connections, setting Recovery Idle to Recover Fmw improves
+	 *   link robustness with various hosts and hubs.
+	 * - It is safe to set for all connection speeds; all chip revisions.
+	 * - R-M-W to leave other bits undisturbed.
+	 * - Reference PLX TT-7372
+	*/
+	val = readl(&dev->ll_chicken_reg->ll_tsn_chicken_bit);
+	val |= BIT(RECOVERY_IDLE_TO_RECOVER_FMW);
+	writel(val, &dev->ll_chicken_reg->ll_tsn_chicken_bit);
+
+	INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+
+	/* disable dedicated endpoints */
+	writel(0x0D, &dev->dep[0].dep_cfg);
+	writel(0x0D, &dev->dep[1].dep_cfg);
+	writel(0x0E, &dev->dep[2].dep_cfg);
+	writel(0x0E, &dev->dep[3].dep_cfg);
+	writel(0x0F, &dev->dep[4].dep_cfg);
+	writel(0x0C, &dev->dep[5].dep_cfg);
+}
+
+static void usb_reinit(struct net2280 *dev)
+{
+	if (dev->quirks & PLX_LEGACY)
+		return usb_reinit_228x(dev);
+	return usb_reinit_338x(dev);
+}
+
+static void ep0_start_228x(struct net2280 *dev)
+{
+	writel(BIT(CLEAR_EP_HIDE_STATUS_PHASE) |
+		BIT(CLEAR_NAK_OUT_PACKETS) |
+		BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE),
+		&dev->epregs[0].ep_rsp);
+
+	/*
+	 * hardware optionally handles a bunch of standard requests
+	 * that the API hides from drivers anyway.  have it do so.
+	 * endpoint status/features are handled in software, to
+	 * help pass tests for some dubious behavior.
+	 */
+	writel(BIT(SET_TEST_MODE) |
+		BIT(SET_ADDRESS) |
+		BIT(DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP) |
+		BIT(GET_DEVICE_STATUS) |
+		BIT(GET_INTERFACE_STATUS),
+		&dev->usb->stdrsp);
+	writel(BIT(USB_ROOT_PORT_WAKEUP_ENABLE) |
+		BIT(SELF_POWERED_USB_DEVICE) |
+		BIT(REMOTE_WAKEUP_SUPPORT) |
+		(dev->softconnect << USB_DETECT_ENABLE) |
+		BIT(SELF_POWERED_STATUS),
+		&dev->usb->usbctl);
+
+	/* enable irqs so we can see ep0 and general operation  */
+	writel(BIT(SETUP_PACKET_INTERRUPT_ENABLE) |
+		BIT(ENDPOINT_0_INTERRUPT_ENABLE),
+		&dev->regs->pciirqenb0);
+	writel(BIT(PCI_INTERRUPT_ENABLE) |
+		BIT(PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE) |
+		BIT(PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE) |
+		BIT(PCI_RETRY_ABORT_INTERRUPT_ENABLE) |
+		BIT(VBUS_INTERRUPT_ENABLE) |
+		BIT(ROOT_PORT_RESET_INTERRUPT_ENABLE) |
+		BIT(SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE),
+		&dev->regs->pciirqenb1);
+
+	/* don't leave any writes posted */
+	(void) readl(&dev->usb->usbctl);
+}
+
+static void ep0_start_338x(struct net2280 *dev)
+{
+	u32 fsmvalue;
+
+	fsmvalue = get_idx_reg(dev->regs, SCRATCH) &
+			(0xf << DEFECT7374_FSM_FIELD);
+
+	if (fsmvalue != DEFECT7374_FSM_SS_CONTROL_READ)
+		ep_info(dev, "%s: Defect 7374 FsmValue %08x\n", __func__,
+		     fsmvalue);
+	else
+		writel(BIT(CLEAR_NAK_OUT_PACKETS_MODE) |
+		       BIT(SET_EP_HIDE_STATUS_PHASE),
+		       &dev->epregs[0].ep_rsp);
+
+	/*
+	 * hardware optionally handles a bunch of standard requests
+	 * that the API hides from drivers anyway.  have it do so.
+	 * endpoint status/features are handled in software, to
+	 * help pass tests for some dubious behavior.
+	 */
+	writel(BIT(SET_ISOCHRONOUS_DELAY) |
+	       BIT(SET_SEL) |
+	       BIT(SET_TEST_MODE) |
+	       BIT(SET_ADDRESS) |
+	       BIT(GET_INTERFACE_STATUS) |
+	       BIT(GET_DEVICE_STATUS),
+		&dev->usb->stdrsp);
+	dev->wakeup_enable = 1;
+	writel(BIT(USB_ROOT_PORT_WAKEUP_ENABLE) |
+	       (dev->softconnect << USB_DETECT_ENABLE) |
+	       BIT(DEVICE_REMOTE_WAKEUP_ENABLE),
+	       &dev->usb->usbctl);
+
+	/* enable irqs so we can see ep0 and general operation  */
+	writel(BIT(SETUP_PACKET_INTERRUPT_ENABLE) |
+	       BIT(ENDPOINT_0_INTERRUPT_ENABLE),
+	       &dev->regs->pciirqenb0);
+	writel(BIT(PCI_INTERRUPT_ENABLE) |
+	       BIT(ROOT_PORT_RESET_INTERRUPT_ENABLE) |
+	       BIT(SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE) |
+	       BIT(VBUS_INTERRUPT_ENABLE),
+	       &dev->regs->pciirqenb1);
+
+	/* don't leave any writes posted */
+	(void)readl(&dev->usb->usbctl);
+}
+
+static void ep0_start(struct net2280 *dev)
+{
+	if (dev->quirks & PLX_LEGACY)
+		return ep0_start_228x(dev);
+	return ep0_start_338x(dev);
+}
+
+/* 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.
+ */
+static int net2280_start(struct usb_gadget *_gadget,
+		struct usb_gadget_driver *driver)
+{
+	struct net2280		*dev;
+	int			retval;
+	unsigned		i;
+
+	/* insist on high speed support from the driver, since
+	 * (dev->usb->xcvrdiag & FORCE_FULL_SPEED_MODE)
+	 * "must not be used in normal operation"
+	 */
+	if (!driver || driver->max_speed < USB_SPEED_HIGH ||
+			!driver->setup)
+		return -EINVAL;
+
+	dev = container_of(_gadget, struct net2280, gadget);
+
+	for (i = 0; i < dev->n_ep; i++)
+		dev->ep[i].irqs = 0;
+
+	/* hook up the driver ... */
+	dev->softconnect = 1;
+	driver->driver.bus = NULL;
+	dev->driver = driver;
+
+	retval = device_create_file(&dev->pdev->dev, &dev_attr_function);
+	if (retval)
+		goto err_unbind;
+	retval = device_create_file(&dev->pdev->dev, &dev_attr_queues);
+	if (retval)
+		goto err_func;
+
+	/* Enable force-full-speed testing mode, if desired */
+	if (full_speed && (dev->quirks & PLX_LEGACY))
+		writel(BIT(FORCE_FULL_SPEED_MODE), &dev->usb->xcvrdiag);
+
+	/* ... then enable host detection and ep0; and we're ready
+	 * for set_configuration as well as eventual disconnect.
+	 */
+	net2280_led_active(dev, 1);
+
+	if (dev->quirks & PLX_SUPERSPEED)
+		defect7374_enable_data_eps_zero(dev);
+
+	ep0_start(dev);
+
+	ep_dbg(dev, "%s ready, usbctl %08x stdrsp %08x\n",
+			driver->driver.name,
+			readl(&dev->usb->usbctl),
+			readl(&dev->usb->stdrsp));
+
+	/* pci writes may still be posted */
+	return 0;
+
+err_func:
+	device_remove_file(&dev->pdev->dev, &dev_attr_function);
+err_unbind:
+	dev->driver = NULL;
+	return retval;
+}
+
+static void stop_activity(struct net2280 *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;
+
+	/* stop hardware; prevent new request submissions;
+	 * and kill any outstanding requests.
+	 */
+	usb_reset(dev);
+	for (i = 0; i < dev->n_ep; i++)
+		nuke(&dev->ep[i]);
+
+	/* report disconnect; the driver is already quiesced */
+	if (driver) {
+		spin_unlock(&dev->lock);
+		driver->disconnect(&dev->gadget);
+		spin_lock(&dev->lock);
+	}
+
+	usb_reinit(dev);
+}
+
+static int net2280_stop(struct usb_gadget *_gadget,
+		struct usb_gadget_driver *driver)
+{
+	struct net2280	*dev;
+	unsigned long	flags;
+
+	dev = container_of(_gadget, struct net2280, gadget);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	stop_activity(dev, driver);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	dev->driver = NULL;
+
+	net2280_led_active(dev, 0);
+
+	/* Disable full-speed test mode */
+	if (dev->quirks & PLX_LEGACY)
+		writel(0, &dev->usb->xcvrdiag);
+
+	device_remove_file(&dev->pdev->dev, &dev_attr_function);
+	device_remove_file(&dev->pdev->dev, &dev_attr_queues);
+
+	ep_dbg(dev, "unregistered driver '%s'\n",
+			driver ? driver->driver.name : "");
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* handle ep0, ep-e, ep-f with 64 byte packets: packet per irq.
+ * also works for dma-capable endpoints, in pio mode or just
+ * to manually advance the queue after short OUT transfers.
+ */
+static void handle_ep_small(struct net2280_ep *ep)
+{
+	struct net2280_request	*req;
+	u32			t;
+	/* 0 error, 1 mid-data, 2 done */
+	int			mode = 1;
+
+	if (!list_empty(&ep->queue))
+		req = list_entry(ep->queue.next,
+			struct net2280_request, queue);
+	else
+		req = NULL;
+
+	/* ack all, and handle what we care about */
+	t = readl(&ep->regs->ep_stat);
+	ep->irqs++;
+#if 0
+	ep_vdbg(ep->dev, "%s ack ep_stat %08x, req %p\n",
+			ep->ep.name, t, req ? &req->req : 0);
+#endif
+	if (!ep->is_in || (ep->dev->quirks & PLX_2280))
+		writel(t & ~BIT(NAK_OUT_PACKETS), &ep->regs->ep_stat);
+	else
+		/* Added for 2282 */
+		writel(t, &ep->regs->ep_stat);
+
+	/* for ep0, monitor token irqs to catch data stage length errors
+	 * and to synchronize on status.
+	 *
+	 * also, to defer reporting of protocol stalls ... here's where
+	 * data or status first appears, handling stalls here should never
+	 * cause trouble on the host side..
+	 *
+	 * control requests could be slightly faster without token synch for
+	 * status, but status can jam up that way.
+	 */
+	if (unlikely(ep->num == 0)) {
+		if (ep->is_in) {
+			/* status; stop NAKing */
+			if (t & BIT(DATA_OUT_PING_TOKEN_INTERRUPT)) {
+				if (ep->dev->protocol_stall) {
+					ep->stopped = 1;
+					set_halt(ep);
+				}
+				if (!req)
+					allow_status(ep);
+				mode = 2;
+			/* reply to extra IN data tokens with a zlp */
+			} else if (t & BIT(DATA_IN_TOKEN_INTERRUPT)) {
+				if (ep->dev->protocol_stall) {
+					ep->stopped = 1;
+					set_halt(ep);
+					mode = 2;
+				} else if (ep->responded &&
+						!req && !ep->stopped)
+					write_fifo(ep, NULL);
+			}
+		} else {
+			/* status; stop NAKing */
+			if (t & BIT(DATA_IN_TOKEN_INTERRUPT)) {
+				if (ep->dev->protocol_stall) {
+					ep->stopped = 1;
+					set_halt(ep);
+				}
+				mode = 2;
+			/* an extra OUT token is an error */
+			} else if (((t & BIT(DATA_OUT_PING_TOKEN_INTERRUPT)) &&
+					req &&
+					req->req.actual == req->req.length) ||
+					(ep->responded && !req)) {
+				ep->dev->protocol_stall = 1;
+				set_halt(ep);
+				ep->stopped = 1;
+				if (req)
+					done(ep, req, -EOVERFLOW);
+				req = NULL;
+			}
+		}
+	}
+
+	if (unlikely(!req))
+		return;
+
+	/* manual DMA queue advance after short OUT */
+	if (likely(ep->dma)) {
+		if (t & BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
+			u32	count;
+			int	stopped = ep->stopped;
+
+			/* TRANSFERRED works around OUT_DONE erratum 0112.
+			 * we expect (N <= maxpacket) bytes; host wrote M.
+			 * iff (M < N) we won't ever see a DMA interrupt.
+			 */
+			ep->stopped = 1;
+			for (count = 0; ; t = readl(&ep->regs->ep_stat)) {
+
+				/* any preceding dma transfers must finish.
+				 * dma handles (M >= N), may empty the queue
+				 */
+				scan_dma_completions(ep);
+				if (unlikely(list_empty(&ep->queue) ||
+						ep->out_overflow)) {
+					req = NULL;
+					break;
+				}
+				req = list_entry(ep->queue.next,
+					struct net2280_request, queue);
+
+				/* here either (M < N), a "real" short rx;
+				 * or (M == N) and the queue didn't empty
+				 */
+				if (likely(t & BIT(FIFO_EMPTY))) {
+					count = readl(&ep->dma->dmacount);
+					count &= DMA_BYTE_COUNT_MASK;
+					if (readl(&ep->dma->dmadesc)
+							!= req->td_dma)
+						req = NULL;
+					break;
+				}
+				udelay(1);
+			}
+
+			/* stop DMA, leave ep NAKing */
+			writel(BIT(DMA_ABORT), &ep->dma->dmastat);
+			spin_stop_dma(ep->dma);
+
+			if (likely(req)) {
+				req->td->dmacount = 0;
+				t = readl(&ep->regs->ep_avail);
+				dma_done(ep, req, count,
+					(ep->out_overflow || t)
+						? -EOVERFLOW : 0);
+			}
+
+			/* also flush to prevent erratum 0106 trouble */
+			if (unlikely(ep->out_overflow ||
+					(ep->dev->chiprev == 0x0100 &&
+					ep->dev->gadget.speed
+					== USB_SPEED_FULL))) {
+				out_flush(ep);
+				ep->out_overflow = 0;
+			}
+
+			/* (re)start dma if needed, stop NAKing */
+			ep->stopped = stopped;
+			if (!list_empty(&ep->queue))
+				restart_dma(ep);
+		} else
+			ep_dbg(ep->dev, "%s dma ep_stat %08x ??\n",
+					ep->ep.name, t);
+		return;
+
+	/* data packet(s) received (in the fifo, OUT) */
+	} else if (t & BIT(DATA_PACKET_RECEIVED_INTERRUPT)) {
+		if (read_fifo(ep, req) && ep->num != 0)
+			mode = 2;
+
+	/* data packet(s) transmitted (IN) */
+	} else if (t & BIT(DATA_PACKET_TRANSMITTED_INTERRUPT)) {
+		unsigned	len;
+
+		len = req->req.length - req->req.actual;
+		if (len > ep->ep.maxpacket)
+			len = ep->ep.maxpacket;
+		req->req.actual += len;
+
+		/* if we wrote it all, we're usually done */
+		/* send zlps until the status stage */
+		if ((req->req.actual == req->req.length) &&
+			(!req->req.zero || len != ep->ep.maxpacket) && ep->num)
+				mode = 2;
+
+	/* there was nothing to do ...  */
+	} else if (mode == 1)
+		return;
+
+	/* done */
+	if (mode == 2) {
+		/* stream endpoints often resubmit/unlink in completion */
+		done(ep, req, 0);
+
+		/* maybe advance queue to next request */
+		if (ep->num == 0) {
+			/* NOTE:  net2280 could let gadget driver start the
+			 * status stage later. since not all controllers let
+			 * them control that, the api doesn't (yet) allow it.
+			 */
+			if (!ep->stopped)
+				allow_status(ep);
+			req = NULL;
+		} else {
+			if (!list_empty(&ep->queue) && !ep->stopped)
+				req = list_entry(ep->queue.next,
+					struct net2280_request, queue);
+			else
+				req = NULL;
+			if (req && !ep->is_in)
+				stop_out_naking(ep);
+		}
+	}
+
+	/* is there a buffer for the next packet?
+	 * for best streaming performance, make sure there is one.
+	 */
+	if (req && !ep->stopped) {
+
+		/* load IN fifo with next packet (may be zlp) */
+		if (t & BIT(DATA_PACKET_TRANSMITTED_INTERRUPT))
+			write_fifo(ep, &req->req);
+	}
+}
+
+static struct net2280_ep *get_ep_by_addr(struct net2280 *dev, u16 wIndex)
+{
+	struct net2280_ep	*ep;
+
+	if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
+		return &dev->ep[0];
+	list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
+		u8	bEndpointAddress;
+
+		if (!ep->desc)
+			continue;
+		bEndpointAddress = ep->desc->bEndpointAddress;
+		if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
+			continue;
+		if ((wIndex & 0x0f) == (bEndpointAddress & 0x0f))
+			return ep;
+	}
+	return NULL;
+}
+
+static void defect7374_workaround(struct net2280 *dev, struct usb_ctrlrequest r)
+{
+	u32 scratch, fsmvalue;
+	u32 ack_wait_timeout, state;
+
+	/* Workaround for Defect 7374 (U1/U2 erroneously rejected): */
+	scratch = get_idx_reg(dev->regs, SCRATCH);
+	fsmvalue = scratch & (0xf << DEFECT7374_FSM_FIELD);
+	scratch &= ~(0xf << DEFECT7374_FSM_FIELD);
+
+	if (!((fsmvalue == DEFECT7374_FSM_WAITING_FOR_CONTROL_READ) &&
+				(r.bRequestType & USB_DIR_IN)))
+		return;
+
+	/* This is the first Control Read for this connection: */
+	if (!(readl(&dev->usb->usbstat) & BIT(SUPER_SPEED_MODE))) {
+		/*
+		 * Connection is NOT SS:
+		 * - Connection must be FS or HS.
+		 * - This FSM state should allow workaround software to
+		 * run after the next USB connection.
+		 */
+		scratch |= DEFECT7374_FSM_NON_SS_CONTROL_READ;
+		goto restore_data_eps;
+	}
+
+	/* Connection is SS: */
+	for (ack_wait_timeout = 0;
+			ack_wait_timeout < DEFECT_7374_NUMBEROF_MAX_WAIT_LOOPS;
+			ack_wait_timeout++) {
+
+		state =	readl(&dev->plregs->pl_ep_status_1)
+			& (0xff << STATE);
+		if ((state >= (ACK_GOOD_NORMAL << STATE)) &&
+			(state <= (ACK_GOOD_MORE_ACKS_TO_COME << STATE))) {
+			scratch |= DEFECT7374_FSM_SS_CONTROL_READ;
+			break;
+		}
+
+		/*
+		 * We have not yet received host's Data Phase ACK
+		 * - Wait and try again.
+		 */
+		udelay(DEFECT_7374_PROCESSOR_WAIT_TIME);
+
+		continue;
+	}
+
+
+	if (ack_wait_timeout >= DEFECT_7374_NUMBEROF_MAX_WAIT_LOOPS) {
+		ep_err(dev, "FAIL: Defect 7374 workaround waited but failed "
+		"to detect SS host's data phase ACK.");
+		ep_err(dev, "PL_EP_STATUS_1(23:16):.Expected from 0x11 to 0x16"
+		"got 0x%2.2x.\n", state >> STATE);
+	} else {
+		ep_warn(dev, "INFO: Defect 7374 workaround waited about\n"
+		"%duSec for Control Read Data Phase ACK\n",
+			DEFECT_7374_PROCESSOR_WAIT_TIME * ack_wait_timeout);
+	}
+
+restore_data_eps:
+	/*
+	 * Restore data EPs to their pre-workaround settings (disabled,
+	 * initialized, and other details).
+	 */
+	defect7374_disable_data_eps(dev);
+
+	set_idx_reg(dev->regs, SCRATCH, scratch);
+
+	return;
+}
+
+static void ep_stall(struct net2280_ep *ep, int stall)
+{
+	struct net2280 *dev = ep->dev;
+	u32 val;
+	static const u32 ep_pl[9] = { 0, 3, 4, 7, 8, 2, 5, 6, 9 };
+
+	if (stall) {
+		writel(BIT(SET_ENDPOINT_HALT) |
+		       /* BIT(SET_NAK_PACKETS) | */
+		       BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE),
+		       &ep->regs->ep_rsp);
+		ep->is_halt = 1;
+	} else {
+		if (dev->gadget.speed == USB_SPEED_SUPER) {
+			/*
+			 * Workaround for SS SeqNum not cleared via
+			 * Endpoint Halt (Clear) bit. select endpoint
+			 */
+			val = readl(&dev->plregs->pl_ep_ctrl);
+			val = (val & ~0x1f) | ep_pl[ep->num];
+			writel(val, &dev->plregs->pl_ep_ctrl);
+
+			val |= BIT(SEQUENCE_NUMBER_RESET);
+			writel(val, &dev->plregs->pl_ep_ctrl);
+		}
+		val = readl(&ep->regs->ep_rsp);
+		val |= BIT(CLEAR_ENDPOINT_HALT) |
+			BIT(CLEAR_ENDPOINT_TOGGLE);
+		writel(val,
+		       /* | BIT(CLEAR_NAK_PACKETS),*/
+		       &ep->regs->ep_rsp);
+		ep->is_halt = 0;
+		val = readl(&ep->regs->ep_rsp);
+	}
+}
+
+static void ep_stdrsp(struct net2280_ep *ep, int value, int wedged)
+{
+	/* set/clear, then synch memory views with the device */
+	if (value) {
+		ep->stopped = 1;
+		if (ep->num == 0)
+			ep->dev->protocol_stall = 1;
+		else {
+			if (ep->dma)
+				ep_stop_dma(ep);
+			ep_stall(ep, true);
+		}
+
+		if (wedged)
+			ep->wedged = 1;
+	} else {
+		ep->stopped = 0;
+		ep->wedged = 0;
+
+		ep_stall(ep, false);
+
+		/* Flush the queue */
+		if (!list_empty(&ep->queue)) {
+			struct net2280_request *req =
+			    list_entry(ep->queue.next, struct net2280_request,
+				       queue);
+			if (ep->dma)
+				resume_dma(ep);
+			else {
+				if (ep->is_in)
+					write_fifo(ep, &req->req);
+				else {
+					if (read_fifo(ep, req))
+						done(ep, req, 0);
+				}
+			}
+		}
+	}
+}
+
+static void handle_stat0_irqs_superspeed(struct net2280 *dev,
+		struct net2280_ep *ep, struct usb_ctrlrequest r)
+{
+	int tmp = 0;
+
+#define	w_value		le16_to_cpu(r.wValue)
+#define	w_index		le16_to_cpu(r.wIndex)
+#define	w_length	le16_to_cpu(r.wLength)
+
+	switch (r.bRequest) {
+		struct net2280_ep *e;
+		u16 status;
+
+	case USB_REQ_SET_CONFIGURATION:
+		dev->addressed_state = !w_value;
+		goto usb3_delegate;
+
+	case USB_REQ_GET_STATUS:
+		switch (r.bRequestType) {
+		case (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE):
+			status = dev->wakeup_enable ? 0x02 : 0x00;
+			if (dev->selfpowered)
+				status |= BIT(0);
+			status |= (dev->u1_enable << 2 | dev->u2_enable << 3 |
+							dev->ltm_enable << 4);
+			writel(0, &dev->epregs[0].ep_irqenb);
+			set_fifo_bytecount(ep, sizeof(status));
+			writel((__force u32) status, &dev->epregs[0].ep_data);
+			allow_status_338x(ep);
+			break;
+
+		case (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
+			e = get_ep_by_addr(dev, w_index);
+			if (!e)
+				goto do_stall3;
+			status = readl(&e->regs->ep_rsp) &
+						BIT(CLEAR_ENDPOINT_HALT);
+			writel(0, &dev->epregs[0].ep_irqenb);
+			set_fifo_bytecount(ep, sizeof(status));
+			writel((__force u32) status, &dev->epregs[0].ep_data);
+			allow_status_338x(ep);
+			break;
+
+		default:
+			goto usb3_delegate;
+		}
+		break;
+
+	case USB_REQ_CLEAR_FEATURE:
+		switch (r.bRequestType) {
+		case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE):
+			if (!dev->addressed_state) {
+				switch (w_value) {
+				case USB_DEVICE_U1_ENABLE:
+					dev->u1_enable = 0;
+					writel(readl(&dev->usb_ext->usbctl2) &
+						~BIT(U1_ENABLE),
+						&dev->usb_ext->usbctl2);
+					allow_status_338x(ep);
+					goto next_endpoints3;
+
+				case USB_DEVICE_U2_ENABLE:
+					dev->u2_enable = 0;
+					writel(readl(&dev->usb_ext->usbctl2) &
+						~BIT(U2_ENABLE),
+						&dev->usb_ext->usbctl2);
+					allow_status_338x(ep);
+					goto next_endpoints3;
+
+				case USB_DEVICE_LTM_ENABLE:
+					dev->ltm_enable = 0;
+					writel(readl(&dev->usb_ext->usbctl2) &
+						~BIT(LTM_ENABLE),
+						&dev->usb_ext->usbctl2);
+					allow_status_338x(ep);
+					goto next_endpoints3;
+
+				default:
+					break;
+				}
+			}
+			if (w_value == USB_DEVICE_REMOTE_WAKEUP) {
+				dev->wakeup_enable = 0;
+				writel(readl(&dev->usb->usbctl) &
+					~BIT(DEVICE_REMOTE_WAKEUP_ENABLE),
+					&dev->usb->usbctl);
+				allow_status_338x(ep);
+				break;
+			}
+			goto usb3_delegate;
+
+		case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
+			e = get_ep_by_addr(dev,	w_index);
+			if (!e)
+				goto do_stall3;
+			if (w_value != USB_ENDPOINT_HALT)
+				goto do_stall3;
+			ep_vdbg(dev, "%s clear halt\n", e->ep.name);
+			ep_stall(e, false);
+			if (!list_empty(&e->queue) && e->td_dma)
+				restart_dma(e);
+			allow_status(ep);
+			ep->stopped = 1;
+			break;
+
+		default:
+			goto usb3_delegate;
+		}
+		break;
+	case USB_REQ_SET_FEATURE:
+		switch (r.bRequestType) {
+		case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE):
+			if (!dev->addressed_state) {
+				switch (w_value) {
+				case USB_DEVICE_U1_ENABLE:
+					dev->u1_enable = 1;
+					writel(readl(&dev->usb_ext->usbctl2) |
+						BIT(U1_ENABLE),
+						&dev->usb_ext->usbctl2);
+					allow_status_338x(ep);
+					goto next_endpoints3;
+
+				case USB_DEVICE_U2_ENABLE:
+					dev->u2_enable = 1;
+					writel(readl(&dev->usb_ext->usbctl2) |
+						BIT(U2_ENABLE),
+						&dev->usb_ext->usbctl2);
+					allow_status_338x(ep);
+					goto next_endpoints3;
+
+				case USB_DEVICE_LTM_ENABLE:
+					dev->ltm_enable = 1;
+					writel(readl(&dev->usb_ext->usbctl2) |
+						BIT(LTM_ENABLE),
+						&dev->usb_ext->usbctl2);
+					allow_status_338x(ep);
+					goto next_endpoints3;
+				default:
+					break;
+				}
+			}
+
+			if (w_value == USB_DEVICE_REMOTE_WAKEUP) {
+				dev->wakeup_enable = 1;
+				writel(readl(&dev->usb->usbctl) |
+					BIT(DEVICE_REMOTE_WAKEUP_ENABLE),
+					&dev->usb->usbctl);
+				allow_status_338x(ep);
+				break;
+			}
+			goto usb3_delegate;
+
+		case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
+			e = get_ep_by_addr(dev,	w_index);
+			if (!e || (w_value != USB_ENDPOINT_HALT))
+				goto do_stall3;
+			ep_stdrsp(e, true, false);
+			allow_status_338x(ep);
+			break;
+
+		default:
+			goto usb3_delegate;
+		}
+
+		break;
+	default:
+
+usb3_delegate:
+		ep_vdbg(dev, "setup %02x.%02x v%04x i%04x l%04x ep_cfg %08x\n",
+				r.bRequestType, r.bRequest,
+				w_value, w_index, w_length,
+				readl(&ep->cfg->ep_cfg));
+
+		ep->responded = 0;
+		spin_unlock(&dev->lock);
+		tmp = dev->driver->setup(&dev->gadget, &r);
+		spin_lock(&dev->lock);
+	}
+do_stall3:
+	if (tmp < 0) {
+		ep_vdbg(dev, "req %02x.%02x protocol STALL; stat %d\n",
+				r.bRequestType, r.bRequest, tmp);
+		dev->protocol_stall = 1;
+		/* TD 9.9 Halt Endpoint test. TD 9.22 Set feature test */
+		ep_stall(ep, true);
+	}
+
+next_endpoints3:
+
+#undef	w_value
+#undef	w_index
+#undef	w_length
+
+	return;
+}
+
+static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
+{
+	struct net2280_ep	*ep;
+	u32			num, scratch;
+
+	/* most of these don't need individual acks */
+	stat &= ~BIT(INTA_ASSERTED);
+	if (!stat)
+		return;
+	/* ep_dbg(dev, "irqstat0 %04x\n", stat); */
+
+	/* starting a control request? */
+	if (unlikely(stat & BIT(SETUP_PACKET_INTERRUPT))) {
+		union {
+			u32			raw[2];
+			struct usb_ctrlrequest	r;
+		} u;
+		int				tmp;
+		struct net2280_request		*req;
+
+		if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
+			u32 val = readl(&dev->usb->usbstat);
+			if (val & BIT(SUPER_SPEED)) {
+				dev->gadget.speed = USB_SPEED_SUPER;
+				usb_ep_set_maxpacket_limit(&dev->ep[0].ep,
+						EP0_SS_MAX_PACKET_SIZE);
+			} else if (val & BIT(HIGH_SPEED)) {
+				dev->gadget.speed = USB_SPEED_HIGH;
+				usb_ep_set_maxpacket_limit(&dev->ep[0].ep,
+						EP0_HS_MAX_PACKET_SIZE);
+			} else {
+				dev->gadget.speed = USB_SPEED_FULL;
+				usb_ep_set_maxpacket_limit(&dev->ep[0].ep,
+						EP0_HS_MAX_PACKET_SIZE);
+			}
+			net2280_led_speed(dev, dev->gadget.speed);
+			ep_dbg(dev, "%s\n",
+					usb_speed_string(dev->gadget.speed));
+		}
+
+		ep = &dev->ep[0];
+		ep->irqs++;
+
+		/* make sure any leftover request state is cleared */
+		stat &= ~BIT(ENDPOINT_0_INTERRUPT);
+		while (!list_empty(&ep->queue)) {
+			req = list_entry(ep->queue.next,
+					struct net2280_request, queue);
+			done(ep, req, (req->req.actual == req->req.length)
+						? 0 : -EPROTO);
+		}
+		ep->stopped = 0;
+		dev->protocol_stall = 0;
+		if (dev->quirks & PLX_SUPERSPEED)
+			ep->is_halt = 0;
+		else{
+			if (ep->dev->quirks & PLX_2280)
+				tmp = BIT(FIFO_OVERFLOW) |
+				    BIT(FIFO_UNDERFLOW);
+			else
+				tmp = 0;
+
+			writel(tmp | BIT(TIMEOUT) |
+				   BIT(USB_STALL_SENT) |
+				   BIT(USB_IN_NAK_SENT) |
+				   BIT(USB_IN_ACK_RCVD) |
+				   BIT(USB_OUT_PING_NAK_SENT) |
+				   BIT(USB_OUT_ACK_SENT) |
+				   BIT(SHORT_PACKET_OUT_DONE_INTERRUPT) |
+				   BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT) |
+				   BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
+				   BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
+				   BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
+				   BIT(DATA_IN_TOKEN_INTERRUPT),
+				   &ep->regs->ep_stat);
+		}
+		u.raw[0] = readl(&dev->usb->setup0123);
+		u.raw[1] = readl(&dev->usb->setup4567);
+
+		cpu_to_le32s(&u.raw[0]);
+		cpu_to_le32s(&u.raw[1]);
+
+		if (dev->quirks & PLX_SUPERSPEED)
+			defect7374_workaround(dev, u.r);
+
+		tmp = 0;
+
+#define	w_value		le16_to_cpu(u.r.wValue)
+#define	w_index		le16_to_cpu(u.r.wIndex)
+#define	w_length	le16_to_cpu(u.r.wLength)
+
+		/* ack the irq */
+		writel(BIT(SETUP_PACKET_INTERRUPT), &dev->regs->irqstat0);
+		stat ^= BIT(SETUP_PACKET_INTERRUPT);
+
+		/* watch control traffic at the token level, and force
+		 * synchronization before letting the status stage happen.
+		 * FIXME ignore tokens we'll NAK, until driver responds.
+		 * that'll mean a lot less irqs for some drivers.
+		 */
+		ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0;
+		if (ep->is_in) {
+			scratch = BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
+				BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
+				BIT(DATA_IN_TOKEN_INTERRUPT);
+			stop_out_naking(ep);
+		} else
+			scratch = BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
+				BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
+				BIT(DATA_IN_TOKEN_INTERRUPT);
+		writel(scratch, &dev->epregs[0].ep_irqenb);
+
+		/* we made the hardware handle most lowlevel requests;
+		 * everything else goes uplevel to the gadget code.
+		 */
+		ep->responded = 1;
+
+		if (dev->gadget.speed == USB_SPEED_SUPER) {
+			handle_stat0_irqs_superspeed(dev, ep, u.r);
+			goto next_endpoints;
+		}
+
+		switch (u.r.bRequest) {
+		case USB_REQ_GET_STATUS: {
+			struct net2280_ep	*e;
+			__le32			status;
+
+			/* hw handles device and interface status */
+			if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
+				goto delegate;
+			e = get_ep_by_addr(dev, w_index);
+			if (!e || w_length > 2)
+				goto do_stall;
+
+			if (readl(&e->regs->ep_rsp) & BIT(SET_ENDPOINT_HALT))
+				status = cpu_to_le32(1);
+			else
+				status = cpu_to_le32(0);
+
+			/* don't bother with a request object! */
+			writel(0, &dev->epregs[0].ep_irqenb);
+			set_fifo_bytecount(ep, w_length);
+			writel((__force u32)status, &dev->epregs[0].ep_data);
+			allow_status(ep);
+			ep_vdbg(dev, "%s stat %02x\n", ep->ep.name, status);
+			goto next_endpoints;
+			}
+			break;
+		case USB_REQ_CLEAR_FEATURE: {
+			struct net2280_ep	*e;
+
+			/* hw handles device features */
+			if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+				goto delegate;
+			if (w_value != USB_ENDPOINT_HALT || w_length != 0)
+				goto do_stall;
+			e = get_ep_by_addr(dev, w_index);
+			if (!e)
+				goto do_stall;
+			if (e->wedged) {
+				ep_vdbg(dev, "%s wedged, halt not cleared\n",
+						ep->ep.name);
+			} else {
+				ep_vdbg(dev, "%s clear halt\n", e->ep.name);
+				clear_halt(e);
+				if ((ep->dev->quirks & PLX_SUPERSPEED) &&
+					!list_empty(&e->queue) && e->td_dma)
+						restart_dma(e);
+			}
+			allow_status(ep);
+			goto next_endpoints;
+			}
+			break;
+		case USB_REQ_SET_FEATURE: {
+			struct net2280_ep	*e;
+
+			/* hw handles device features */
+			if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+				goto delegate;
+			if (w_value != USB_ENDPOINT_HALT || w_length != 0)
+				goto do_stall;
+			e = get_ep_by_addr(dev, w_index);
+			if (!e)
+				goto do_stall;
+			if (e->ep.name == ep0name)
+				goto do_stall;
+			set_halt(e);
+			if ((dev->quirks & PLX_SUPERSPEED) && e->dma)
+				abort_dma(e);
+			allow_status(ep);
+			ep_vdbg(dev, "%s set halt\n", ep->ep.name);
+			goto next_endpoints;
+			}
+			break;
+		default:
+delegate:
+			ep_vdbg(dev, "setup %02x.%02x v%04x i%04x l%04x "
+				"ep_cfg %08x\n",
+				u.r.bRequestType, u.r.bRequest,
+				w_value, w_index, w_length,
+				readl(&ep->cfg->ep_cfg));
+			ep->responded = 0;
+			spin_unlock(&dev->lock);
+			tmp = dev->driver->setup(&dev->gadget, &u.r);
+			spin_lock(&dev->lock);
+		}
+
+		/* stall ep0 on error */
+		if (tmp < 0) {
+do_stall:
+			ep_vdbg(dev, "req %02x.%02x protocol STALL; stat %d\n",
+					u.r.bRequestType, u.r.bRequest, tmp);
+			dev->protocol_stall = 1;
+		}
+
+		/* some in/out token irq should follow; maybe stall then.
+		 * driver must queue a request (even zlp) or halt ep0
+		 * before the host times out.
+		 */
+	}
+
+#undef	w_value
+#undef	w_index
+#undef	w_length
+
+next_endpoints:
+	/* endpoint data irq ? */
+	scratch = stat & 0x7f;
+	stat &= ~0x7f;
+	for (num = 0; scratch; num++) {
+		u32		t;
+
+		/* do this endpoint's FIFO and queue need tending? */
+		t = BIT(num);
+		if ((scratch & t) == 0)
+			continue;
+		scratch ^= t;
+
+		ep = &dev->ep[num];
+		handle_ep_small(ep);
+	}
+
+	if (stat)
+		ep_dbg(dev, "unhandled irqstat0 %08x\n", stat);
+}
+
+#define DMA_INTERRUPTS (BIT(DMA_D_INTERRUPT) | \
+		BIT(DMA_C_INTERRUPT) | \
+		BIT(DMA_B_INTERRUPT) | \
+		BIT(DMA_A_INTERRUPT))
+#define	PCI_ERROR_INTERRUPTS ( \
+		BIT(PCI_MASTER_ABORT_RECEIVED_INTERRUPT) | \
+		BIT(PCI_TARGET_ABORT_RECEIVED_INTERRUPT) | \
+		BIT(PCI_RETRY_ABORT_INTERRUPT))
+
+static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
+{
+	struct net2280_ep	*ep;
+	u32			tmp, num, mask, scratch;
+
+	/* after disconnect there's nothing else to do! */
+	tmp = BIT(VBUS_INTERRUPT) | BIT(ROOT_PORT_RESET_INTERRUPT);
+	mask = BIT(SUPER_SPEED) | BIT(HIGH_SPEED) | BIT(FULL_SPEED);
+
+	/* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
+	 * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRUPT set and
+	 * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT
+	 * only indicates a change in the reset state).
+	 */
+	if (stat & tmp) {
+		writel(tmp, &dev->regs->irqstat1);
+		if ((((stat & BIT(ROOT_PORT_RESET_INTERRUPT)) &&
+				(readl(&dev->usb->usbstat) & mask)) ||
+				((readl(&dev->usb->usbctl) &
+					BIT(VBUS_PIN)) == 0)) &&
+				(dev->gadget.speed != USB_SPEED_UNKNOWN)) {
+			ep_dbg(dev, "disconnect %s\n",
+					dev->driver->driver.name);
+			stop_activity(dev, dev->driver);
+			ep0_start(dev);
+			return;
+		}
+		stat &= ~tmp;
+
+		/* vBUS can bounce ... one of many reasons to ignore the
+		 * notion of hotplug events on bus connect/disconnect!
+		 */
+		if (!stat)
+			return;
+	}
+
+	/* NOTE: chip stays in PCI D0 state for now, but it could
+	 * enter D1 to save more power
+	 */
+	tmp = BIT(SUSPEND_REQUEST_CHANGE_INTERRUPT);
+	if (stat & tmp) {
+		writel(tmp, &dev->regs->irqstat1);
+		if (stat & BIT(SUSPEND_REQUEST_INTERRUPT)) {
+			if (dev->driver->suspend)
+				dev->driver->suspend(&dev->gadget);
+			if (!enable_suspend)
+				stat &= ~BIT(SUSPEND_REQUEST_INTERRUPT);
+		} else {
+			if (dev->driver->resume)
+				dev->driver->resume(&dev->gadget);
+			/* at high speed, note erratum 0133 */
+		}
+		stat &= ~tmp;
+	}
+
+	/* clear any other status/irqs */
+	if (stat)
+		writel(stat, &dev->regs->irqstat1);
+
+	/* some status we can just ignore */
+	if (dev->quirks & PLX_2280)
+		stat &= ~(BIT(CONTROL_STATUS_INTERRUPT) |
+			  BIT(SUSPEND_REQUEST_INTERRUPT) |
+			  BIT(RESUME_INTERRUPT) |
+			  BIT(SOF_INTERRUPT));
+	else
+		stat &= ~(BIT(CONTROL_STATUS_INTERRUPT) |
+			  BIT(RESUME_INTERRUPT) |
+			  BIT(SOF_DOWN_INTERRUPT) |
+			  BIT(SOF_INTERRUPT));
+
+	if (!stat)
+		return;
+	/* ep_dbg(dev, "irqstat1 %08x\n", stat);*/
+
+	/* DMA status, for ep-{a,b,c,d} */
+	scratch = stat & DMA_INTERRUPTS;
+	stat &= ~DMA_INTERRUPTS;
+	scratch >>= 9;
+	for (num = 0; scratch; num++) {
+		struct net2280_dma_regs	__iomem *dma;
+
+		tmp = BIT(num);
+		if ((tmp & scratch) == 0)
+			continue;
+		scratch ^= tmp;
+
+		ep = &dev->ep[num + 1];
+		dma = ep->dma;
+
+		if (!dma)
+			continue;
+
+		/* clear ep's dma status */
+		tmp = readl(&dma->dmastat);
+		writel(tmp, &dma->dmastat);
+
+		/* dma sync*/
+		if (dev->quirks & PLX_SUPERSPEED) {
+			u32 r_dmacount = readl(&dma->dmacount);
+			if (!ep->is_in &&  (r_dmacount & 0x00FFFFFF) &&
+			    (tmp & BIT(DMA_TRANSACTION_DONE_INTERRUPT)))
+				continue;
+		}
+
+		/* chaining should stop on abort, short OUT from fifo,
+		 * or (stat0 codepath) short OUT transfer.
+		 */
+		if (!use_dma_chaining) {
+			if (!(tmp & BIT(DMA_TRANSACTION_DONE_INTERRUPT))) {
+				ep_dbg(ep->dev, "%s no xact done? %08x\n",
+					ep->ep.name, tmp);
+				continue;
+			}
+			stop_dma(ep->dma);
+		}
+
+		/* OUT transfers terminate when the data from the
+		 * host is in our memory.  Process whatever's done.
+		 * On this path, we know transfer's last packet wasn't
+		 * less than req->length. NAK_OUT_PACKETS may be set,
+		 * or the FIFO may already be holding new packets.
+		 *
+		 * IN transfers can linger in the FIFO for a very
+		 * long time ... we ignore that for now, accounting
+		 * precisely (like PIO does) needs per-packet irqs
+		 */
+		scan_dma_completions(ep);
+
+		/* disable dma on inactive queues; else maybe restart */
+		if (list_empty(&ep->queue)) {
+			if (use_dma_chaining)
+				stop_dma(ep->dma);
+		} else {
+			tmp = readl(&dma->dmactl);
+			if (!use_dma_chaining || (tmp & BIT(DMA_ENABLE)) == 0)
+				restart_dma(ep);
+			else if (ep->is_in && use_dma_chaining) {
+				struct net2280_request	*req;
+				__le32			dmacount;
+
+				/* the descriptor at the head of the chain
+				 * may still have VALID_BIT clear; that's
+				 * used to trigger changing DMA_FIFO_VALIDATE
+				 * (affects automagic zlp writes).
+				 */
+				req = list_entry(ep->queue.next,
+						struct net2280_request, queue);
+				dmacount = req->td->dmacount;
+				dmacount &= cpu_to_le32(BIT(VALID_BIT) |
+						DMA_BYTE_COUNT_MASK);
+				if (dmacount && (dmacount & valid_bit) == 0)
+					restart_dma(ep);
+			}
+		}
+		ep->irqs++;
+	}
+
+	/* NOTE:  there are other PCI errors we might usefully notice.
+	 * if they appear very often, here's where to try recovering.
+	 */
+	if (stat & PCI_ERROR_INTERRUPTS) {
+		ep_err(dev, "pci dma error; stat %08x\n", stat);
+		stat &= ~PCI_ERROR_INTERRUPTS;
+		/* these are fatal errors, but "maybe" they won't
+		 * happen again ...
+		 */
+		stop_activity(dev, dev->driver);
+		ep0_start(dev);
+		stat = 0;
+	}
+
+	if (stat)
+		ep_dbg(dev, "unhandled irqstat1 %08x\n", stat);
+}
+
+static irqreturn_t net2280_irq(int irq, void *_dev)
+{
+	struct net2280		*dev = _dev;
+
+	/* shared interrupt, not ours */
+	if ((dev->quirks & PLX_LEGACY) &&
+		(!(readl(&dev->regs->irqstat0) & BIT(INTA_ASSERTED))))
+		return IRQ_NONE;
+
+	spin_lock(&dev->lock);
+
+	/* handle disconnect, dma, and more */
+	handle_stat1_irqs(dev, readl(&dev->regs->irqstat1));
+
+	/* control requests and PIO */
+	handle_stat0_irqs(dev, readl(&dev->regs->irqstat0));
+
+	if (dev->quirks & PLX_SUPERSPEED) {
+		/* re-enable interrupt to trigger any possible new interrupt */
+		u32 pciirqenb1 = readl(&dev->regs->pciirqenb1);
+		writel(pciirqenb1 & 0x7FFFFFFF, &dev->regs->pciirqenb1);
+		writel(pciirqenb1, &dev->regs->pciirqenb1);
+	}
+
+	spin_unlock(&dev->lock);
+
+	return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void gadget_release(struct device *_dev)
+{
+	struct net2280	*dev = dev_get_drvdata(_dev);
+
+	kfree(dev);
+}
+
+/* tear down the binding between this driver and the pci device */
+
+static void net2280_remove(struct pci_dev *pdev)
+{
+	struct net2280		*dev = pci_get_drvdata(pdev);
+
+	usb_del_gadget_udc(&dev->gadget);
+
+	BUG_ON(dev->driver);
+
+	/* then clean up the resources we allocated during probe() */
+	net2280_led_shutdown(dev);
+	if (dev->requests) {
+		int		i;
+		for (i = 1; i < 5; i++) {
+			if (!dev->ep[i].dummy)
+				continue;
+			pci_pool_free(dev->requests, dev->ep[i].dummy,
+					dev->ep[i].td_dma);
+		}
+		pci_pool_destroy(dev->requests);
+	}
+	if (dev->got_irq)
+		free_irq(pdev->irq, dev);
+	if (use_msi && dev->quirks & PLX_SUPERSPEED)
+		pci_disable_msi(pdev);
+	if (dev->regs)
+		iounmap(dev->regs);
+	if (dev->region)
+		release_mem_region(pci_resource_start(pdev, 0),
+				pci_resource_len(pdev, 0));
+	if (dev->enabled)
+		pci_disable_device(pdev);
+	device_remove_file(&pdev->dev, &dev_attr_registers);
+
+	ep_info(dev, "unbind\n");
+}
+
+/* wrap this driver around the specified device, but
+ * don't respond over USB until a gadget driver binds to us.
+ */
+
+static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct net2280		*dev;
+	unsigned long		resource, len;
+	void			__iomem *base = NULL;
+	int			retval, i;
+
+	if (!use_dma)
+		use_dma_chaining = 0;
+
+	/* alloc, and start init */
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		retval = -ENOMEM;
+		goto done;
+	}
+
+	pci_set_drvdata(pdev, dev);
+	spin_lock_init(&dev->lock);
+	dev->quirks = id->driver_data;
+	dev->pdev = pdev;
+	dev->gadget.ops = &net2280_ops;
+	dev->gadget.max_speed = (dev->quirks & PLX_SUPERSPEED) ?
+				USB_SPEED_SUPER : USB_SPEED_HIGH;
+
+	/* the "gadget" abstracts/virtualizes the controller */
+	dev->gadget.name = driver_name;
+
+	/* now all the pci goodies ... */
+	if (pci_enable_device(pdev) < 0) {
+		retval = -ENODEV;
+		goto done;
+	}
+	dev->enabled = 1;
+
+	/* BAR 0 holds all the registers
+	 * BAR 1 is 8051 memory; unused here (note erratum 0103)
+	 * BAR 2 is fifo memory; unused here
+	 */
+	resource = pci_resource_start(pdev, 0);
+	len = pci_resource_len(pdev, 0);
+	if (!request_mem_region(resource, len, driver_name)) {
+		ep_dbg(dev, "controller already in use\n");
+		retval = -EBUSY;
+		goto done;
+	}
+	dev->region = 1;
+
+	/* FIXME provide firmware download interface to put
+	 * 8051 code into the chip, e.g. to turn on PCI PM.
+	 */
+
+	base = ioremap_nocache(resource, len);
+	if (base == NULL) {
+		ep_dbg(dev, "can't map memory\n");
+		retval = -EFAULT;
+		goto done;
+	}
+	dev->regs = (struct net2280_regs __iomem *) base;
+	dev->usb = (struct net2280_usb_regs __iomem *) (base + 0x0080);
+	dev->pci = (struct net2280_pci_regs __iomem *) (base + 0x0100);
+	dev->dma = (struct net2280_dma_regs __iomem *) (base + 0x0180);
+	dev->dep = (struct net2280_dep_regs __iomem *) (base + 0x0200);
+	dev->epregs = (struct net2280_ep_regs __iomem *) (base + 0x0300);
+
+	if (dev->quirks & PLX_SUPERSPEED) {
+		u32 fsmvalue;
+		u32 usbstat;
+		dev->usb_ext = (struct usb338x_usb_ext_regs __iomem *)
+							(base + 0x00b4);
+		dev->fiforegs = (struct usb338x_fifo_regs __iomem *)
+							(base + 0x0500);
+		dev->llregs = (struct usb338x_ll_regs __iomem *)
+							(base + 0x0700);
+		dev->ll_lfps_regs = (struct usb338x_ll_lfps_regs __iomem *)
+							(base + 0x0748);
+		dev->ll_tsn_regs = (struct usb338x_ll_tsn_regs __iomem *)
+							(base + 0x077c);
+		dev->ll_chicken_reg = (struct usb338x_ll_chi_regs __iomem *)
+							(base + 0x079c);
+		dev->plregs = (struct usb338x_pl_regs __iomem *)
+							(base + 0x0800);
+		usbstat = readl(&dev->usb->usbstat);
+		dev->enhanced_mode = !!(usbstat & BIT(11));
+		dev->n_ep = (dev->enhanced_mode) ? 9 : 5;
+		/* put into initial config, link up all endpoints */
+		fsmvalue = get_idx_reg(dev->regs, SCRATCH) &
+					(0xf << DEFECT7374_FSM_FIELD);
+		/* See if firmware needs to set up for workaround: */
+		if (fsmvalue == DEFECT7374_FSM_SS_CONTROL_READ)
+			writel(0, &dev->usb->usbctl);
+	} else{
+		dev->enhanced_mode = 0;
+		dev->n_ep = 7;
+		/* put into initial config, link up all endpoints */
+		writel(0, &dev->usb->usbctl);
+	}
+
+	usb_reset(dev);
+	usb_reinit(dev);
+
+	/* irq setup after old hardware is cleaned up */
+	if (!pdev->irq) {
+		ep_err(dev, "No IRQ.  Check PCI setup!\n");
+		retval = -ENODEV;
+		goto done;
+	}
+
+	if (use_msi && (dev->quirks & PLX_SUPERSPEED))
+		if (pci_enable_msi(pdev))
+			ep_err(dev, "Failed to enable MSI mode\n");
+
+	if (request_irq(pdev->irq, net2280_irq, IRQF_SHARED,
+							driver_name, dev)) {
+		ep_err(dev, "request interrupt %d failed\n", pdev->irq);
+		retval = -EBUSY;
+		goto done;
+	}
+	dev->got_irq = 1;
+
+	/* DMA setup */
+	/* NOTE:  we know only the 32 LSBs of dma addresses may be nonzero */
+	dev->requests = pci_pool_create("requests", pdev,
+		sizeof(struct net2280_dma),
+		0 /* no alignment requirements */,
+		0 /* or page-crossing issues */);
+	if (!dev->requests) {
+		ep_dbg(dev, "can't get request pool\n");
+		retval = -ENOMEM;
+		goto done;
+	}
+	for (i = 1; i < 5; i++) {
+		struct net2280_dma	*td;
+
+		td = pci_pool_alloc(dev->requests, GFP_KERNEL,
+				&dev->ep[i].td_dma);
+		if (!td) {
+			ep_dbg(dev, "can't get dummy %d\n", i);
+			retval = -ENOMEM;
+			goto done;
+		}
+		td->dmacount = 0;	/* not VALID */
+		td->dmadesc = td->dmaaddr;
+		dev->ep[i].dummy = td;
+	}
+
+	/* enable lower-overhead pci memory bursts during DMA */
+	if (dev->quirks & PLX_LEGACY)
+		writel(BIT(DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE) |
+			/*
+			 * 256 write retries may not be enough...
+			   BIT(PCI_RETRY_ABORT_ENABLE) |
+			*/
+			BIT(DMA_READ_MULTIPLE_ENABLE) |
+			BIT(DMA_READ_LINE_ENABLE),
+			&dev->pci->pcimstctl);
+	/* erratum 0115 shouldn't appear: Linux inits PCI_LATENCY_TIMER */
+	pci_set_master(pdev);
+	pci_try_set_mwi(pdev);
+
+	/* ... also flushes any posted pci writes */
+	dev->chiprev = get_idx_reg(dev->regs, REG_CHIPREV) & 0xffff;
+
+	/* done */
+	ep_info(dev, "%s\n", driver_desc);
+	ep_info(dev, "irq %d, pci mem %p, chip rev %04x\n",
+			pdev->irq, base, dev->chiprev);
+	ep_info(dev, "version: " DRIVER_VERSION "; dma %s %s\n",
+		use_dma	? (use_dma_chaining ? "chaining" : "enabled")
+			: "disabled",
+		dev->enhanced_mode ? "enhanced mode" : "legacy mode");
+	retval = device_create_file(&pdev->dev, &dev_attr_registers);
+	if (retval)
+		goto done;
+
+	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+			gadget_release);
+	if (retval)
+		goto done;
+	return 0;
+
+done:
+	if (dev)
+		net2280_remove(pdev);
+	return retval;
+}
+
+/* make sure the board is quiescent; otherwise it will continue
+ * generating IRQs across the upcoming reboot.
+ */
+
+static void net2280_shutdown(struct pci_dev *pdev)
+{
+	struct net2280		*dev = pci_get_drvdata(pdev);
+
+	/* disable IRQs */
+	writel(0, &dev->regs->pciirqenb0);
+	writel(0, &dev->regs->pciirqenb1);
+
+	/* disable the pullup so the host will think we're gone */
+	writel(0, &dev->usb->usbctl);
+
+	/* Disable full-speed test mode */
+	if (dev->quirks & PLX_LEGACY)
+		writel(0, &dev->usb->xcvrdiag);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static const struct pci_device_id pci_ids[] = { {
+	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+	.class_mask =	~0,
+	.vendor =	PCI_VENDOR_ID_PLX_LEGACY,
+	.device =	0x2280,
+	.subvendor =	PCI_ANY_ID,
+	.subdevice =	PCI_ANY_ID,
+	.driver_data =	PLX_LEGACY | PLX_2280,
+	}, {
+	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+	.class_mask =	~0,
+	.vendor =	PCI_VENDOR_ID_PLX_LEGACY,
+	.device =	0x2282,
+	.subvendor =	PCI_ANY_ID,
+	.subdevice =	PCI_ANY_ID,
+	.driver_data =	PLX_LEGACY,
+	},
+	{
+	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+	.class_mask =	~0,
+	.vendor =	PCI_VENDOR_ID_PLX,
+	.device =	0x3380,
+	.subvendor =	PCI_ANY_ID,
+	.subdevice =	PCI_ANY_ID,
+	.driver_data =	PLX_SUPERSPEED,
+	 },
+	{
+	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+	.class_mask =	~0,
+	.vendor =	PCI_VENDOR_ID_PLX,
+	.device =	0x3382,
+	.subvendor =	PCI_ANY_ID,
+	.subdevice =	PCI_ANY_ID,
+	.driver_data =	PLX_SUPERSPEED,
+	 },
+{ /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE(pci, pci_ids);
+
+/* pci driver glue; this is a "new style" PCI driver module */
+static struct pci_driver net2280_pci_driver = {
+	.name =		(char *) driver_name,
+	.id_table =	pci_ids,
+
+	.probe =	net2280_probe,
+	.remove =	net2280_remove,
+	.shutdown =	net2280_shutdown,
+
+	/* FIXME add power management support */
+};
+
+module_pci_driver(net2280_pci_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/udc/net2280.h b/drivers/usb/gadget/udc/net2280.h
new file mode 100644
index 0000000..03f1524
--- /dev/null
+++ b/drivers/usb/gadget/udc/net2280.h
@@ -0,0 +1,403 @@
+/*
+ * NetChip 2280 high/full speed USB device controller.
+ * Unlike many such controllers, this one talks PCI.
+ */
+
+/*
+ * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
+ * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2014 Ricardo Ribalda - Qtechnology/AS
+ *
+ * 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.
+ */
+
+#include <linux/usb/net2280.h>
+#include <linux/usb/usb338x.h>
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	__KERNEL__
+
+/* indexed registers [11.10] are accessed indirectly
+ * caller must own the device lock.
+ */
+
+static inline u32 get_idx_reg(struct net2280_regs __iomem *regs, u32 index)
+{
+	writel(index, &regs->idxaddr);
+	/* NOTE:  synchs device/cpu memory views */
+	return readl(&regs->idxdata);
+}
+
+static inline void
+set_idx_reg(struct net2280_regs __iomem *regs, u32 index, u32 value)
+{
+	writel(index, &regs->idxaddr);
+	writel(value, &regs->idxdata);
+	/* posted, may not be visible yet */
+}
+
+#endif	/* __KERNEL__ */
+
+#define PCI_VENDOR_ID_PLX_LEGACY 0x17cc
+
+#define PLX_LEGACY		BIT(0)
+#define PLX_2280		BIT(1)
+#define PLX_SUPERSPEED		BIT(2)
+
+#define REG_DIAG		0x0
+#define     RETRY_COUNTER                                       16
+#define     FORCE_PCI_SERR                                      11
+#define     FORCE_PCI_INTERRUPT                                 10
+#define     FORCE_USB_INTERRUPT                                 9
+#define     FORCE_CPU_INTERRUPT                                 8
+#define     ILLEGAL_BYTE_ENABLES                                5
+#define     FAST_TIMES                                          4
+#define     FORCE_RECEIVE_ERROR                                 2
+#define     FORCE_TRANSMIT_CRC_ERROR                            0
+#define REG_FRAME		0x02	/* from last sof */
+#define REG_CHIPREV		0x03	/* in bcd */
+#define	REG_HS_NAK_RATE		0x0a	/* NAK per N uframes */
+
+#define	CHIPREV_1	0x0100
+#define	CHIPREV_1A	0x0110
+
+/* DEFECT 7374 */
+#define DEFECT_7374_NUMBEROF_MAX_WAIT_LOOPS         200
+#define DEFECT_7374_PROCESSOR_WAIT_TIME             10
+
+/* ep0 max packet size */
+#define EP0_SS_MAX_PACKET_SIZE  0x200
+#define EP0_HS_MAX_PACKET_SIZE  0x40
+#ifdef	__KERNEL__
+
+/*-------------------------------------------------------------------------*/
+
+/* [8.3] for scatter/gather i/o
+ * use struct net2280_dma_regs bitfields
+ */
+struct net2280_dma {
+	__le32		dmacount;
+	__le32		dmaaddr;		/* the buffer */
+	__le32		dmadesc;		/* next dma descriptor */
+	__le32		_reserved;
+} __aligned(16);
+
+/*-------------------------------------------------------------------------*/
+
+/* DRIVER DATA STRUCTURES and UTILITIES */
+
+struct net2280_ep {
+	struct usb_ep				ep;
+	struct net2280_ep_regs __iomem *cfg;
+	struct net2280_ep_regs			__iomem *regs;
+	struct net2280_dma_regs			__iomem *dma;
+	struct net2280_dma			*dummy;
+	struct usb338x_fifo_regs __iomem *fiforegs;
+	dma_addr_t				td_dma;	/* of dummy */
+	struct net2280				*dev;
+	unsigned long				irqs;
+	unsigned is_halt:1, dma_started:1;
+
+	/* analogous to a host-side qh */
+	struct list_head			queue;
+	const struct usb_endpoint_descriptor	*desc;
+	unsigned				num : 8,
+						fifo_size : 12,
+						in_fifo_validate : 1,
+						out_overflow : 1,
+						stopped : 1,
+						wedged : 1,
+						is_in : 1,
+						is_iso : 1,
+						responded : 1;
+};
+
+static inline void allow_status(struct net2280_ep *ep)
+{
+	/* ep0 only */
+	writel(BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE) |
+		BIT(CLEAR_NAK_OUT_PACKETS) |
+		BIT(CLEAR_NAK_OUT_PACKETS_MODE),
+		&ep->regs->ep_rsp);
+	ep->stopped = 1;
+}
+
+static void allow_status_338x(struct net2280_ep *ep)
+{
+	/*
+	 * Control Status Phase Handshake was set by the chip when the setup
+	 * packet arrived. While set, the chip automatically NAKs the host's
+	 * Status Phase tokens.
+	 */
+	writel(BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE), &ep->regs->ep_rsp);
+
+	ep->stopped = 1;
+
+	/* TD 9.9 Halt Endpoint test.  TD 9.22 set feature test. */
+	ep->responded = 0;
+}
+
+struct net2280_request {
+	struct usb_request		req;
+	struct net2280_dma		*td;
+	dma_addr_t			td_dma;
+	struct list_head		queue;
+	unsigned			mapped : 1,
+					valid : 1;
+};
+
+struct net2280 {
+	/* each pci device provides one gadget, several endpoints */
+	struct usb_gadget		gadget;
+	spinlock_t			lock;
+	struct net2280_ep		ep[9];
+	struct usb_gadget_driver	*driver;
+	unsigned			enabled : 1,
+					protocol_stall : 1,
+					softconnect : 1,
+					got_irq : 1,
+					region:1,
+					u1_enable:1,
+					u2_enable:1,
+					ltm_enable:1,
+					wakeup_enable:1,
+					selfpowered:1,
+					addressed_state:1;
+	u16				chiprev;
+	int enhanced_mode;
+	int n_ep;
+	kernel_ulong_t			quirks;
+
+
+	/* pci state used to access those endpoints */
+	struct pci_dev			*pdev;
+	struct net2280_regs		__iomem *regs;
+	struct net2280_usb_regs		__iomem *usb;
+	struct usb338x_usb_ext_regs	__iomem *usb_ext;
+	struct net2280_pci_regs		__iomem *pci;
+	struct net2280_dma_regs		__iomem *dma;
+	struct net2280_dep_regs		__iomem *dep;
+	struct net2280_ep_regs		__iomem *epregs;
+	struct usb338x_fifo_regs	__iomem *fiforegs;
+	struct usb338x_ll_regs		__iomem *llregs;
+	struct usb338x_ll_lfps_regs	__iomem *ll_lfps_regs;
+	struct usb338x_ll_tsn_regs	__iomem *ll_tsn_regs;
+	struct usb338x_ll_chi_regs	__iomem *ll_chicken_reg;
+	struct usb338x_pl_regs		__iomem *plregs;
+
+	struct pci_pool			*requests;
+	/* statistics...*/
+};
+
+static inline void set_halt(struct net2280_ep *ep)
+{
+	/* ep0 and bulk/intr endpoints */
+	writel(BIT(CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE) |
+		/* set NAK_OUT for erratum 0114 */
+		((ep->dev->chiprev == CHIPREV_1) << SET_NAK_OUT_PACKETS) |
+		BIT(SET_ENDPOINT_HALT),
+		&ep->regs->ep_rsp);
+}
+
+static inline void clear_halt(struct net2280_ep *ep)
+{
+	/* ep0 and bulk/intr endpoints */
+	writel(BIT(CLEAR_ENDPOINT_HALT) |
+		BIT(CLEAR_ENDPOINT_TOGGLE) |
+		    /*
+		     * unless the gadget driver left a short packet in the
+		     * fifo, this reverses the erratum 0114 workaround.
+		     */
+		((ep->dev->chiprev == CHIPREV_1) << CLEAR_NAK_OUT_PACKETS),
+		&ep->regs->ep_rsp);
+}
+
+/*
+ * FSM value for Defect 7374 (U1U2 Test) is managed in
+ * chip's SCRATCH register:
+ */
+#define DEFECT7374_FSM_FIELD    28
+
+/* Waiting for Control Read:
+ *  - A transition to this state indicates a fresh USB connection,
+ *    before the first Setup Packet. The connection speed is not
+ *    known. Firmware is waiting for the first Control Read.
+ *  - Starting state: This state can be thought of as the FSM's typical
+ *    starting state.
+ *  - Tip: Upon the first SS Control Read the FSM never
+ *    returns to this state.
+ */
+#define DEFECT7374_FSM_WAITING_FOR_CONTROL_READ BIT(DEFECT7374_FSM_FIELD)
+
+/* Non-SS Control Read:
+ *  - A transition to this state indicates detection of the first HS
+ *    or FS Control Read.
+ *  - Tip: Upon the first SS Control Read the FSM never
+ *    returns to this state.
+ */
+#define	DEFECT7374_FSM_NON_SS_CONTROL_READ (2 << DEFECT7374_FSM_FIELD)
+
+/* SS Control Read:
+ *  - A transition to this state indicates detection of the
+ *    first SS Control Read.
+ *  - This state indicates workaround completion. Workarounds no longer
+ *    need to be applied (as long as the chip remains powered up).
+ *  - Tip: Once in this state the FSM state does not change (until
+ *    the chip's power is lost and restored).
+ *  - This can be thought of as the final state of the FSM;
+ *    the FSM 'locks-up' in this state until the chip loses power.
+ */
+#define DEFECT7374_FSM_SS_CONTROL_READ (3 << DEFECT7374_FSM_FIELD)
+
+#ifdef USE_RDK_LEDS
+
+static inline void net2280_led_init(struct net2280 *dev)
+{
+	/* LED3 (green) is on during USB activity. note erratum 0113. */
+	writel(BIT(GPIO3_LED_SELECT) |
+		BIT(GPIO3_OUTPUT_ENABLE) |
+		BIT(GPIO2_OUTPUT_ENABLE) |
+		BIT(GPIO1_OUTPUT_ENABLE) |
+		BIT(GPIO0_OUTPUT_ENABLE),
+		&dev->regs->gpioctl);
+}
+
+/* indicate speed with bi-color LED 0/1 */
+static inline
+void net2280_led_speed(struct net2280 *dev, enum usb_device_speed speed)
+{
+	u32	val = readl(&dev->regs->gpioctl);
+	switch (speed) {
+	case USB_SPEED_SUPER:		/* green + red */
+		val |= BIT(GPIO0_DATA) | BIT(GPIO1_DATA);
+		break;
+	case USB_SPEED_HIGH:		/* green */
+		val &= ~BIT(GPIO0_DATA);
+		val |= BIT(GPIO1_DATA);
+		break;
+	case USB_SPEED_FULL:		/* red */
+		val &= ~BIT(GPIO1_DATA);
+		val |= BIT(GPIO0_DATA);
+		break;
+	default:			/* (off/black) */
+		val &= ~(BIT(GPIO1_DATA) | BIT(GPIO0_DATA));
+		break;
+	}
+	writel(val, &dev->regs->gpioctl);
+}
+
+/* indicate power with LED 2 */
+static inline void net2280_led_active(struct net2280 *dev, int is_active)
+{
+	u32	val = readl(&dev->regs->gpioctl);
+
+	/* FIXME this LED never seems to turn on.*/
+	if (is_active)
+		val |= GPIO2_DATA;
+	else
+		val &= ~GPIO2_DATA;
+	writel(val, &dev->regs->gpioctl);
+}
+
+static inline void net2280_led_shutdown(struct net2280 *dev)
+{
+	/* turn off all four GPIO*_DATA bits */
+	writel(readl(&dev->regs->gpioctl) & ~0x0f,
+			&dev->regs->gpioctl);
+}
+
+#else
+
+#define net2280_led_init(dev)		do { } while (0)
+#define net2280_led_speed(dev, speed)	do { } while (0)
+#define net2280_led_shutdown(dev)	do { } while (0)
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#define ep_dbg(ndev, fmt, args...) \
+	dev_dbg((&((ndev)->pdev->dev)), fmt, ##args)
+
+#define ep_vdbg(ndev, fmt, args...) \
+	dev_vdbg((&((ndev)->pdev->dev)), fmt, ##args)
+
+#define ep_info(ndev, fmt, args...) \
+	dev_info((&((ndev)->pdev->dev)), fmt, ##args)
+
+#define ep_warn(ndev, fmt, args...) \
+	dev_warn((&((ndev)->pdev->dev)), fmt, ##args)
+
+#define ep_err(ndev, fmt, args...) \
+	dev_err((&((ndev)->pdev->dev)), fmt, ##args)
+
+/*-------------------------------------------------------------------------*/
+
+static inline void set_fifo_bytecount(struct net2280_ep *ep, unsigned count)
+{
+	if (ep->dev->pdev->vendor == 0x17cc)
+		writeb(count, 2 + (u8 __iomem *) &ep->regs->ep_cfg);
+	else{
+		u32 tmp = readl(&ep->cfg->ep_cfg) &
+					(~(0x07 << EP_FIFO_BYTE_COUNT));
+		writel(tmp | (count << EP_FIFO_BYTE_COUNT), &ep->cfg->ep_cfg);
+	}
+}
+
+static inline void start_out_naking(struct net2280_ep *ep)
+{
+	/* NOTE:  hardware races lurk here, and PING protocol issues */
+	writel(BIT(SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
+	/* synch with device */
+	readl(&ep->regs->ep_rsp);
+}
+
+#ifdef DEBUG
+static inline void assert_out_naking(struct net2280_ep *ep, const char *where)
+{
+	u32	tmp = readl(&ep->regs->ep_stat);
+
+	if ((tmp & BIT(NAK_OUT_PACKETS)) == 0) {
+		ep_dbg(ep->dev, "%s %s %08x !NAK\n",
+				ep->ep.name, where, tmp);
+		writel(BIT(SET_NAK_OUT_PACKETS),
+			&ep->regs->ep_rsp);
+	}
+}
+#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep, __func__)
+#else
+#define ASSERT_OUT_NAKING(ep) do {} while (0)
+#endif
+
+static inline void stop_out_naking(struct net2280_ep *ep)
+{
+	u32	tmp;
+
+	tmp = readl(&ep->regs->ep_stat);
+	if ((tmp & BIT(NAK_OUT_PACKETS)) != 0)
+		writel(BIT(CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
+}
+
+
+static inline void set_max_speed(struct net2280_ep *ep, u32 max)
+{
+	u32 reg;
+	static const u32 ep_enhanced[9] = { 0x10, 0x60, 0x30, 0x80,
+					  0x50, 0x20, 0x70, 0x40, 0x90 };
+
+	if (ep->dev->enhanced_mode)
+		reg = ep_enhanced[ep->num];
+	else{
+		reg = (ep->num + 1) * 0x10;
+		if (ep->dev->gadget.speed != USB_SPEED_HIGH)
+			reg += 1;
+	}
+
+	set_idx_reg(ep->dev->regs, reg, max);
+}
+
+#endif	/* __KERNEL__ */
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c
similarity index 99%
rename from drivers/usb/gadget/omap_udc.c
rename to drivers/usb/gadget/udc/omap_udc.c
index 2ae4f6d..e731373 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/udc/omap_udc.c
@@ -2079,10 +2079,7 @@
 						&udc->gadget);
 		if (status < 0) {
 			ERR("can't bind to transceiver\n");
-			if (driver->unbind) {
-				driver->unbind(&udc->gadget);
-				udc->driver = NULL;
-			}
+			udc->driver = NULL;
 			goto done;
 		}
 	} else {
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/udc/omap_udc.h
similarity index 100%
rename from drivers/usb/gadget/omap_udc.h
rename to drivers/usb/gadget/udc/omap_udc.h
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c
similarity index 100%
rename from drivers/usb/gadget/pch_udc.c
rename to drivers/usb/gadget/udc/pch_udc.c
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c
similarity index 97%
rename from drivers/usb/gadget/pxa25x_udc.c
rename to drivers/usb/gadget/udc/pxa25x_udc.c
index 9984437..251e4d5 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/udc/pxa25x_udc.c
@@ -16,6 +16,7 @@
 /* #define VERBOSE_DEBUG */
 
 #include <linux/device.h>
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
@@ -40,7 +41,6 @@
 
 #include <asm/byteorder.h>
 #include <asm/dma.h>
-#include <asm/gpio.h>
 #include <asm/mach-types.h>
 #include <asm/unaligned.h>
 
@@ -2105,11 +2105,9 @@
 	if (irq < 0)
 		return -ENODEV;
 
-	dev->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(dev->clk)) {
-		retval = PTR_ERR(dev->clk);
-		goto err_clk;
-	}
+	dev->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk))
+		return PTR_ERR(dev->clk);
 
 	pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
 		dev->has_cfr ? "" : " (!cfr)",
@@ -2120,15 +2118,16 @@
 	dev->dev = &pdev->dev;
 	dev->mach = dev_get_platdata(&pdev->dev);
 
-	dev->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+	dev->transceiver = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 
 	if (gpio_is_valid(dev->mach->gpio_pullup)) {
-		if ((retval = gpio_request(dev->mach->gpio_pullup,
-				"pca25x_udc GPIO PULLUP"))) {
+		retval = devm_gpio_request(&pdev->dev, dev->mach->gpio_pullup,
+					   "pca25x_udc GPIO PULLUP");
+		if (retval) {
 			dev_dbg(&pdev->dev,
 				"can't get pullup gpio %d, err: %d\n",
 				dev->mach->gpio_pullup, retval);
-			goto err_gpio_pullup;
+			goto err;
 		}
 		gpio_direction_output(dev->mach->gpio_pullup, 0);
 	}
@@ -2146,30 +2145,32 @@
 	dev->vbus = 0;
 
 	/* irq setup after old hardware state is cleaned up */
-	retval = request_irq(irq, pxa25x_udc_irq,
-			0, driver_name, dev);
+	retval = devm_request_irq(&pdev->dev, irq, pxa25x_udc_irq, 0,
+				  driver_name, dev);
 	if (retval != 0) {
 		pr_err("%s: can't get irq %d, err %d\n",
 			driver_name, irq, retval);
-		goto err_irq1;
+		goto err;
 	}
 	dev->got_irq = 1;
 
 #ifdef CONFIG_ARCH_LUBBOCK
 	if (machine_is_lubbock()) {
-		retval = request_irq(LUBBOCK_USB_DISC_IRQ, lubbock_vbus_irq,
-				     0, driver_name, dev);
+		retval = devm_request_irq(&pdev->dev, LUBBOCK_USB_DISC_IRQ,
+					  lubbock_vbus_irq, 0, driver_name,
+					  dev);
 		if (retval != 0) {
 			pr_err("%s: can't get irq %i, err %d\n",
 				driver_name, LUBBOCK_USB_DISC_IRQ, retval);
-			goto err_irq_lub;
+			goto err;
 		}
-		retval = request_irq(LUBBOCK_USB_IRQ, lubbock_vbus_irq,
-				     0, driver_name, dev);
+		retval = devm_request_irq(&pdev->dev, LUBBOCK_USB_IRQ,
+					  lubbock_vbus_irq, 0, driver_name,
+					  dev);
 		if (retval != 0) {
 			pr_err("%s: can't get irq %i, err %d\n",
 				driver_name, LUBBOCK_USB_IRQ, retval);
-			goto lubbock_fail0;
+			goto err;
 		}
 	} else
 #endif
@@ -2180,22 +2181,9 @@
 		return retval;
 
 	remove_debug_files(dev);
-#ifdef	CONFIG_ARCH_LUBBOCK
-lubbock_fail0:
-	free_irq(LUBBOCK_USB_DISC_IRQ, dev);
- err_irq_lub:
-	free_irq(irq, dev);
-#endif
- err_irq1:
-	if (gpio_is_valid(dev->mach->gpio_pullup))
-		gpio_free(dev->mach->gpio_pullup);
- err_gpio_pullup:
-	if (!IS_ERR_OR_NULL(dev->transceiver)) {
-		usb_put_phy(dev->transceiver);
+ err:
+	if (!IS_ERR_OR_NULL(dev->transceiver))
 		dev->transceiver = NULL;
-	}
-	clk_put(dev->clk);
- err_clk:
 	return retval;
 }
 
@@ -2217,25 +2205,8 @@
 
 	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 (gpio_is_valid(dev->mach->gpio_pullup))
-		gpio_free(dev->mach->gpio_pullup);
-
-	clk_put(dev->clk);
-
-	if (!IS_ERR_OR_NULL(dev->transceiver)) {
-		usb_put_phy(dev->transceiver);
+	if (!IS_ERR_OR_NULL(dev->transceiver))
 		dev->transceiver = NULL;
-	}
 
 	the_controller = NULL;
 	return 0;
diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/udc/pxa25x_udc.h
similarity index 100%
rename from drivers/usb/gadget/pxa25x_udc.h
rename to drivers/usb/gadget/udc/pxa25x_udc.h
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c
similarity index 99%
rename from drivers/usb/gadget/pxa27x_udc.c
rename to drivers/usb/gadget/udc/pxa27x_udc.c
index cdf4d67..597d39f89 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/udc/pxa27x_udc.c
@@ -2446,6 +2446,9 @@
 		retval = PTR_ERR(udc->clk);
 		goto err_clk;
 	}
+	retval = clk_prepare(udc->clk);
+	if (retval)
+		goto err_clk_prepare;
 
 	retval = -ENOMEM;
 	udc->regs = ioremap(regs->start, resource_size(regs));
@@ -2483,6 +2486,8 @@
 err_irq:
 	iounmap(udc->regs);
 err_map:
+	clk_unprepare(udc->clk);
+err_clk_prepare:
 	clk_put(udc->clk);
 	udc->clk = NULL;
 err_clk:
@@ -2509,6 +2514,7 @@
 
 	udc->transceiver = NULL;
 	the_controller = NULL;
+	clk_unprepare(udc->clk);
 	clk_put(udc->clk);
 	iounmap(udc->regs);
 
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/udc/pxa27x_udc.h
similarity index 100%
rename from drivers/usb/gadget/pxa27x_udc.h
rename to drivers/usb/gadget/udc/pxa27x_udc.h
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c
similarity index 96%
rename from drivers/usb/gadget/r8a66597-udc.c
rename to drivers/usb/gadget/udc/r8a66597-udc.c
index b698a49..4600842 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/udc/r8a66597-udc.c
@@ -1826,18 +1826,12 @@
 
 	usb_del_gadget_udc(&r8a66597->gadget);
 	del_timer_sync(&r8a66597->timer);
-	iounmap(r8a66597->reg);
-	if (r8a66597->pdata->sudmac)
-		iounmap(r8a66597->sudmac_reg);
-	free_irq(platform_get_irq(pdev, 0), r8a66597);
 	r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
 
 	if (r8a66597->pdata->on_chip) {
 		clk_disable_unprepare(r8a66597->clk);
-		clk_put(r8a66597->clk);
 	}
 
-	kfree(r8a66597);
 	return 0;
 }
 
@@ -1845,28 +1839,24 @@
 {
 }
 
-static int __init r8a66597_sudmac_ioremap(struct r8a66597 *r8a66597,
+static int r8a66597_sudmac_ioremap(struct r8a66597 *r8a66597,
 					  struct platform_device *pdev)
 {
 	struct resource *res;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sudmac");
-	if (!res) {
-		dev_err(&pdev->dev, "platform_get_resource error(sudmac).\n");
-		return -ENODEV;
-	}
-
-	r8a66597->sudmac_reg = ioremap(res->start, resource_size(res));
-	if (r8a66597->sudmac_reg == NULL) {
+	r8a66597->sudmac_reg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(r8a66597->sudmac_reg)) {
 		dev_err(&pdev->dev, "ioremap error(sudmac).\n");
-		return -ENOMEM;
+		return PTR_ERR(r8a66597->sudmac_reg);
 	}
 
 	return 0;
 }
 
-static int __init r8a66597_probe(struct platform_device *pdev)
+static int r8a66597_probe(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
 	char clk_name[8];
 	struct resource *res, *ires;
 	int irq;
@@ -1877,39 +1867,27 @@
 	unsigned long irq_trigger;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -ENODEV;
-		dev_err(&pdev->dev, "platform_get_resource error.\n");
-		goto clean_up;
-	}
+	reg = devm_ioremap_resource(&pdev->dev, res);
+	if (!reg)
+		return -ENODEV;
 
 	ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	irq = ires->start;
 	irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
 
 	if (irq < 0) {
-		ret = -ENODEV;
-		dev_err(&pdev->dev, "platform_get_irq error.\n");
-		goto clean_up;
-	}
-
-	reg = ioremap(res->start, resource_size(res));
-	if (reg == NULL) {
-		ret = -ENOMEM;
-		dev_err(&pdev->dev, "ioremap error.\n");
-		goto clean_up;
+		dev_err(dev, "platform_get_irq error.\n");
+		return -ENODEV;
 	}
 
 	/* initialize ucd */
-	r8a66597 = kzalloc(sizeof(struct r8a66597), GFP_KERNEL);
-	if (r8a66597 == NULL) {
-		ret = -ENOMEM;
-		goto clean_up;
-	}
+	r8a66597 = devm_kzalloc(dev, sizeof(struct r8a66597), GFP_KERNEL);
+	if (r8a66597 == NULL)
+		return -ENOMEM;
 
 	spin_lock_init(&r8a66597->lock);
 	platform_set_drvdata(pdev, r8a66597);
-	r8a66597->pdata = dev_get_platdata(&pdev->dev);
+	r8a66597->pdata = dev_get_platdata(dev);
 	r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 
 	r8a66597->gadget.ops = &r8a66597_gadget_ops;
@@ -1923,12 +1901,10 @@
 
 	if (r8a66597->pdata->on_chip) {
 		snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id);
-		r8a66597->clk = clk_get(&pdev->dev, clk_name);
+		r8a66597->clk = devm_clk_get(dev, clk_name);
 		if (IS_ERR(r8a66597->clk)) {
-			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
-				clk_name);
-			ret = PTR_ERR(r8a66597->clk);
-			goto clean_up;
+			dev_err(dev, "cannot get clock \"%s\"\n", clk_name);
+			return PTR_ERR(r8a66597->clk);
 		}
 		clk_prepare_enable(r8a66597->clk);
 	}
@@ -1941,10 +1917,10 @@
 
 	disable_controller(r8a66597); /* make sure controller is disabled */
 
-	ret = request_irq(irq, r8a66597_irq, IRQF_SHARED,
-			udc_name, r8a66597);
+	ret = devm_request_irq(dev, irq, r8a66597_irq, IRQF_SHARED,
+			       udc_name, r8a66597);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "request_irq error (%d)\n", ret);
+		dev_err(dev, "request_irq error (%d)\n", ret);
 		goto clean_up2;
 	}
 
@@ -1978,37 +1954,25 @@
 							GFP_KERNEL);
 	if (r8a66597->ep0_req == NULL) {
 		ret = -ENOMEM;
-		goto clean_up3;
+		goto clean_up2;
 	}
 	r8a66597->ep0_req->complete = nop_completion;
 
-	ret = usb_add_gadget_udc(&pdev->dev, &r8a66597->gadget);
+	ret = usb_add_gadget_udc(dev, &r8a66597->gadget);
 	if (ret)
 		goto err_add_udc;
 
-	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
+	dev_info(dev, "version %s\n", DRIVER_VERSION);
 	return 0;
 
 err_add_udc:
 	r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
-clean_up3:
-	free_irq(irq, r8a66597);
 clean_up2:
-	if (r8a66597->pdata->on_chip) {
+	if (r8a66597->pdata->on_chip)
 		clk_disable_unprepare(r8a66597->clk);
-		clk_put(r8a66597->clk);
-	}
-clean_up:
-	if (r8a66597) {
-		if (r8a66597->sudmac_reg)
-			iounmap(r8a66597->sudmac_reg);
-		if (r8a66597->ep0_req)
-			r8a66597_free_request(&r8a66597->ep[0].ep,
-						r8a66597->ep0_req);
-		kfree(r8a66597);
-	}
-	if (reg)
-		iounmap(reg);
+
+	if (r8a66597->ep0_req)
+		r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
 
 	return ret;
 }
diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/udc/r8a66597-udc.h
similarity index 100%
rename from drivers/usb/gadget/r8a66597-udc.h
rename to drivers/usb/gadget/udc/r8a66597-udc.h
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/udc/s3c-hsudc.c
similarity index 100%
rename from drivers/usb/gadget/s3c-hsudc.c
rename to drivers/usb/gadget/udc/s3c-hsudc.c
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c
similarity index 99%
rename from drivers/usb/gadget/s3c2410_udc.c
rename to drivers/usb/gadget/udc/s3c2410_udc.c
index 7987aa0..357b58e 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/udc/s3c2410_udc.c
@@ -1788,7 +1788,7 @@
 		return PTR_ERR(usb_bus_clock);
 	}
 
-	clk_enable(usb_bus_clock);
+	clk_prepare_enable(usb_bus_clock);
 
 	udc_clock = clk_get(NULL, "usb-device");
 	if (IS_ERR(udc_clock)) {
@@ -1796,7 +1796,7 @@
 		return PTR_ERR(udc_clock);
 	}
 
-	clk_enable(udc_clock);
+	clk_prepare_enable(udc_clock);
 
 	mdelay(10);
 
@@ -1952,13 +1952,13 @@
 	release_mem_region(rsrc_start, rsrc_len);
 
 	if (!IS_ERR(udc_clock) && udc_clock != NULL) {
-		clk_disable(udc_clock);
+		clk_disable_unprepare(udc_clock);
 		clk_put(udc_clock);
 		udc_clock = NULL;
 	}
 
 	if (!IS_ERR(usb_bus_clock) && usb_bus_clock != NULL) {
-		clk_disable(usb_bus_clock);
+		clk_disable_unprepare(usb_bus_clock);
 		clk_put(usb_bus_clock);
 		usb_bus_clock = NULL;
 	}
diff --git a/drivers/usb/gadget/s3c2410_udc.h b/drivers/usb/gadget/udc/s3c2410_udc.h
similarity index 100%
rename from drivers/usb/gadget/s3c2410_udc.h
rename to drivers/usb/gadget/udc/s3c2410_udc.h
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
similarity index 100%
rename from drivers/usb/gadget/udc-core.c
rename to drivers/usb/gadget/udc/udc-core.c
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index d40d5f0..ac4422b 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -455,7 +455,7 @@
 
 	int				ret = -ENOMEM;
 
-	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
 		dev_err(&pdev->dev, "failed to allocate glue context\n");
 		goto err0;
@@ -464,7 +464,7 @@
 	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 	if (!musb) {
 		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err1;
+		goto err0;
 	}
 
 	musb->dev.parent		= &pdev->dev;
@@ -478,7 +478,7 @@
 
 	glue->phy = usb_phy_generic_register();
 	if (IS_ERR(glue->phy))
-		goto err2;
+		goto err1;
 	platform_set_drvdata(pdev, glue);
 
 	memset(musb_resources, 0x00, sizeof(*musb_resources) *
@@ -498,31 +498,28 @@
 			ARRAY_SIZE(musb_resources));
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add resources\n");
-		goto err3;
+		goto err2;
 	}
 
 	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add platform_data\n");
-		goto err3;
+		goto err2;
 	}
 
 	ret = platform_device_add(musb);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register musb device\n");
-		goto err3;
+		goto err2;
 	}
 
 	return 0;
 
-err3:
+err2:
 	usb_phy_generic_unregister(glue->phy);
 
-err2:
-	platform_device_put(musb);
-
 err1:
-	kfree(glue);
+	platform_device_put(musb);
 
 err0:
 	return ret;
@@ -534,7 +531,6 @@
 
 	platform_device_unregister(glue->musb);
 	usb_phy_generic_unregister(glue->phy);
-	kfree(glue);
 
 	return 0;
 }
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index de8492b..110b784 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -519,23 +519,23 @@
 
 	int				ret = -ENOMEM;
 
-	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
 		dev_err(&pdev->dev, "failed to allocate glue context\n");
 		goto err0;
 	}
 
-	clk = clk_get(&pdev->dev, "usb");
+	clk = devm_clk_get(&pdev->dev, "usb");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clock\n");
 		ret = PTR_ERR(clk);
-		goto err3;
+		goto err0;
 	}
 
 	ret = clk_enable(clk);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to enable clock\n");
-		goto err4;
+		goto err0;
 	}
 
 	glue->dev			= &pdev->dev;
@@ -579,20 +579,14 @@
 	if (IS_ERR(musb)) {
 		ret = PTR_ERR(musb);
 		dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
-		goto err5;
+		goto err1;
 	}
 
 	return 0;
 
-err5:
+err1:
 	clk_disable(clk);
 
-err4:
-	clk_put(clk);
-
-err3:
-	kfree(glue);
-
 err0:
 	return ret;
 }
@@ -604,8 +598,6 @@
 	platform_device_unregister(glue->musb);
 	usb_phy_generic_unregister();
 	clk_disable(glue->clk);
-	clk_put(glue->clk);
-	kfree(glue);
 
 	return 0;
 }
diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c
index 5f30537..d118729 100644
--- a/drivers/usb/musb/jz4740.c
+++ b/drivers/usb/musb/jz4740.c
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/usb/usb_phy_generic.h>
 
 #include "musb_core.h"
 
@@ -80,6 +81,7 @@
 
 static int jz4740_musb_init(struct musb *musb)
 {
+	usb_phy_generic_register();
 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (!musb->xceiv) {
 		pr_err("HS UDC: no transceiver configured\n");
@@ -182,6 +184,7 @@
 	struct jz4740_glue	*glue = platform_get_drvdata(pdev);
 
 	platform_device_unregister(glue->musb);
+	usb_phy_generic_unregister(pdev);
 	clk_disable_unprepare(glue->clk);
 
 	return 0;
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index eff3c5c..b841ee0 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -850,7 +850,8 @@
 
 	/* handle babble condition */
 	if (int_usb & MUSB_INTR_BABBLE && is_host_active(musb))
-		schedule_work(&musb->recover_work);
+		schedule_delayed_work(&musb->recover_work,
+				      msecs_to_jiffies(100));
 
 #if 0
 /* REVISIT ... this would be for multiplexing periodic endpoints, or
@@ -1517,7 +1518,7 @@
 	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
 	dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n",
-		(devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
+		is_host_active(musb) ? "host" : "peripheral",
 		musb->int_usb, musb->int_tx, musb->int_rx);
 
 	/* the core can interrupt us for multiple reasons; docs have
@@ -1531,7 +1532,7 @@
 
 	/* handle endpoint 0 first */
 	if (musb->int_tx & 1) {
-		if (devctl & MUSB_DEVCTL_HM)
+		if (is_host_active(musb))
 			retval |= musb_h_ep0_irq(musb);
 		else
 			retval |= musb_g_ep0_irq(musb);
@@ -1545,7 +1546,7 @@
 			/* musb_ep_select(musb->mregs, ep_num); */
 			/* REVISIT just retval = ep->rx_irq(...) */
 			retval = IRQ_HANDLED;
-			if (devctl & MUSB_DEVCTL_HM)
+			if (is_host_active(musb))
 				musb_host_rx(musb, ep_num);
 			else
 				musb_g_rx(musb, ep_num);
@@ -1563,7 +1564,7 @@
 			/* musb_ep_select(musb->mregs, ep_num); */
 			/* REVISIT just retval |= ep->tx_irq(...) */
 			retval = IRQ_HANDLED;
-			if (devctl & MUSB_DEVCTL_HM)
+			if (is_host_active(musb))
 				musb_host_tx(musb, ep_num);
 			else
 				musb_g_tx(musb, ep_num);
@@ -1585,15 +1586,13 @@
 
 void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit)
 {
-	u8	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
-
 	/* called with controller lock already held */
 
 	if (!epnum) {
 #ifndef CONFIG_USB_TUSB_OMAP_DMA
 		if (!is_cppi_enabled()) {
 			/* endpoint 0 */
-			if (devctl & MUSB_DEVCTL_HM)
+			if (is_host_active(musb))
 				musb_h_ep0_irq(musb);
 			else
 				musb_g_ep0_irq(musb);
@@ -1602,13 +1601,13 @@
 	} else {
 		/* endpoints 1..15 */
 		if (transmit) {
-			if (devctl & MUSB_DEVCTL_HM)
+			if (is_host_active(musb))
 				musb_host_tx(musb, epnum);
 			else
 				musb_g_tx(musb, epnum);
 		} else {
 			/* receive */
-			if (devctl & MUSB_DEVCTL_HM)
+			if (is_host_active(musb))
 				musb_host_rx(musb, epnum);
 			else
 				musb_g_rx(musb, epnum);
@@ -1753,20 +1752,22 @@
 /* Recover from babble interrupt conditions */
 static void musb_recover_work(struct work_struct *data)
 {
-	struct musb *musb = container_of(data, struct musb, recover_work);
-	int status;
+	struct musb *musb = container_of(data, struct musb, recover_work.work);
+	int status, ret;
 
-	musb_platform_reset(musb);
+	ret  = musb_platform_reset(musb);
+	if (ret)
+		return;
 
 	usb_phy_vbus_off(musb->xceiv);
-	udelay(100);
+	usleep_range(100, 200);
 
 	usb_phy_vbus_on(musb->xceiv);
-	udelay(100);
+	usleep_range(100, 200);
 
 	/*
-	 * When a babble condition occurs, the musb controller removes the
-	 * session bit and the endpoint config is lost.
+	 * When a babble condition occurs, the musb controller
+	 * removes the session bit and the endpoint config is lost.
 	 */
 	if (musb->dyn_fifo)
 		status = ep_config_from_table(musb);
@@ -1945,7 +1946,7 @@
 
 	/* Init IRQ workqueue before request_irq */
 	INIT_WORK(&musb->irq_work, musb_irq_work);
-	INIT_WORK(&musb->recover_work, musb_recover_work);
+	INIT_DELAYED_WORK(&musb->recover_work, musb_recover_work);
 	INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset);
 	INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume);
 
@@ -2041,7 +2042,7 @@
 
 fail3:
 	cancel_work_sync(&musb->irq_work);
-	cancel_work_sync(&musb->recover_work);
+	cancel_delayed_work_sync(&musb->recover_work);
 	cancel_delayed_work_sync(&musb->finish_resume_work);
 	cancel_delayed_work_sync(&musb->deassert_reset_work);
 	if (musb->dma_controller)
@@ -2107,7 +2108,7 @@
 		dma_controller_destroy(musb->dma_controller);
 
 	cancel_work_sync(&musb->irq_work);
-	cancel_work_sync(&musb->recover_work);
+	cancel_delayed_work_sync(&musb->recover_work);
 	cancel_delayed_work_sync(&musb->finish_resume_work);
 	cancel_delayed_work_sync(&musb->deassert_reset_work);
 	musb_free(musb);
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index d155a15..414e57a 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -192,7 +192,7 @@
 
 	int	(*set_mode)(struct musb *musb, u8 mode);
 	void	(*try_idle)(struct musb *musb, unsigned long timeout);
-	void	(*reset)(struct musb *musb);
+	int	(*reset)(struct musb *musb);
 
 	int	(*vbus_status)(struct musb *musb);
 	void	(*set_vbus)(struct musb *musb, int on);
@@ -297,7 +297,7 @@
 
 	irqreturn_t		(*isr)(int, void *);
 	struct work_struct	irq_work;
-	struct work_struct	recover_work;
+	struct delayed_work	recover_work;
 	struct delayed_work	deassert_reset_work;
 	struct delayed_work	finish_resume_work;
 	u16			hwvers;
@@ -555,10 +555,12 @@
 		musb->ops->try_idle(musb, timeout);
 }
 
-static inline void musb_platform_reset(struct musb *musb)
+static inline int  musb_platform_reset(struct musb *musb)
 {
-	if (musb->ops->reset)
-		musb->ops->reset(musb);
+	if (!musb->ops->reset)
+		return -EINVAL;
+
+	return musb->ops->reset(musb);
 }
 
 static inline int musb_platform_get_vbus_status(struct musb *musb)
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c
index 5341bb2..47ae645 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -39,7 +39,6 @@
 	u32 transferred;
 	u32 packet_sz;
 	struct list_head tx_check;
-	struct work_struct dma_completion;
 };
 
 #define MUSB_DMA_NUM_CHANNELS 15
@@ -74,15 +73,18 @@
 
 static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
 {
+	struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+	struct musb *musb = hw_ep->musb;
 	u16 csr;
 	u8 toggle;
 
 	if (cppi41_channel->is_tx)
 		return;
-	if (!is_host_active(cppi41_channel->controller->musb))
+	if (!is_host_active(musb))
 		return;
 
-	csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR);
+	musb_ep_select(musb->mregs, hw_ep->epnum);
+	csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
 	toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
 
 	/*
@@ -107,24 +109,13 @@
 	void __iomem	*epio = musb->endpoints[epnum].regs;
 	u16		csr;
 
+	musb_ep_select(musb->mregs, hw_ep->epnum);
 	csr = musb_readw(epio, MUSB_TXCSR);
 	if (csr & MUSB_TXCSR_TXPKTRDY)
 		return false;
 	return true;
 }
 
-static bool is_isoc(struct musb_hw_ep *hw_ep, bool in)
-{
-	if (in && hw_ep->in_qh) {
-		if (hw_ep->in_qh->type == USB_ENDPOINT_XFER_ISOC)
-			return true;
-	} else if (hw_ep->out_qh) {
-		if (hw_ep->out_qh->type == USB_ENDPOINT_XFER_ISOC)
-			return true;
-	}
-	return false;
-}
-
 static void cppi41_dma_callback(void *private_data);
 
 static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
@@ -139,6 +130,7 @@
 		cppi41_channel->channel.actual_len =
 			cppi41_channel->transferred;
 		cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
+		cppi41_channel->channel.rx_packet_done = true;
 		musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx);
 	} else {
 		/* next iteration, reload */
@@ -172,6 +164,7 @@
 		dma_async_issue_pending(dc);
 
 		if (!cppi41_channel->is_tx) {
+			musb_ep_select(musb->mregs, hw_ep->epnum);
 			csr = musb_readw(epio, MUSB_RXCSR);
 			csr |= MUSB_RXCSR_H_REQPKT;
 			musb_writew(epio, MUSB_RXCSR, csr);
@@ -179,32 +172,6 @@
 	}
 }
 
-static void cppi_trans_done_work(struct work_struct *work)
-{
-	unsigned long flags;
-	struct cppi41_dma_channel *cppi41_channel =
-		container_of(work, struct cppi41_dma_channel, dma_completion);
-	struct cppi41_dma_controller *controller = cppi41_channel->controller;
-	struct musb *musb = controller->musb;
-	struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
-	bool empty;
-
-	if (!cppi41_channel->is_tx && is_isoc(hw_ep, 1)) {
-		spin_lock_irqsave(&musb->lock, flags);
-		cppi41_trans_done(cppi41_channel);
-		spin_unlock_irqrestore(&musb->lock, flags);
-	} else {
-		empty = musb_is_tx_fifo_empty(hw_ep);
-		if (empty) {
-			spin_lock_irqsave(&musb->lock, flags);
-			cppi41_trans_done(cppi41_channel);
-			spin_unlock_irqrestore(&musb->lock, flags);
-		} else {
-			schedule_work(&cppi41_channel->dma_completion);
-		}
-	}
-}
-
 static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
 {
 	struct cppi41_dma_controller *controller;
@@ -233,7 +200,7 @@
 	if (!list_empty(&controller->early_tx_list)) {
 		ret = HRTIMER_RESTART;
 		hrtimer_forward_now(&controller->early_tx,
-				ktime_set(0, 150 * NSEC_PER_USEC));
+				ktime_set(0, 50 * NSEC_PER_USEC));
 	}
 
 	spin_unlock_irqrestore(&musb->lock, flags);
@@ -268,14 +235,6 @@
 			transferred < cppi41_channel->packet_sz)
 		cppi41_channel->prog_len = 0;
 
-	if (!cppi41_channel->is_tx) {
-		if (is_isoc(hw_ep, 1))
-			schedule_work(&cppi41_channel->dma_completion);
-		else
-			cppi41_trans_done(cppi41_channel);
-		goto out;
-	}
-
 	empty = musb_is_tx_fifo_empty(hw_ep);
 	if (empty) {
 		cppi41_trans_done(cppi41_channel);
@@ -312,15 +271,13 @@
 				goto out;
 			}
 		}
-		if (is_isoc(hw_ep, 0)) {
-			schedule_work(&cppi41_channel->dma_completion);
-			goto out;
-		}
 		list_add_tail(&cppi41_channel->tx_check,
 				&controller->early_tx_list);
 		if (!hrtimer_is_queued(&controller->early_tx)) {
+			unsigned long usecs = cppi41_channel->total_len / 10;
+
 			hrtimer_start_range_ns(&controller->early_tx,
-				ktime_set(0, 140 * NSEC_PER_USEC),
+				ktime_set(0, usecs * NSEC_PER_USEC),
 				40 * NSEC_PER_USEC,
 				HRTIMER_MODE_REL);
 		}
@@ -450,6 +407,7 @@
 	dma_desc->callback = cppi41_dma_callback;
 	dma_desc->callback_param = channel;
 	cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
+	cppi41_channel->channel.rx_packet_done = false;
 
 	save_rx_toggle(cppi41_channel);
 	dma_async_issue_pending(dc);
@@ -672,8 +630,6 @@
 		cppi41_channel->port_num = port;
 		cppi41_channel->is_tx = is_tx;
 		INIT_LIST_HEAD(&cppi41_channel->tx_check);
-		INIT_WORK(&cppi41_channel->dma_completion,
-			  cppi_trans_done_work);
 
 		musb_dma = &cppi41_channel->channel;
 		musb_dma->private_data = cppi41_channel;
diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 1345a4f..1d44faa 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -129,6 +129,7 @@
 	size_t			actual_len;
 	enum dma_channel_status	status;
 	bool			desired_mode;
+	bool			rx_packet_done;
 };
 
 /*
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 09529f9..c791ba5 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -56,16 +56,24 @@
  * dependent on musb core layer symbols.
  */
 static inline u8 dsps_readb(const void __iomem *addr, unsigned offset)
-	{ return __raw_readb(addr + offset); }
+{
+	return __raw_readb(addr + offset);
+}
 
 static inline u32 dsps_readl(const void __iomem *addr, unsigned offset)
-	{ return __raw_readl(addr + offset); }
+{
+	return __raw_readl(addr + offset);
+}
 
 static inline void dsps_writeb(void __iomem *addr, unsigned offset, u8 data)
-	{ __raw_writeb(data, addr + offset); }
+{
+	__raw_writeb(data, addr + offset);
+}
 
 static inline void dsps_writel(void __iomem *addr, unsigned offset, u32 data)
-	{ __raw_writel(data, addr + offset); }
+{
+	__raw_writel(data, addr + offset);
+}
 
 /**
  * DSPS musb wrapper register offset.
@@ -136,6 +144,7 @@
 	const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
 	struct timer_list timer;	/* otg_workaround timer */
 	unsigned long last_timer;    /* last timer data for each instance */
+	bool sw_babble_enabled;
 
 	struct dsps_context context;
 	struct debugfs_regset32 regset;
@@ -469,6 +478,19 @@
 	val &= ~(1 << wrp->otg_disable);
 	dsps_writel(musb->ctrl_base, wrp->phy_utmi, val);
 
+	/*
+	 *  Check whether the dsps version has babble control enabled.
+	 * In latest silicon revision the babble control logic is enabled.
+	 * If MUSB_BABBLE_CTL returns 0x4 then we have the babble control
+	 * logic enabled.
+	 */
+	val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL);
+	if (val == MUSB_BABBLE_RCV_DISABLE) {
+		glue->sw_babble_enabled = true;
+		val |= MUSB_BABBLE_SW_SESSION_CTRL;
+		dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val);
+	}
+
 	ret = dsps_musb_dbg_init(musb, glue);
 	if (ret)
 		return ret;
@@ -535,14 +557,82 @@
 	return 0;
 }
 
-static void dsps_musb_reset(struct musb *musb)
+static bool  sw_babble_control(struct musb *musb)
+{
+	u8 babble_ctl;
+	bool session_restart =  false;
+
+	babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL);
+	dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n",
+		babble_ctl);
+	/*
+	 * check line monitor flag to check whether babble is
+	 * due to noise
+	 */
+	dev_dbg(musb->controller, "STUCK_J is %s\n",
+		babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset");
+
+	if (babble_ctl & MUSB_BABBLE_STUCK_J) {
+		int timeout = 10;
+
+		/*
+		 * babble is due to noise, then set transmit idle (d7 bit)
+		 * to resume normal operation
+		 */
+		babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL);
+		babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE;
+		dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl);
+
+		/* wait till line monitor flag cleared */
+		dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n");
+		do {
+			babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL);
+			udelay(1);
+		} while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--);
+
+		/* check whether stuck_at_j bit cleared */
+		if (babble_ctl & MUSB_BABBLE_STUCK_J) {
+			/*
+			 * real babble condition has occurred
+			 * restart the controller to start the
+			 * session again
+			 */
+			dev_dbg(musb->controller, "J not cleared, misc (%x)\n",
+				babble_ctl);
+			session_restart = true;
+		}
+	} else {
+		session_restart = true;
+	}
+
+	return session_restart;
+}
+
+static int dsps_musb_reset(struct musb *musb)
 {
 	struct device *dev = musb->controller;
 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
 	const struct dsps_musb_wrapper *wrp = glue->wrp;
+	int session_restart = 0;
 
-	dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset));
-	udelay(100);
+	if (glue->sw_babble_enabled)
+		session_restart = sw_babble_control(musb);
+	/*
+	 * In case of new silicon version babble condition can be recovered
+	 * without resetting the MUSB. But for older silicon versions, MUSB
+	 * reset is needed
+	 */
+	if (session_restart || !glue->sw_babble_enabled) {
+		dev_info(musb->controller, "Restarting MUSB to recover from Babble\n");
+		dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset));
+		usleep_range(100, 200);
+		usb_phy_shutdown(musb->xceiv);
+		usleep_range(100, 200);
+		usb_phy_init(musb->xceiv);
+		session_restart = 1;
+	}
+
+	return !session_restart;
 }
 
 static struct musb_platform_ops dsps_ops = {
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index eb06291..855793d 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -120,7 +120,7 @@
 		if (csr != lastcsr)
 			dev_dbg(musb->controller, "Host TX FIFONOTEMPTY csr: %02x\n", csr);
 		lastcsr = csr;
-		csr |= MUSB_TXCSR_FLUSHFIFO;
+		csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_TXPKTRDY;
 		musb_writew(epio, MUSB_TXCSR, csr);
 		csr = musb_readw(epio, MUSB_TXCSR);
 		if (WARN(retries-- < 1,
@@ -1295,7 +1295,7 @@
 	if (status) {
 		if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
 			dma->status = MUSB_DMA_STATUS_CORE_ABORT;
-			(void) musb->dma_controller->channel_abort(dma);
+			musb->dma_controller->channel_abort(dma);
 		}
 
 		/* do the proper sequence to abort the transfer in the
@@ -1640,7 +1640,7 @@
 		/* clean up dma and collect transfer count */
 		if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
 			dma->status = MUSB_DMA_STATUS_CORE_ABORT;
-			(void) musb->dma_controller->channel_abort(dma);
+			musb->dma_controller->channel_abort(dma);
 			xfer_len = dma->actual_len;
 		}
 		musb_h_flush_rxfifo(hw_ep, MUSB_RXCSR_CLRDATATOG);
@@ -1671,7 +1671,7 @@
 		 */
 		if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
 			dma->status = MUSB_DMA_STATUS_CORE_ABORT;
-			(void) musb->dma_controller->channel_abort(dma);
+			musb->dma_controller->channel_abort(dma);
 			xfer_len = dma->actual_len;
 			done = true;
 		}
@@ -1734,10 +1734,11 @@
 			}
 
 		} else  {
-		/* done if urb buffer is full or short packet is recd */
-		done = (urb->actual_length + xfer_len >=
-				urb->transfer_buffer_length
-			|| dma->actual_len < qh->maxpacket);
+			/* done if urb buffer is full or short packet is recd */
+			done = (urb->actual_length + xfer_len >=
+					urb->transfer_buffer_length
+				|| dma->actual_len < qh->maxpacket
+				|| dma->rx_packet_done);
 		}
 
 		/* send IN token for next packet, without AUTOREQ */
@@ -1957,7 +1958,7 @@
 	struct musb_qh		*qh,
 	int			is_in)
 {
-	int			idle;
+	int			idle = 0;
 	int			best_diff;
 	int			best_end, epnum;
 	struct musb_hw_ep	*hw_ep = NULL;
diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h
index 03f2655..b9bcda5 100644
--- a/drivers/usb/musb/musb_regs.h
+++ b/drivers/usb/musb/musb_regs.h
@@ -72,6 +72,12 @@
 #define MUSB_DEVCTL_HR		0x02
 #define MUSB_DEVCTL_SESSION	0x01
 
+/* BABBLE_CTL */
+#define MUSB_BABBLE_FORCE_TXIDLE	0x80
+#define MUSB_BABBLE_SW_SESSION_CTRL	0x40
+#define MUSB_BABBLE_STUCK_J		0x20
+#define MUSB_BABBLE_RCV_DISABLE		0x04
+
 /* MUSB ULPI VBUSCONTROL */
 #define MUSB_ULPI_USE_EXTVBUS	0x01
 #define MUSB_ULPI_USE_EXTVBUSIND 0x02
@@ -246,6 +252,7 @@
  */
 
 #define MUSB_DEVCTL		0x60	/* 8 bit */
+#define MUSB_BABBLE_CTL		0x61	/* 8 bit */
 
 /* These are always controlled through the INDEX register */
 #define MUSB_TXFIFOSZ		0x62	/* 8-bit (see masks) */
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 159ef4b..7dfc6cb 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -22,6 +22,7 @@
 #include <linux/usb.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/usb/usb_phy_generic.h>
@@ -1160,12 +1161,12 @@
 	struct platform_device		*musb;
 	struct tusb6010_glue		*glue;
 	struct platform_device_info	pinfo;
-	int				ret = -ENOMEM;
+	int				ret;
 
-	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
 		dev_err(&pdev->dev, "failed to allocate glue context\n");
-		goto err0;
+		return -ENOMEM;
 	}
 
 	glue->dev			= &pdev->dev;
@@ -1204,16 +1205,10 @@
 	if (IS_ERR(musb)) {
 		ret = PTR_ERR(musb);
 		dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
-		goto err3;
+		return ret;
 	}
 
 	return 0;
-
-err3:
-	kfree(glue);
-
-err0:
-	return ret;
 }
 
 static int tusb_remove(struct platform_device *pdev)
@@ -1222,7 +1217,6 @@
 
 	platform_device_unregister(glue->musb);
 	usb_phy_generic_unregister(glue->phy);
-	kfree(glue);
 
 	return 0;
 }
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index f202e50..dc666e9 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -246,7 +246,7 @@
 		}
 	}
 
-	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
 		dev_err(&pdev->dev, "failed to allocate glue context\n");
 		goto err0;
@@ -255,20 +255,20 @@
 	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 	if (!musb) {
 		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err1;
+		goto err0;
 	}
 
-	clk = clk_get(&pdev->dev, NULL);
+	clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clock\n");
 		ret = PTR_ERR(clk);
-		goto err3;
+		goto err1;
 	}
 
 	ret = clk_prepare_enable(clk);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to enable clock\n");
-		goto err4;
+		goto err1;
 	}
 
 	musb->dev.parent		= &pdev->dev;
@@ -301,34 +301,28 @@
 			ARRAY_SIZE(musb_resources));
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add resources\n");
-		goto err5;
+		goto err2;
 	}
 
 	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add platform_data\n");
-		goto err5;
+		goto err2;
 	}
 
 	ret = platform_device_add(musb);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register musb device\n");
-		goto err5;
+		goto err2;
 	}
 
 	return 0;
 
-err5:
+err2:
 	clk_disable_unprepare(clk);
 
-err4:
-	clk_put(clk);
-
-err3:
-	platform_device_put(musb);
-
 err1:
-	kfree(glue);
+	platform_device_put(musb);
 
 err0:
 	return ret;
@@ -340,8 +334,6 @@
 
 	platform_device_unregister(glue->musb);
 	clk_disable_unprepare(glue->clk);
-	clk_put(glue->clk);
-	kfree(glue);
 
 	return 0;
 }
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
index 585e50c..b70e055 100644
--- a/drivers/usb/phy/phy-am335x.c
+++ b/drivers/usb/phy/phy-am335x.c
@@ -122,16 +122,10 @@
 
 	return 0;
 }
-
-static const struct dev_pm_ops am335x_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(am335x_phy_suspend, am335x_phy_resume)
-};
-
-#define DEV_PM_OPS     (&am335x_pm_ops)
-#else
-#define DEV_PM_OPS     NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(am335x_pm_ops, am335x_phy_suspend, am335x_phy_resume);
+
 static const struct of_device_id am335x_phy_ids[] = {
 	{ .compatible = "ti,am335x-usb-phy" },
 	{ }
@@ -144,7 +138,7 @@
 	.driver         = {
 		.name   = "am335x-phy-driver",
 		.owner  = THIS_MODULE,
-		.pm = DEV_PM_OPS,
+		.pm = &am335x_pm_ops,
 		.of_match_table = am335x_phy_ids,
 	},
 };
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index 69462e0..ea9e705 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -253,11 +253,13 @@
 		return -EINVAL;
 	gpio = pdata->gpio_vbus;
 
-	gpio_vbus = kzalloc(sizeof(struct gpio_vbus_data), GFP_KERNEL);
+	gpio_vbus = devm_kzalloc(&pdev->dev, sizeof(struct gpio_vbus_data),
+				 GFP_KERNEL);
 	if (!gpio_vbus)
 		return -ENOMEM;
 
-	gpio_vbus->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
+	gpio_vbus->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
+					  GFP_KERNEL);
 	if (!gpio_vbus->phy.otg) {
 		kfree(gpio_vbus);
 		return -ENOMEM;
@@ -274,11 +276,11 @@
 	gpio_vbus->phy.otg->phy = &gpio_vbus->phy;
 	gpio_vbus->phy.otg->set_peripheral = gpio_vbus_set_peripheral;
 
-	err = gpio_request(gpio, "vbus_detect");
+	err = devm_gpio_request(&pdev->dev, gpio, "vbus_detect");
 	if (err) {
 		dev_err(&pdev->dev, "can't request vbus gpio %d, err: %d\n",
 			gpio, err);
-		goto err_gpio;
+		return err;
 	}
 	gpio_direction_input(gpio);
 
@@ -296,27 +298,27 @@
 	/* if data line pullup is in use, initialize it to "not pulling up" */
 	gpio = pdata->gpio_pullup;
 	if (gpio_is_valid(gpio)) {
-		err = gpio_request(gpio, "udc_pullup");
+		err = devm_gpio_request(&pdev->dev, gpio, "udc_pullup");
 		if (err) {
 			dev_err(&pdev->dev,
 				"can't request pullup gpio %d, err: %d\n",
 				gpio, err);
-			gpio_free(pdata->gpio_vbus);
-			goto err_gpio;
+			return err;
 		}
 		gpio_direction_output(gpio, pdata->gpio_pullup_inverted);
 	}
 
-	err = request_irq(irq, gpio_vbus_irq, irqflags, "vbus_detect", pdev);
+	err = devm_request_irq(&pdev->dev, irq, gpio_vbus_irq, irqflags,
+			       "vbus_detect", pdev);
 	if (err) {
 		dev_err(&pdev->dev, "can't request irq %i, err: %d\n",
 			irq, err);
-		goto err_irq;
+		return err;
 	}
 
 	INIT_DELAYED_WORK(&gpio_vbus->work, gpio_vbus_work);
 
-	gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw");
+	gpio_vbus->vbus_draw = devm_regulator_get(&pdev->dev, "vbus_draw");
 	if (IS_ERR(gpio_vbus->vbus_draw)) {
 		dev_dbg(&pdev->dev, "can't get vbus_draw regulator, err: %ld\n",
 			PTR_ERR(gpio_vbus->vbus_draw));
@@ -328,44 +330,23 @@
 	if (err) {
 		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
 			err);
-		goto err_otg;
+		return err;
 	}
 
 	device_init_wakeup(&pdev->dev, pdata->wakeup);
 
 	return 0;
-err_otg:
-	regulator_put(gpio_vbus->vbus_draw);
-	free_irq(irq, pdev);
-err_irq:
-	if (gpio_is_valid(pdata->gpio_pullup))
-		gpio_free(pdata->gpio_pullup);
-	gpio_free(pdata->gpio_vbus);
-err_gpio:
-	kfree(gpio_vbus->phy.otg);
-	kfree(gpio_vbus);
-	return err;
 }
 
 static int gpio_vbus_remove(struct platform_device *pdev)
 {
 	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
-	struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev);
-	int gpio = pdata->gpio_vbus;
 
 	device_init_wakeup(&pdev->dev, 0);
 	cancel_delayed_work_sync(&gpio_vbus->work);
-	regulator_put(gpio_vbus->vbus_draw);
 
 	usb_remove_phy(&gpio_vbus->phy);
 
-	free_irq(gpio_vbus->irq, pdev);
-	if (gpio_is_valid(pdata->gpio_pullup))
-		gpio_free(pdata->gpio_pullup);
-	gpio_free(gpio);
-	kfree(gpio_vbus->phy.otg);
-	kfree(gpio_vbus);
-
 	return 0;
 }
 
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index c929370..e4108ee 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -279,11 +279,11 @@
 
 static int msm_otg_phy_clk_reset(struct msm_otg *motg)
 {
-	int ret;
+	int ret = 0;
 
-	if (motg->pdata->phy_clk_reset)
+	if (motg->pdata->phy_clk_reset && motg->phy_reset_clk)
 		ret = motg->pdata->phy_clk_reset(motg->phy_reset_clk);
-	else
+	else if (motg->phy_rst)
 		ret = reset_control_reset(motg->phy_rst);
 
 	if (ret)
@@ -1429,7 +1429,7 @@
 	debugfs_remove(msm_otg_dbg_root);
 }
 
-static struct of_device_id msm_otg_dt_match[] = {
+static const struct of_device_id msm_otg_dt_match[] = {
 	{
 		.compatible = "qcom,usb-otg-ci",
 		.data = (void *) CI_45NM_INTEGRATED_PHY
@@ -1466,7 +1466,7 @@
 
 	motg->phy_rst = devm_reset_control_get(&pdev->dev, "phy");
 	if (IS_ERR(motg->phy_rst))
-		return PTR_ERR(motg->phy_rst);
+		motg->phy_rst = NULL;
 
 	pdata->mode = of_usb_get_dr_mode(node);
 	if (pdata->mode == USB_DR_MODE_UNKNOWN)
@@ -1558,7 +1558,7 @@
 					   np ? "phy" : "usb_phy_clk");
 	if (IS_ERR(motg->phy_reset_clk)) {
 		dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
-		return PTR_ERR(motg->phy_reset_clk);
+		motg->phy_reset_clk = NULL;
 	}
 
 	motg->clk = devm_clk_get(&pdev->dev, np ? "core" : "usb_hs_clk");
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 50dc69e..13b4fa2 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -962,7 +962,7 @@
 	.requires_extra_tuning_parameters = true,
 };
 
-static struct of_device_id tegra_usb_phy_id_table[] = {
+static const struct of_device_id tegra_usb_phy_id_table[] = {
 	{ .compatible = "nvidia,tegra30-usb-phy", .data = &tegra30_soc_config },
 	{ .compatible = "nvidia,tegra20-usb-phy", .data = &tegra20_soc_config },
 	{ },
diff --git a/drivers/usb/renesas_usbhs/Makefile b/drivers/usb/renesas_usbhs/Makefile
index bc8aef4..9e47f47 100644
--- a/drivers/usb/renesas_usbhs/Makefile
+++ b/drivers/usb/renesas_usbhs/Makefile
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_USB_RENESAS_USBHS)	+= renesas_usbhs.o
 
-renesas_usbhs-y			:= common.o mod.o pipe.o fifo.o
+renesas_usbhs-y			:= common.o mod.o pipe.o fifo.o rcar2.o
 
 ifneq ($(CONFIG_USB_RENESAS_USBHS_HCD),)
 	renesas_usbhs-y		+= mod_host.o
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index 17267b0..1b9bf8d 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -15,12 +15,14 @@
  *
  */
 #include <linux/err.h>
+#include <linux/gpio.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/sysfs.h>
 #include "common.h"
+#include "rcar2.h"
 
 /*
  *		image of renesas_usbhs
@@ -284,6 +286,8 @@
 /*
  *		platform default param
  */
+
+/* commonly used on old SH-Mobile SoCs */
 static u32 usbhsc_default_pipe_type[] = {
 		USB_ENDPOINT_XFER_CONTROL,
 		USB_ENDPOINT_XFER_ISOC,
@@ -297,6 +301,26 @@
 		USB_ENDPOINT_XFER_INT,
 };
 
+/* commonly used on newer SH-Mobile and R-Car SoCs */
+static u32 usbhsc_new_pipe_type[] = {
+		USB_ENDPOINT_XFER_CONTROL,
+		USB_ENDPOINT_XFER_ISOC,
+		USB_ENDPOINT_XFER_ISOC,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_INT,
+		USB_ENDPOINT_XFER_INT,
+		USB_ENDPOINT_XFER_INT,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+		USB_ENDPOINT_XFER_BULK,
+};
+
 /*
  *		power control
  */
@@ -423,8 +447,7 @@
 	int ret;
 
 	/* check platform information */
-	if (!info ||
-	    !info->platform_callback.get_id) {
+	if (!info) {
 		dev_err(&pdev->dev, "no platform information\n");
 		return -EINVAL;
 	}
@@ -451,13 +474,32 @@
 	/*
 	 * care platform info
 	 */
-	memcpy(&priv->pfunc,
-	       &info->platform_callback,
-	       sizeof(struct renesas_usbhs_platform_callback));
+
 	memcpy(&priv->dparam,
 	       &info->driver_param,
 	       sizeof(struct renesas_usbhs_driver_param));
 
+	switch (priv->dparam.type) {
+	case USBHS_TYPE_R8A7790:
+	case USBHS_TYPE_R8A7791:
+		priv->pfunc = usbhs_rcar2_ops;
+		if (!priv->dparam.pipe_type) {
+			priv->dparam.pipe_type = usbhsc_new_pipe_type;
+			priv->dparam.pipe_size =
+				ARRAY_SIZE(usbhsc_new_pipe_type);
+		}
+		break;
+	default:
+		if (!info->platform_callback.get_id) {
+			dev_err(&pdev->dev, "no platform callbacks");
+			return -EINVAL;
+		}
+		memcpy(&priv->pfunc,
+		       &info->platform_callback,
+		       sizeof(struct renesas_usbhs_platform_callback));
+		break;
+	}
+
 	/* set driver callback functions for platform */
 	dfunc			= &info->driver_callback;
 	dfunc->notify_hotplug	= usbhsc_drvcllbck_notify_hotplug;
@@ -507,6 +549,20 @@
 	 */
 	usbhs_sys_clock_ctrl(priv, 0);
 
+	/* check GPIO determining if USB function should be enabled */
+	if (priv->dparam.enable_gpio) {
+		gpio_request_one(priv->dparam.enable_gpio, GPIOF_IN, NULL);
+		ret = !gpio_get_value(priv->dparam.enable_gpio);
+		gpio_free(priv->dparam.enable_gpio);
+		if (ret) {
+			dev_warn(&pdev->dev,
+				 "USB function not selected (GPIO %d)\n",
+				 priv->dparam.enable_gpio);
+			ret = -ENOTSUPP;
+			goto probe_end_mod_exit;
+		}
+	}
+
 	/*
 	 * platform call
 	 *
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h
index c69dd2f..a7996da 100644
--- a/drivers/usb/renesas_usbhs/common.h
+++ b/drivers/usb/renesas_usbhs/common.h
@@ -268,6 +268,8 @@
 	 * fifo control
 	 */
 	struct usbhs_fifo_info fifo_info;
+
+	struct usb_phy *phy;
 };
 
 /*
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 458f376..04e6505 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -600,8 +600,10 @@
 static int usbhsg_ep_disable(struct usb_ep *ep)
 {
 	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
+	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
 
 	usbhsg_pipe_disable(uep);
+	usbhs_pipe_free(pipe);
 
 	uep->pipe->mod_private	= NULL;
 	uep->pipe		= NULL;
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c
index 7926e1c..75fbcf6 100644
--- a/drivers/usb/renesas_usbhs/pipe.c
+++ b/drivers/usb/renesas_usbhs/pipe.c
@@ -640,6 +640,11 @@
 	return pipe;
 }
 
+static void usbhsp_put_pipe(struct usbhs_pipe *pipe)
+{
+	usbhsp_flags_init(pipe);
+}
+
 void usbhs_pipe_init(struct usbhs_priv *priv,
 		     int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map))
 {
@@ -710,6 +715,7 @@
 	usbhsp_pipe_select(pipe);
 	usbhsp_pipe_cfg_set(pipe, 0xFFFF, pipecfg);
 	usbhsp_pipe_buf_set(pipe, 0xFFFF, pipebuf);
+	usbhs_pipe_clear(pipe);
 
 	usbhs_pipe_sequence_data0(pipe);
 
@@ -726,6 +732,11 @@
 	return pipe;
 }
 
+void usbhs_pipe_free(struct usbhs_pipe *pipe)
+{
+	usbhsp_put_pipe(pipe);
+}
+
 void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo)
 {
 	if (pipe->fifo)
diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h
index 3e53498..406f36d 100644
--- a/drivers/usb/renesas_usbhs/pipe.h
+++ b/drivers/usb/renesas_usbhs/pipe.h
@@ -75,6 +75,7 @@
 char *usbhs_pipe_name(struct usbhs_pipe *pipe);
 struct usbhs_pipe
 *usbhs_pipe_malloc(struct usbhs_priv *priv, int endpoint_type, int dir_in);
+void usbhs_pipe_free(struct usbhs_pipe *pipe);
 int usbhs_pipe_probe(struct usbhs_priv *priv);
 void usbhs_pipe_remove(struct usbhs_priv *priv);
 int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe);
diff --git a/drivers/usb/renesas_usbhs/rcar2.c b/drivers/usb/renesas_usbhs/rcar2.c
new file mode 100644
index 0000000..e6b9dcc
--- /dev/null
+++ b/drivers/usb/renesas_usbhs/rcar2.c
@@ -0,0 +1,77 @@
+/*
+ * Renesas USB driver R-Car Gen. 2 initialization and power control
+ *
+ * Copyright (C) 2014 Ulrich Hecht
+ *
+ * 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.
+ *
+ */
+
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_data/gpio-rcar.h>
+#include <linux/usb/phy.h>
+#include "common.h"
+#include "rcar2.h"
+
+static int usbhs_rcar2_hardware_init(struct platform_device *pdev)
+{
+	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
+	struct usb_phy *phy;
+
+	phy = usb_get_phy_dev(&pdev->dev, 0);
+	if (IS_ERR(phy))
+		return PTR_ERR(phy);
+
+	priv->phy = phy;
+	return 0;
+}
+
+static int usbhs_rcar2_hardware_exit(struct platform_device *pdev)
+{
+	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
+
+	if (!priv->phy)
+		return 0;
+
+	usb_put_phy(priv->phy);
+	priv->phy = NULL;
+
+	return 0;
+}
+
+static int usbhs_rcar2_power_ctrl(struct platform_device *pdev,
+				void __iomem *base, int enable)
+{
+	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
+
+	if (!priv->phy)
+		return -ENODEV;
+
+	if (enable) {
+		int retval = usb_phy_init(priv->phy);
+
+		if (!retval)
+			retval = usb_phy_set_suspend(priv->phy, 0);
+		return retval;
+	}
+
+	usb_phy_set_suspend(priv->phy, 1);
+	usb_phy_shutdown(priv->phy);
+	return 0;
+}
+
+static int usbhs_rcar2_get_id(struct platform_device *pdev)
+{
+	return USBHS_GADGET;
+}
+
+const struct renesas_usbhs_platform_callback usbhs_rcar2_ops = {
+	.hardware_init = usbhs_rcar2_hardware_init,
+	.hardware_exit = usbhs_rcar2_hardware_exit,
+	.power_ctrl = usbhs_rcar2_power_ctrl,
+	.get_id = usbhs_rcar2_get_id,
+};
diff --git a/drivers/usb/renesas_usbhs/rcar2.h b/drivers/usb/renesas_usbhs/rcar2.h
new file mode 100644
index 0000000..f07f10d
--- /dev/null
+++ b/drivers/usb/renesas_usbhs/rcar2.h
@@ -0,0 +1,4 @@
+#include "common.h"
+
+extern const struct renesas_usbhs_platform_callback
+	usbhs_rcar2_ops;
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 7373203..c330f5e 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -386,6 +386,21 @@
 
 extern int usb_composite_probe(struct usb_composite_driver *driver);
 extern void usb_composite_unregister(struct usb_composite_driver *driver);
+
+/**
+ * module_usb_composite_driver() - Helper macro for registering a USB gadget
+ * composite driver
+ * @__usb_composite_driver: usb_composite_driver struct
+ *
+ * Helper macro for USB gadget composite drivers which do not do anything
+ * special in module init/exit. This eliminates a lot of boilerplate. Each
+ * module may only use this macro once, and calling it replaces module_init()
+ * and module_exit()
+ */
+#define module_usb_composite_driver(__usb_composite_driver) \
+	module_driver(__usb_composite_driver, usb_composite_probe, \
+		       usb_composite_unregister)
+
 extern void usb_composite_setup_continue(struct usb_composite_dev *cdev);
 extern int composite_dev_prepare(struct usb_composite_driver *composite,
 		struct usb_composite_dev *cdev);
diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h
index e452ba6..d5952bb 100644
--- a/include/linux/usb/renesas_usbhs.h
+++ b/include/linux/usb/renesas_usbhs.h
@@ -153,6 +153,9 @@
 	 */
 	int pio_dma_border; /* default is 64byte */
 
+	u32 type;
+	u32 enable_gpio;
+
 	/*
 	 * option:
 	 */
@@ -160,6 +163,9 @@
 	u32 has_sudmac:1; /* for SUDMAC */
 };
 
+#define USBHS_TYPE_R8A7790 1
+#define USBHS_TYPE_R8A7791 2
+
 /*
  * option:
  *
diff --git a/include/linux/usb/usb338x.h b/include/linux/usb/usb338x.h
new file mode 100644
index 0000000..f92eb63
--- /dev/null
+++ b/include/linux/usb/usb338x.h
@@ -0,0 +1,199 @@
+/*
+ * USB 338x super/high/full speed USB device controller.
+ * Unlike many such controllers, this one talks PCI.
+ *
+ * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
+ * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2014 Ricardo Ribalda - Qtechnology/AS
+ *
+ * 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.
+ *
+ */
+
+#ifndef __LINUX_USB_USB338X_H
+#define __LINUX_USB_USB338X_H
+
+#include <linux/usb/net2280.h>
+
+/*
+ * Extra defined bits for net2280 registers
+ */
+#define     SCRATCH			      0x0b
+
+#define     DEFECT7374_FSM_FIELD                28
+#define     SUPER_SPEED				 8
+#define     DMA_REQUEST_OUTSTANDING              5
+#define     DMA_PAUSE_DONE_INTERRUPT            26
+#define     SET_ISOCHRONOUS_DELAY               24
+#define     SET_SEL                             22
+#define     SUPER_SPEED_MODE                     8
+
+/*ep_cfg*/
+#define     MAX_BURST_SIZE                      24
+#define     EP_FIFO_BYTE_COUNT                  16
+#define     IN_ENDPOINT_ENABLE                  14
+#define     IN_ENDPOINT_TYPE                    12
+#define     OUT_ENDPOINT_ENABLE                 10
+#define     OUT_ENDPOINT_TYPE                    8
+
+struct usb338x_usb_ext_regs {
+	u32     usbclass;
+#define     DEVICE_PROTOCOL                     16
+#define     DEVICE_SUB_CLASS                     8
+#define     DEVICE_CLASS                         0
+	u32     ss_sel;
+#define     U2_SYSTEM_EXIT_LATENCY               8
+#define     U1_SYSTEM_EXIT_LATENCY               0
+	u32     ss_del;
+#define     U2_DEVICE_EXIT_LATENCY               8
+#define     U1_DEVICE_EXIT_LATENCY               0
+	u32     usb2lpm;
+#define     USB_L1_LPM_HIRD                      2
+#define     USB_L1_LPM_REMOTE_WAKE               1
+#define     USB_L1_LPM_SUPPORT                   0
+	u32     usb3belt;
+#define     BELT_MULTIPLIER                     10
+#define     BEST_EFFORT_LATENCY_TOLERANCE        0
+	u32     usbctl2;
+#define     LTM_ENABLE                           7
+#define     U2_ENABLE                            6
+#define     U1_ENABLE                            5
+#define     FUNCTION_SUSPEND                     4
+#define     USB3_CORE_ENABLE                     3
+#define     USB2_CORE_ENABLE                     2
+#define     SERIAL_NUMBER_STRING_ENABLE          0
+	u32     in_timeout;
+#define     GPEP3_TIMEOUT                       19
+#define     GPEP2_TIMEOUT                       18
+#define     GPEP1_TIMEOUT                       17
+#define     GPEP0_TIMEOUT                       16
+#define     GPEP3_TIMEOUT_VALUE                 13
+#define     GPEP3_TIMEOUT_ENABLE                12
+#define     GPEP2_TIMEOUT_VALUE                  9
+#define     GPEP2_TIMEOUT_ENABLE                 8
+#define     GPEP1_TIMEOUT_VALUE                  5
+#define     GPEP1_TIMEOUT_ENABLE                 4
+#define     GPEP0_TIMEOUT_VALUE                  1
+#define     GPEP0_TIMEOUT_ENABLE                 0
+	u32     isodelay;
+#define     ISOCHRONOUS_DELAY                    0
+} __packed;
+
+struct usb338x_fifo_regs {
+	/* offset 0x0500, 0x0520, 0x0540, 0x0560, 0x0580 */
+	u32     ep_fifo_size_base;
+#define     IN_FIFO_BASE_ADDRESS                                22
+#define     IN_FIFO_SIZE                                        16
+#define     OUT_FIFO_BASE_ADDRESS                               6
+#define     OUT_FIFO_SIZE                                       0
+	u32     ep_fifo_out_wrptr;
+	u32     ep_fifo_out_rdptr;
+	u32     ep_fifo_in_wrptr;
+	u32     ep_fifo_in_rdptr;
+	u32     unused[3];
+} __packed;
+
+
+/* Link layer */
+struct usb338x_ll_regs {
+	/* offset 0x700 */
+	u32   ll_ltssm_ctrl1;
+	u32   ll_ltssm_ctrl2;
+	u32   ll_ltssm_ctrl3;
+	u32   unused[2];
+	u32   ll_general_ctrl0;
+	u32   ll_general_ctrl1;
+#define     PM_U3_AUTO_EXIT                                     29
+#define     PM_U2_AUTO_EXIT                                     28
+#define     PM_U1_AUTO_EXIT                                     27
+#define     PM_FORCE_U2_ENTRY                                   26
+#define     PM_FORCE_U1_ENTRY                                   25
+#define     PM_LGO_COLLISION_SEND_LAU                           24
+#define     PM_DIR_LINK_REJECT                                  23
+#define     PM_FORCE_LINK_ACCEPT                                22
+#define     PM_DIR_ENTRY_U3                                     20
+#define     PM_DIR_ENTRY_U2                                     19
+#define     PM_DIR_ENTRY_U1                                     18
+#define     PM_U2_ENABLE                                        17
+#define     PM_U1_ENABLE                                        16
+#define     SKP_THRESHOLD_ADJUST_FMW                            8
+#define     RESEND_DPP_ON_LRTY_FMW                              7
+#define     DL_BIT_VALUE_FMW                                    6
+#define     FORCE_DL_BIT                                        5
+	u32   ll_general_ctrl2;
+#define     SELECT_INVERT_LANE_POLARITY                         7
+#define     FORCE_INVERT_LANE_POLARITY                          6
+	u32   ll_general_ctrl3;
+	u32   ll_general_ctrl4;
+	u32   ll_error_gen;
+} __packed;
+
+struct usb338x_ll_lfps_regs {
+	/* offset 0x748 */
+	u32   ll_lfps_5;
+#define     TIMER_LFPS_6US                                      16
+	u32   ll_lfps_6;
+#define     TIMER_LFPS_80US                                     0
+} __packed;
+
+struct usb338x_ll_tsn_regs {
+	/* offset 0x77C */
+	u32   ll_tsn_counters_2;
+#define     HOT_TX_NORESET_TS2                                  24
+	u32   ll_tsn_counters_3;
+#define     HOT_RX_RESET_TS2                                    0
+} __packed;
+
+struct usb338x_ll_chi_regs {
+	/* offset 0x79C */
+	u32   ll_tsn_chicken_bit;
+#define     RECOVERY_IDLE_TO_RECOVER_FMW                        3
+} __packed;
+
+/* protocol layer */
+struct usb338x_pl_regs {
+	/* offset 0x800 */
+	u32   pl_reg_1;
+	u32   pl_reg_2;
+	u32   pl_reg_3;
+	u32   pl_reg_4;
+	u32   pl_ep_ctrl;
+	/* Protocol Layer Endpoint Control*/
+#define     PL_EP_CTRL                                  0x810
+#define     ENDPOINT_SELECT                             0
+	/* [4:0] */
+#define     EP_INITIALIZED                              16
+#define     SEQUENCE_NUMBER_RESET                       17
+#define     CLEAR_ACK_ERROR_CODE                        20
+	u32   pl_reg_6;
+	u32   pl_reg_7;
+	u32   pl_reg_8;
+	u32   pl_ep_status_1;
+	/* Protocol Layer Endpoint Status 1*/
+#define     PL_EP_STATUS_1                              0x820
+#define     STATE                                       16
+#define     ACK_GOOD_NORMAL                             0x11
+#define     ACK_GOOD_MORE_ACKS_TO_COME                  0x16
+	u32   pl_ep_status_2;
+	u32   pl_ep_status_3;
+	/* Protocol Layer Endpoint Status 3*/
+#define     PL_EP_STATUS_3                              0x828
+#define     SEQUENCE_NUMBER                             0
+	u32   pl_ep_status_4;
+	/* Protocol Layer Endpoint Status 4*/
+#define     PL_EP_STATUS_4                              0x82c
+	u32   pl_ep_cfg_4;
+	/* Protocol Layer Endpoint Configuration 4*/
+#define     PL_EP_CFG_4                                 0x830
+#define     NON_CTRL_IN_TOLERATE_BAD_DIR                6
+} __packed;
+
+#endif /* __LINUX_USB_USB338X_H */
diff --git a/include/uapi/linux/usb/functionfs.h b/include/uapi/linux/usb/functionfs.h
index 24b68c5..0154b28 100644
--- a/include/uapi/linux/usb/functionfs.h
+++ b/include/uapi/linux/usb/functionfs.h
@@ -18,10 +18,9 @@
 	FUNCTIONFS_HAS_FS_DESC = 1,
 	FUNCTIONFS_HAS_HS_DESC = 2,
 	FUNCTIONFS_HAS_SS_DESC = 4,
+	FUNCTIONFS_HAS_MS_OS_DESC = 8,
 };
 
-#ifndef __KERNEL__
-
 /* Descriptor of an non-audio endpoint */
 struct usb_endpoint_descriptor_no_audio {
 	__u8  bLength;
@@ -41,6 +40,37 @@
 	__le32 hs_count;
 } __attribute__((packed, deprecated));
 
+/* MS OS Descriptor header */
+struct usb_os_desc_header {
+	__u8	interface;
+	__le32	dwLength;
+	__le16	bcdVersion;
+	__le16	wIndex;
+	union {
+		struct {
+			__u8	bCount;
+			__u8	Reserved;
+		};
+		__le16	wCount;
+	};
+} __attribute__((packed));
+
+struct usb_ext_compat_desc {
+	__u8	bFirstInterfaceNumber;
+	__u8	Reserved1;
+	__u8	CompatibleID[8];
+	__u8	SubCompatibleID[8];
+	__u8	Reserved2[6];
+};
+
+struct usb_ext_prop_desc {
+	__le32	dwSize;
+	__le32	dwPropertyDataType;
+	__le16	wPropertyNameLength;
+} __attribute__((packed));
+
+#ifndef __KERNEL__
+
 /*
  * Descriptors format:
  *
@@ -52,9 +82,11 @@
  * |     | fs_count  | LE32         | number of full-speed descriptors     |
  * |     | hs_count  | LE32         | number of high-speed descriptors     |
  * |     | ss_count  | LE32         | number of super-speed descriptors    |
+ * |     | os_count  | LE32         | number of MS OS descriptors          |
  * |     | fs_descrs | Descriptor[] | list of full-speed descriptors       |
  * |     | hs_descrs | Descriptor[] | list of high-speed descriptors       |
  * |     | ss_descrs | Descriptor[] | list of super-speed descriptors      |
+ * |     | os_descrs | OSDesc[]     | list of MS OS descriptors            |
  *
  * Depending on which flags are set, various fields may be missing in the
  * structure.  Any flags that are not recognised cause the whole block to be
@@ -81,6 +113,52 @@
  * |   0 | bLength         | U8   | length of the descriptor |
  * |   1 | bDescriptorType | U8   | descriptor type          |
  * |   2 | payload         |      | descriptor's payload     |
+ *
+ * OSDesc[] is an array of valid MS OS Feature Descriptors which have one of
+ * the following formats:
+ *
+ * | off | name            | type | description              |
+ * |-----+-----------------+------+--------------------------|
+ * |   0 | inteface        | U8   | related interface number |
+ * |   1 | dwLength        | U32  | length of the descriptor |
+ * |   5 | bcdVersion      | U16  | currently supported: 1   |
+ * |   7 | wIndex          | U16  | currently supported: 4   |
+ * |   9 | bCount          | U8   | number of ext. compat.   |
+ * |  10 | Reserved        | U8   | 0                        |
+ * |  11 | ExtCompat[]     |      | list of ext. compat. d.  |
+ *
+ * | off | name            | type | description              |
+ * |-----+-----------------+------+--------------------------|
+ * |   0 | inteface        | U8   | related interface number |
+ * |   1 | dwLength        | U32  | length of the descriptor |
+ * |   5 | bcdVersion      | U16  | currently supported: 1   |
+ * |   7 | wIndex          | U16  | currently supported: 5   |
+ * |   9 | wCount          | U16  | number of ext. compat.   |
+ * |  11 | ExtProp[]       |      | list of ext. prop. d.    |
+ *
+ * ExtCompat[] is an array of valid Extended Compatiblity descriptors
+ * which have the following format:
+ *
+ * | off | name                  | type | description                         |
+ * |-----+-----------------------+------+-------------------------------------|
+ * |   0 | bFirstInterfaceNumber | U8   | index of the interface or of the 1st|
+ * |     |                       |      | interface in an IAD group           |
+ * |   1 | Reserved              | U8   | 0                                   |
+ * |   2 | CompatibleID          | U8[8]| compatible ID string                |
+ * |  10 | SubCompatibleID       | U8[8]| subcompatible ID string             |
+ * |  18 | Reserved              | U8[6]| 0                                   |
+ *
+ * ExtProp[] is an array of valid Extended Properties descriptors
+ * which have the following format:
+ *
+ * | off | name                  | type | description                         |
+ * |-----+-----------------------+------+-------------------------------------|
+ * |   0 | dwSize                | U32  | length of the descriptor            |
+ * |   4 | dwPropertyDataType    | U32  | 1..7                                |
+ * |   8 | wPropertyNameLength   | U16  | bPropertyName length (NL)           |
+ * |  10 | bPropertyName         |U8[NL]| name of this property               |
+ * |10+NL| dwPropertyDataLength  | U32  | bPropertyData length (DL)           |
+ * |14+NL| bProperty             |U8[DL]| payload of this property            |
  */
 
 struct usb_functionfs_strings_head {
diff --git a/tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c b/tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c
index 87216a0..af4b050 100644
--- a/tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c
+++ b/tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c
@@ -1,3 +1,30 @@
+/*
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * For more information, please refer to <http://unlicense.org/>
+ */
+
 #define _BSD_SOURCE /* for endian.h */
 
 #include <endian.h>
@@ -27,7 +54,9 @@
 /******************** Descriptors and Strings *******************************/
 
 static const struct {
-	struct usb_functionfs_descs_head header;
+	struct usb_functionfs_descs_head_v2 header;
+	__le32 fs_count;
+	__le32 hs_count;
 	struct {
 		struct usb_interface_descriptor intf;
 		struct usb_endpoint_descriptor_no_audio bulk_sink;
@@ -35,11 +64,12 @@
 	} __attribute__ ((__packed__)) fs_descs, hs_descs;
 } __attribute__ ((__packed__)) descriptors = {
 	.header = {
-		.magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC),
+		.magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2),
+		.flags = htole32(FUNCTIONFS_HAS_FS_DESC |
+				     FUNCTIONFS_HAS_HS_DESC),
 		.length = htole32(sizeof(descriptors)),
-		.fs_count = 3,
-		.hs_count = 3,
 	},
+	.fs_count = htole32(3),
 	.fs_descs = {
 		.intf = {
 			.bLength = sizeof(descriptors.fs_descs.intf),
@@ -61,6 +91,7 @@
 			.bmAttributes = USB_ENDPOINT_XFER_BULK,
 		},
 	},
+	.hs_count = htole32(3),
 	.hs_descs = {
 		.intf = {
 			.bLength = sizeof(descriptors.hs_descs.intf),
diff --git a/tools/usb/ffs-aio-example/multibuff/host_app/test.c b/tools/usb/ffs-aio-example/multibuff/host_app/test.c
index b0ad874..daa3abe 100644
--- a/tools/usb/ffs-aio-example/multibuff/host_app/test.c
+++ b/tools/usb/ffs-aio-example/multibuff/host_app/test.c
@@ -1,3 +1,30 @@
+/*
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * For more information, please refer to <http://unlicense.org/>
+ */
+
 #include <libusb.h>
 #include <stdio.h>
 #include <string.h>
diff --git a/tools/usb/ffs-aio-example/simple/device_app/aio_simple.c b/tools/usb/ffs-aio-example/simple/device_app/aio_simple.c
index f558664..adc310a 100644
--- a/tools/usb/ffs-aio-example/simple/device_app/aio_simple.c
+++ b/tools/usb/ffs-aio-example/simple/device_app/aio_simple.c
@@ -1,3 +1,30 @@
+/*
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * For more information, please refer to <http://unlicense.org/>
+ */
+
 #define _BSD_SOURCE /* for endian.h */
 
 #include <endian.h>
@@ -25,7 +52,9 @@
 /******************** Descriptors and Strings *******************************/
 
 static const struct {
-	struct usb_functionfs_descs_head header;
+	struct usb_functionfs_descs_head_v2 header;
+	__le32 fs_count;
+	__le32 hs_count;
 	struct {
 		struct usb_interface_descriptor intf;
 		struct usb_endpoint_descriptor_no_audio bulk_sink;
@@ -33,11 +62,12 @@
 	} __attribute__ ((__packed__)) fs_descs, hs_descs;
 } __attribute__ ((__packed__)) descriptors = {
 	.header = {
-		.magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC),
+		.magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2),
+		.flags = htole32(FUNCTIONFS_HAS_FS_DESC |
+				     FUNCTIONFS_HAS_HS_DESC),
 		.length = htole32(sizeof(descriptors)),
-		.fs_count = 3,
-		.hs_count = 3,
 	},
+	.fs_count = htole32(3),
 	.fs_descs = {
 		.intf = {
 			.bLength = sizeof(descriptors.fs_descs.intf),
@@ -59,6 +89,7 @@
 			.bmAttributes = USB_ENDPOINT_XFER_BULK,
 		},
 	},
+	.hs_count = htole32(3),
 	.hs_descs = {
 		.intf = {
 			.bLength = sizeof(descriptors.hs_descs.intf),
diff --git a/tools/usb/ffs-aio-example/simple/host_app/test.c b/tools/usb/ffs-aio-example/simple/host_app/test.c
index 64b6a57..acd6332 100644
--- a/tools/usb/ffs-aio-example/simple/host_app/test.c
+++ b/tools/usb/ffs-aio-example/simple/host_app/test.c
@@ -1,3 +1,30 @@
+/*
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * For more information, please refer to <http://unlicense.org/>
+ */
+
 #include <libusb.h>
 #include <stdio.h>
 #include <string.h>