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

Felipe writes:

usb: changes for v3.14 merge window

This pull request is quite extensive, containing
105 non-merge commits. Because of that, we describe
the changes in sections below:

New drivers:
	- Keystone PHY driver and DWC3 Glue Layer
	- Aeroflex Gaisler GRUSBDC
	- Tahvo PHY driver for N770
	- JZ4740 MUSB gluer Layer
	- Broadcom PHY Driver

Important new features:
	- MUSB DSPS learned about suspend/resume
	- New quirk_ep_out_aligned_size flag added to struct usb_gadget
	- DWC3 initializes the new quirk flag so gadget drivers can use it.
	- AM335x PHY Driver learns about remote wakeup
	- Renesas USBHS now requests DMA Engine only once
	- s3c-hsotg is now re-used on Broadcom devices
	- USB PHY layer now makes sure to initialize the notifier for all
		drivers
	- omap-control learned about TI's new AM437x devices
	- few other usb gadget/function drivers learned about the new
		configfs-based binding.

Misc Fixes and Clean Ups:
	- Several sparse fixes all over the place
	- Removal of redundant of_match_ptr()
	- r-car gen2 phy now uses usb_add_phy_dev()
	- removal of DEFINE_PCI_DEVICE_TABLE() from a few drivers
	- conversion to clk_prepare/clk_unprepare on r8a66597-udc
	- some randconfig errors and build warnings were fixed
	- removal of unnecessary lock on dwc3-omap.c

Signed-of-by: Felipe Balbi <balbi@ti.com>
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-ffs b/Documentation/ABI/testing/configfs-usb-gadget-ffs
new file mode 100644
index 0000000..14343e2
--- /dev/null
+++ b/Documentation/ABI/testing/configfs-usb-gadget-ffs
@@ -0,0 +1,9 @@
+What:		/config/usb-gadget/gadget/functions/ffs.name
+Date:		Nov 2013
+KenelVersion:	3.13
+Description:	The purpose of this directory is to create and remove it.
+
+		A corresponding USB function instance is created/removed.
+		There are no attributes here.
+
+		All parameters are set through FunctionFS.
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-loopback b/Documentation/ABI/testing/configfs-usb-gadget-loopback
new file mode 100644
index 0000000..852b236
--- /dev/null
+++ b/Documentation/ABI/testing/configfs-usb-gadget-loopback
@@ -0,0 +1,8 @@
+What:		/config/usb-gadget/gadget/functions/Loopback.name
+Date:		Nov 2013
+KenelVersion:	3.13
+Description:
+		The attributes:
+
+		qlen		- depth of loopback queue
+		bulk_buflen	- buffer length
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-sourcesink b/Documentation/ABI/testing/configfs-usb-gadget-sourcesink
new file mode 100644
index 0000000..a30f309
--- /dev/null
+++ b/Documentation/ABI/testing/configfs-usb-gadget-sourcesink
@@ -0,0 +1,12 @@
+What:		/config/usb-gadget/gadget/functions/SourceSink.name
+Date:		Nov 2013
+KenelVersion:	3.13
+Description:
+		The attributes:
+
+		pattern		- 0 (all zeros), 1 (mod63), 2 (none)
+		isoc_interval	- 1..16
+		isoc_maxpacket	- 0 - 1023 (fs), 0 - 1024 (hs/ss)
+		isoc_mult	- 0..2 (hs/ss only)
+		isoc_maxburst	- 0..15 (ss only)
+		qlen		- buffer length
diff --git a/Documentation/ABI/testing/sysfs-platform-tahvo-usb b/Documentation/ABI/testing/sysfs-platform-tahvo-usb
new file mode 100644
index 0000000..f6e20ce
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-tahvo-usb
@@ -0,0 +1,16 @@
+What:		/sys/bus/platform/devices/tahvo-usb/otg_mode
+Date:		December 2013
+Contact:	Aaro Koskinen <aaro.koskinen@iki.fi>
+Description:
+		Set or read the current OTG mode. Valid values are "host" and
+		"peripheral".
+
+		Reading: returns the current mode.
+
+What:		/sys/bus/platform/devices/tahvo-usb/vbus
+Date:		December 2013
+Contact:	Aaro Koskinen <aaro.koskinen@iki.fi>
+Description:
+		Read the current VBUS state.
+
+		Reading: returns "on" or "off".
diff --git a/Documentation/devicetree/bindings/phy/bcm-phy.txt b/Documentation/devicetree/bindings/phy/bcm-phy.txt
new file mode 100644
index 0000000..3dc8b3d
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/bcm-phy.txt
@@ -0,0 +1,15 @@
+BROADCOM KONA USB2 PHY
+
+Required properties:
+ - compatible: brcm,kona-usb2-phy
+ - reg: offset and length of the PHY registers
+ - #phy-cells: must be 0
+Refer to phy/phy-bindings.txt for the generic PHY binding properties
+
+Example:
+
+	usbphy: usb-phy@3f130000 {
+		compatible = "brcm,kona-usb2-phy";
+		reg = <0x3f130000 0x28>;
+		#phy-cells = <0>;
+	};
diff --git a/Documentation/devicetree/bindings/staging/dwc2.txt b/Documentation/devicetree/bindings/staging/dwc2.txt
index 1a1b7cf..a1753ed 100644
--- a/Documentation/devicetree/bindings/staging/dwc2.txt
+++ b/Documentation/devicetree/bindings/staging/dwc2.txt
@@ -5,6 +5,14 @@
 - compatible : "snps,dwc2"
 - reg : Should contain 1 register range (address and length)
 - interrupts : Should contain 1 interrupt
+- clocks: clock provider specifier
+- clock-names: shall be "otg"
+Refer to clk/clock-bindings.txt for generic clock consumer properties
+
+Optional properties:
+- phys: phy provider specifier
+- phy-names: shall be "device"
+Refer to phy/phy-bindings.txt for generic phy consumer properties
 
 Example:
 
@@ -12,4 +20,8 @@
                 compatible = "ralink,rt3050-usb, snps,dwc2";
                 reg = <0x101c0000 40000>;
                 interrupts = <18>;
+		clocks = <&usb_otg_ahb_clk>;
+		clock-names = "otg";
+		phys = <&usbphy>;
+		phy-names = "usb2-phy";
         };
diff --git a/Documentation/devicetree/bindings/usb/gr-udc.txt b/Documentation/devicetree/bindings/usb/gr-udc.txt
new file mode 100644
index 0000000..0c5118f
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/gr-udc.txt
@@ -0,0 +1,28 @@
+USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC.
+
+The GRUSBDC USB Device Controller core is available in the GRLIB VHDL
+IP core library.
+
+Note: In the ordinary environment for the core, a Leon SPARC system,
+these properties are built from information in the AMBA plug&play.
+
+Required properties:
+
+- name : Should be "GAISLER_USBDC" or "01_021"
+
+- reg : Address and length of the register set for the device
+
+- interrupts : Interrupt numbers for this device
+
+Optional properties:
+
+- epobufsizes : An array of buffer sizes for OUT endpoints. If the property is
+	not present, or for endpoints outside of the array, 1024 is assumed by
+	the driver.
+
+- epibufsizes : An array of buffer sizes for IN endpoints. If the property is
+	not present, or for endpoints outside of the array, 1024 is assumed by
+	the driver.
+
+For further information look in the documentation for the GLIB IP core library:
+http://www.gaisler.com/products/grlib/grip.pdf
diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt
index 090e5e2..c495135 100644
--- a/Documentation/devicetree/bindings/usb/omap-usb.txt
+++ b/Documentation/devicetree/bindings/usb/omap-usb.txt
@@ -87,6 +87,8 @@
 			e.g. USB3 PHY and SATA PHY on OMAP5.
  "ti,control-phy-dra7usb2" - if it has power down register like USB2 PHY on
 			DRA7 platform.
+ "ti,control-phy-am437usb2" - if it has power down register like USB2 PHY on
+			AM437 platform.
  - reg : Address and length of the register set for the device. It contains
    the address of "otghs_control" for control-phy-otghs or "power" register
    for other types.
diff --git a/arch/arm/mach-omap1/include/mach/usb.h b/arch/arm/mach-omap1/include/mach/usb.h
index 45e5ac7..2c26305 100644
--- a/arch/arm/mach-omap1/include/mach/usb.h
+++ b/arch/arm/mach-omap1/include/mach/usb.h
@@ -8,43 +8,7 @@
 #define	is_usb0_device(config)	0
 #endif
 
-struct omap_usb_config {
-	/* Configure drivers according to the connectors on your board:
-	 *  - "A" connector (rectagular)
-	 *	... for host/OHCI use, set "register_host".
-	 *  - "B" connector (squarish) or "Mini-B"
-	 *	... for device/gadget use, set "register_dev".
-	 *  - "Mini-AB" connector (very similar to Mini-B)
-	 *	... for OTG use as device OR host, initialize "otg"
-	 */
-	unsigned	register_host:1;
-	unsigned	register_dev:1;
-	u8		otg;	/* port number, 1-based:  usb1 == 2 */
-
-	u8		hmc_mode;
-
-	/* implicitly true if otg:  host supports remote wakeup? */
-	u8		rwc;
-
-	/* signaling pins used to talk to transceiver on usbN:
-	 *  0 == usbN unused
-	 *  2 == usb0-only, using internal transceiver
-	 *  3 == 3 wire bidirectional
-	 *  4 == 4 wire bidirectional
-	 *  6 == 6 wire unidirectional (or TLL)
-	 */
-	u8		pins[3];
-
-	struct platform_device *udc_device;
-	struct platform_device *ohci_device;
-	struct platform_device *otg_device;
-
-	u32 (*usb0_init)(unsigned nwires, unsigned is_device);
-	u32 (*usb1_init)(unsigned nwires);
-	u32 (*usb2_init)(unsigned nwires, unsigned alt_pingroup);
-
-	int (*ocpi_enable)(void);
-};
+#include <linux/platform_data/usb-omap1.h>
 
 void omap_otg_init(struct omap_usb_config *config);
 
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 330ef2d..a49e853 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -51,4 +51,10 @@
 	help
 	  Support for Display Port PHY found on Samsung EXYNOS SoCs.
 
+config BCM_KONA_USB2_PHY
+	tristate "Broadcom Kona USB2 PHY Driver"
+	depends on GENERIC_PHY
+	help
+	  Enable this to support the Broadcom Kona USB 2.0 PHY.
+
 endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index d0caae9..c447f1a 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o
+obj-$(CONFIG_BCM_KONA_USB2_PHY)		+= phy-bcm-kona-usb2.o
 obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)	+= phy-exynos-dp-video.o
 obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)	+= phy-exynos-mipi-video.o
 obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o
diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c
new file mode 100644
index 0000000..efc5c1a
--- /dev/null
+++ b/drivers/phy/phy-bcm-kona-usb2.c
@@ -0,0 +1,158 @@
+/*
+ * phy-bcm-kona-usb2.c - Broadcom Kona USB2 Phy Driver
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Matt Porter <mporter@linaro.org>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+#define OTGCTL			(0)
+#define OTGCTL_OTGSTAT2		BIT(31)
+#define OTGCTL_OTGSTAT1		BIT(30)
+#define OTGCTL_PRST_N_SW	BIT(11)
+#define OTGCTL_HRESET_N		BIT(10)
+#define OTGCTL_UTMI_LINE_STATE1	BIT(9)
+#define OTGCTL_UTMI_LINE_STATE0	BIT(8)
+
+#define P1CTL			(8)
+#define P1CTL_SOFT_RESET	BIT(1)
+#define P1CTL_NON_DRIVING	BIT(0)
+
+struct bcm_kona_usb {
+	void __iomem *regs;
+};
+
+static void bcm_kona_usb_phy_power(struct bcm_kona_usb *phy, int on)
+{
+	u32 val;
+
+	val = readl(phy->regs + OTGCTL);
+	if (on) {
+		/* Configure and power PHY */
+		val &= ~(OTGCTL_OTGSTAT2 | OTGCTL_OTGSTAT1 |
+			 OTGCTL_UTMI_LINE_STATE1 | OTGCTL_UTMI_LINE_STATE0);
+		val |= OTGCTL_PRST_N_SW | OTGCTL_HRESET_N;
+	} else {
+		val &= ~(OTGCTL_PRST_N_SW | OTGCTL_HRESET_N);
+	}
+	writel(val, phy->regs + OTGCTL);
+}
+
+static int bcm_kona_usb_phy_init(struct phy *gphy)
+{
+	struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
+	u32 val;
+
+	/* Soft reset PHY */
+	val = readl(phy->regs + P1CTL);
+	val &= ~P1CTL_NON_DRIVING;
+	val |= P1CTL_SOFT_RESET;
+	writel(val, phy->regs + P1CTL);
+	writel(val & ~P1CTL_SOFT_RESET, phy->regs + P1CTL);
+	/* Reset needs to be asserted for 2ms */
+	mdelay(2);
+	writel(val | P1CTL_SOFT_RESET, phy->regs + P1CTL);
+
+	return 0;
+}
+
+static int bcm_kona_usb_phy_power_on(struct phy *gphy)
+{
+	struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
+
+	bcm_kona_usb_phy_power(phy, 1);
+
+	return 0;
+}
+
+static int bcm_kona_usb_phy_power_off(struct phy *gphy)
+{
+	struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
+
+	bcm_kona_usb_phy_power(phy, 0);
+
+	return 0;
+}
+
+static struct phy_ops ops = {
+	.init		= bcm_kona_usb_phy_init,
+	.power_on	= bcm_kona_usb_phy_power_on,
+	.power_off	= bcm_kona_usb_phy_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static int bcm_kona_usb2_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct bcm_kona_usb *phy;
+	struct resource *res;
+	struct phy *gphy;
+	struct phy_provider *phy_provider;
+
+	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	phy->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(phy->regs))
+		return PTR_ERR(phy->regs);
+
+	platform_set_drvdata(pdev, phy);
+
+	gphy = devm_phy_create(dev, &ops, NULL);
+	if (IS_ERR(gphy))
+		return PTR_ERR(gphy);
+
+	/* The Kona PHY supports an 8-bit wide UTMI interface */
+	phy_set_bus_width(gphy, 8);
+
+	phy_set_drvdata(gphy, phy);
+
+	phy_provider = devm_of_phy_provider_register(dev,
+			of_phy_simple_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	return 0;
+}
+
+static const struct of_device_id bcm_kona_usb2_dt_ids[] = {
+	{ .compatible = "brcm,kona-usb2-phy" },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, bcm_kona_usb2_dt_ids);
+
+static struct platform_driver bcm_kona_usb2_driver = {
+	.probe		= bcm_kona_usb2_probe,
+	.driver		= {
+		.name	= "bcm-kona-usb2",
+		.owner	= THIS_MODULE,
+		.of_match_table = bcm_kona_usb2_dt_ids,
+	},
+};
+
+module_platform_driver(bcm_kona_usb2_driver);
+
+MODULE_ALIAS("platform:bcm-kona-usb2");
+MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
+MODULE_DESCRIPTION("BCM Kona USB 2.0 PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 2642b8a..a34fb98 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -94,8 +94,6 @@
 
 source "drivers/usb/host/Kconfig"
 
-source "drivers/usb/musb/Kconfig"
-
 source "drivers/usb/renesas_usbhs/Kconfig"
 
 source "drivers/usb/class/Kconfig"
@@ -106,6 +104,8 @@
 
 endif
 
+source "drivers/usb/musb/Kconfig"
+
 source "drivers/usb/dwc3/Kconfig"
 
 source "drivers/usb/chipidea/Kconfig"
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 69d20fb..73a39ef 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -1566,7 +1566,7 @@
 			 * eps, maxP is set by epautoconfig() called
 			 * by gadget layer
 			 */
-			hwep->ep.maxpacket = (unsigned short)~0;
+			usb_ep_set_maxpacket_limit(&hwep->ep, (unsigned short)~0);
 
 			INIT_LIST_HEAD(&hwep->qh.queue);
 			hwep->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL,
@@ -1586,7 +1586,7 @@
 				else
 					ci->ep0in = hwep;
 
-				hwep->ep.maxpacket = CTRL_PAYLOAD_MAX;
+				usb_ep_set_maxpacket_limit(&hwep->ep, CTRL_PAYLOAD_MAX);
 				continue;
 			}
 
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 70fc430..e2c730f 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -70,6 +70,13 @@
 	  One such PCIe-based platform is Synopsys' PCIe HAPS model of
 	  this IP.
 
+config USB_DWC3_KEYSTONE
+	tristate "Texas Instruments Keystone2 Platforms"
+	default USB_DWC3
+	help
+	  Support of USB2/3 functionality in TI Keystone2 platforms.
+	  Say 'Y' or 'M' here if you have one such device
+
 comment "Debugging features"
 
 config USB_DWC3_DEBUG
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index dd17601..10ac3e7 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -32,3 +32,4 @@
 obj-$(CONFIG_USB_DWC3_OMAP)		+= dwc3-omap.o
 obj-$(CONFIG_USB_DWC3_EXYNOS)		+= dwc3-exynos.o
 obj-$(CONFIG_USB_DWC3_PCI)		+= dwc3-pci.o
+obj-$(CONFIG_USB_DWC3_KEYSTONE)		+= dwc3-keystone.o
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index 8b20c70..28c8ad7 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -50,6 +50,7 @@
 
 	exynos->usb2_phy = pdev;
 	pdata.type = USB_PHY_TYPE_USB2;
+	pdata.gpio_reset = -1;
 
 	ret = platform_device_add_data(exynos->usb2_phy, &pdata, sizeof(pdata));
 	if (ret)
diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c
new file mode 100644
index 0000000..1fad161
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-keystone.c
@@ -0,0 +1,202 @@
+/**
+ * dwc3-keystone.c - Keystone Specific Glue layer
+ *
+ * Copyright (C) 2010-2013 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: WingMan Kwok <w-kwok2@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+
+/* USBSS register offsets */
+#define USBSS_REVISION		0x0000
+#define USBSS_SYSCONFIG		0x0010
+#define USBSS_IRQ_EOI		0x0018
+#define USBSS_IRQSTATUS_RAW_0	0x0020
+#define USBSS_IRQSTATUS_0	0x0024
+#define USBSS_IRQENABLE_SET_0	0x0028
+#define USBSS_IRQENABLE_CLR_0	0x002c
+
+/* IRQ register bits */
+#define USBSS_IRQ_EOI_LINE(n)	BIT(n)
+#define USBSS_IRQ_EVENT_ST	BIT(0)
+#define USBSS_IRQ_COREIRQ_EN	BIT(0)
+#define USBSS_IRQ_COREIRQ_CLR	BIT(0)
+
+static u64 kdwc3_dma_mask;
+
+struct dwc3_keystone {
+	struct device			*dev;
+	struct clk			*clk;
+	void __iomem			*usbss;
+};
+
+static inline u32 kdwc3_readl(void __iomem *base, u32 offset)
+{
+	return readl(base + offset);
+}
+
+static inline void kdwc3_writel(void __iomem *base, u32 offset, u32 value)
+{
+	writel(value, base + offset);
+}
+
+static void kdwc3_enable_irqs(struct dwc3_keystone *kdwc)
+{
+	u32 val;
+
+	val = kdwc3_readl(kdwc->usbss, USBSS_IRQENABLE_SET_0);
+	val |= USBSS_IRQ_COREIRQ_EN;
+	kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_SET_0, val);
+}
+
+static void kdwc3_disable_irqs(struct dwc3_keystone *kdwc)
+{
+	u32 val;
+
+	val = kdwc3_readl(kdwc->usbss, USBSS_IRQENABLE_SET_0);
+	val &= ~USBSS_IRQ_COREIRQ_EN;
+	kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_SET_0, val);
+}
+
+static irqreturn_t dwc3_keystone_interrupt(int irq, void *_kdwc)
+{
+	struct dwc3_keystone	*kdwc = _kdwc;
+
+	kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_CLR_0, USBSS_IRQ_COREIRQ_CLR);
+	kdwc3_writel(kdwc->usbss, USBSS_IRQSTATUS_0, USBSS_IRQ_EVENT_ST);
+	kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_SET_0, USBSS_IRQ_COREIRQ_EN);
+	kdwc3_writel(kdwc->usbss, USBSS_IRQ_EOI, USBSS_IRQ_EOI_LINE(0));
+
+	return IRQ_HANDLED;
+}
+
+static int kdwc3_probe(struct platform_device *pdev)
+{
+	struct device		*dev = &pdev->dev;
+	struct device_node	*node = pdev->dev.of_node;
+	struct dwc3_keystone	*kdwc;
+	struct resource		*res;
+	int			error, irq;
+
+	kdwc = devm_kzalloc(dev, sizeof(*kdwc), GFP_KERNEL);
+	if (!kdwc)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, kdwc);
+
+	kdwc->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "missing usbss resource\n");
+		return -EINVAL;
+	}
+
+	kdwc->usbss = devm_ioremap_resource(dev, res);
+	if (IS_ERR(kdwc->usbss))
+		return PTR_ERR(kdwc->usbss);
+
+	kdwc3_dma_mask = dma_get_mask(dev);
+	dev->dma_mask = &kdwc3_dma_mask;
+
+	kdwc->clk = devm_clk_get(kdwc->dev, "usb");
+
+	error = clk_prepare_enable(kdwc->clk);
+	if (error < 0) {
+		dev_dbg(kdwc->dev, "unable to enable usb clock, err %d\n",
+			error);
+		return error;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "missing irq\n");
+		goto err_irq;
+	}
+
+	error = devm_request_irq(dev, irq, dwc3_keystone_interrupt, IRQF_SHARED,
+			dev_name(dev), kdwc);
+	if (error) {
+		dev_err(dev, "failed to request IRQ #%d --> %d\n",
+				irq, error);
+		goto err_irq;
+	}
+
+	kdwc3_enable_irqs(kdwc);
+
+	error = of_platform_populate(node, NULL, NULL, dev);
+	if (error) {
+		dev_err(&pdev->dev, "failed to create dwc3 core\n");
+		goto err_core;
+	}
+
+	return 0;
+
+err_core:
+	kdwc3_disable_irqs(kdwc);
+err_irq:
+	clk_disable_unprepare(kdwc->clk);
+
+	return error;
+}
+
+static int kdwc3_remove_core(struct device *dev, void *c)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	platform_device_unregister(pdev);
+
+	return 0;
+}
+
+static int kdwc3_remove(struct platform_device *pdev)
+{
+	struct dwc3_keystone *kdwc = platform_get_drvdata(pdev);
+
+	kdwc3_disable_irqs(kdwc);
+	device_for_each_child(&pdev->dev, NULL, kdwc3_remove_core);
+	clk_disable_unprepare(kdwc->clk);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static const struct of_device_id kdwc3_of_match[] = {
+	{ .compatible = "ti,keystone-dwc3", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, kdwc3_of_match);
+
+static struct platform_driver kdwc3_driver = {
+	.probe		= kdwc3_probe,
+	.remove		= kdwc3_remove,
+	.driver		= {
+		.name	= "keystone-dwc3",
+		.owner	        = THIS_MODULE,
+		.of_match_table	= kdwc3_of_match,
+	},
+};
+
+module_platform_driver(kdwc3_driver);
+
+MODULE_ALIAS("platform:keystone-dwc3");
+MODULE_AUTHOR("WingMan Kwok <w-kwok2@ti.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("DesignWare USB3 KEYSTONE Glue Layer");
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 7f7ea62..b269dbd 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/spinlock.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/dwc3-omap.h>
 #include <linux/pm_runtime.h>
@@ -120,9 +119,6 @@
 #define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID	(1 << 1)
 
 struct dwc3_omap {
-	/* device lock */
-	spinlock_t		lock;
-
 	struct device		*dev;
 
 	int			irq;
@@ -280,8 +276,6 @@
 	struct dwc3_omap	*omap = _omap;
 	u32			reg;
 
-	spin_lock(&omap->lock);
-
 	reg = dwc3_omap_read_irqmisc_status(omap);
 
 	if (reg & USBOTGSS_IRQMISC_DMADISABLECLR) {
@@ -322,8 +316,6 @@
 
 	dwc3_omap_write_irq0_status(omap, reg);
 
-	spin_unlock(&omap->lock);
-
 	return IRQ_HANDLED;
 }
 
@@ -449,8 +441,6 @@
 		}
 	}
 
-	spin_lock_init(&omap->lock);
-
 	omap->dev	= dev;
 	omap->irq	= irq;
 	omap->base	= base;
@@ -535,7 +525,7 @@
 		edev = of_extcon_get_extcon_dev(dev, 0);
 		if (IS_ERR(edev)) {
 			dev_vdbg(dev, "couldn't get extcon device\n");
-			ret = PTR_ERR(edev);
+			ret = -EPROBE_DEFER;
 			goto err2;
 		}
 
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 665686e..f393c18 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -52,6 +52,7 @@
 
 	glue->usb2_phy = pdev;
 	pdata.type = USB_PHY_TYPE_USB2;
+	pdata.gpio_reset = -1;
 
 	ret = platform_device_add_data(glue->usb2_phy, &pdata, sizeof(pdata));
 	if (ret)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 02e44fc..2da0a5a 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1650,7 +1650,7 @@
 		dev_vdbg(dwc->dev, "initializing %s\n", dep->name);
 
 		if (epnum == 0 || epnum == 1) {
-			dep->endpoint.maxpacket = 512;
+			usb_ep_set_maxpacket_limit(&dep->endpoint, 512);
 			dep->endpoint.maxburst = 1;
 			dep->endpoint.ops = &dwc3_gadget_ep0_ops;
 			if (!epnum)
@@ -1658,7 +1658,7 @@
 		} else {
 			int		ret;
 
-			dep->endpoint.maxpacket = 1024;
+			usb_ep_set_maxpacket_limit(&dep->endpoint, 1024);
 			dep->endpoint.max_streams = 15;
 			dep->endpoint.ops = &dwc3_gadget_ep_ops;
 			list_add_tail(&dep->endpoint.ep_list,
@@ -2597,6 +2597,12 @@
 	dwc->gadget.name		= "dwc3-gadget";
 
 	/*
+	 * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize
+	 * on ep out.
+	 */
+	dwc->gadget.quirk_ep_out_aligned_size = true;
+
+	/*
 	 * REVISIT: Here we should clear all pending IRQs to be
 	 * sure we're starting from a well known location.
 	 */
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index f66d96a..8154165 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -216,6 +216,13 @@
 	   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
@@ -294,11 +301,11 @@
 	   gadget drivers to also be dynamically linked.
 
 config USB_S3C_HSOTG
-	tristate "S3C HS/OtG USB Device controller"
-	depends on S3C_DEV_USB_HSOTG
+	depends on ARM
+	tristate "Designware/S3C HS/OtG USB Device controller"
 	help
-	  The Samsung S3C64XX USB2.0 high-speed gadget controller
-	  integrated into the S3C64XX series SoC.
+	  The Designware USB2.0 high-speed gadget controller
+	  integrated into many SoCs.
 
 config USB_S3C2410
 	tristate "S3C2410 USB Device Controller"
@@ -512,9 +519,6 @@
 config USB_U_ETHER
 	tristate
 
-config USB_U_RNDIS
-	tristate
-
 config USB_F_SERIAL
 	tristate
 
@@ -542,6 +546,9 @@
 config USB_F_MASS_STORAGE
 	tristate
 
+config USB_F_FS
+	tristate
+
 choice
 	tristate "USB Gadget Drivers"
 	default USB_ETH
@@ -642,7 +649,6 @@
 	depends on USB_CONFIGFS
 	depends on NET
 	select USB_U_ETHER
-	select USB_U_RNDIS
 	select USB_F_RNDIS
 	help
 	   Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
@@ -690,6 +696,31 @@
 	  device (in much the same way as the "loop" device driver),
 	  specified as a module parameter or sysfs option.
 
+config USB_CONFIGFS_F_LB_SS
+	boolean "Loopback and sourcesink function (for testing)"
+	depends on USB_CONFIGFS
+	select USB_F_SS_LB
+	help
+	  Loopback function loops back a configurable number of transfers.
+	  Sourcesink function either sinks and sources bulk data.
+	  It also implements control requests, for "chapter 9" conformance.
+	  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.
+
+config USB_CONFIGFS_F_FS
+	boolean "Function filesystem (FunctionFS)"
+	depends on USB_CONFIGFS
+	select USB_F_FS
+	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.
+
 config USB_ZERO
 	tristate "Gadget Zero (DEVELOPMENT)"
 	select USB_LIBCOMPOSITE
@@ -760,7 +791,6 @@
 	depends on NET
 	select USB_LIBCOMPOSITE
 	select USB_U_ETHER
-	select USB_U_RNDIS
 	select USB_F_ECM
 	select USB_F_SUBSET
 	select CRC32
@@ -864,6 +894,7 @@
 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
@@ -883,6 +914,8 @@
 	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.
@@ -891,7 +924,7 @@
 	bool "Include configuration with RNDIS (Ethernet)"
 	depends on USB_FUNCTIONFS && NET
 	select USB_U_ETHER
-	select USB_U_RNDIS
+	select USB_F_RNDIS
 	help
 	  Include a configuration with RNDIS function (Ethernet) and the Filesystem.
 
@@ -1065,7 +1098,6 @@
 config USB_G_MULTI_RNDIS
 	bool "RNDIS + CDC Serial + Storage configuration"
 	depends on USB_G_MULTI
-	select USB_U_RNDIS
 	select USB_F_RNDIS
 	default y
 	help
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index f1af396..5f150bc 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -7,7 +7,7 @@
 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
+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
@@ -35,6 +35,7 @@
 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
@@ -47,8 +48,6 @@
 usb_f_obex-y			:= f_obex.o
 obj-$(CONFIG_USB_F_OBEX)	+= usb_f_obex.o
 obj-$(CONFIG_USB_U_ETHER)	+= u_ether.o
-u_rndis-y			:= rndis.o
-obj-$(CONFIG_USB_U_RNDIS)	+= u_rndis.o
 usb_f_ncm-y			:= f_ncm.o
 obj-$(CONFIG_USB_F_NCM)		+= usb_f_ncm.o
 usb_f_ecm-y			:= f_ecm.o
@@ -59,10 +58,12 @@
 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
+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
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index f0ff4a6..a04aa8b 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -446,7 +446,7 @@
 	ep->ep.ops = &udc_ep_ops;
 	INIT_LIST_HEAD(&ep->queue);
 
-	ep->ep.maxpacket = (u16) ~0;
+	usb_ep_set_maxpacket_limit(&ep->ep,(u16) ~0);
 	/* set NAK */
 	tmp = readl(&ep->regs->ctl);
 	tmp |= AMD_BIT(UDC_EPCTL_SNAK);
@@ -1564,12 +1564,15 @@
 	}
 	/* EP0 max packet */
 	if (dev->gadget.speed == USB_SPEED_FULL) {
-		dev->ep[UDC_EP0IN_IX].ep.maxpacket = UDC_FS_EP0IN_MAX_PKT_SIZE;
-		dev->ep[UDC_EP0OUT_IX].ep.maxpacket =
-						UDC_FS_EP0OUT_MAX_PKT_SIZE;
+		usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IX].ep,
+					   UDC_FS_EP0IN_MAX_PKT_SIZE);
+		usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IX].ep,
+					   UDC_FS_EP0OUT_MAX_PKT_SIZE);
 	} else if (dev->gadget.speed == USB_SPEED_HIGH) {
-		dev->ep[UDC_EP0IN_IX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE;
-		dev->ep[UDC_EP0OUT_IX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE;
+		usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IX].ep,
+					   UDC_EP0IN_MAX_PKT_SIZE);
+		usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IX].ep,
+					   UDC_EP0OUT_MAX_PKT_SIZE);
 	}
 
 	/*
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 4cc4fd6..c3f49fd 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -834,7 +834,7 @@
 		ep->ep.desc = NULL;
 		ep->stopped = 0;
 		ep->fifo_bank = 0;
-		ep->ep.maxpacket = ep->maxpacket;
+		usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
 		ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i);
 		/* initialize one queue per endpoint */
 		INIT_LIST_HEAD(&ep->queue);
@@ -1759,15 +1759,15 @@
 
 	/* newer chips have more FIFO memory than rm9200 */
 	if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) {
-		udc->ep[0].maxpacket = 64;
-		udc->ep[3].maxpacket = 64;
-		udc->ep[4].maxpacket = 512;
-		udc->ep[5].maxpacket = 512;
+		usb_ep_set_maxpacket_limit(&udc->ep[0].ep, 64);
+		usb_ep_set_maxpacket_limit(&udc->ep[3].ep, 64);
+		usb_ep_set_maxpacket_limit(&udc->ep[4].ep, 512);
+		usb_ep_set_maxpacket_limit(&udc->ep[5].ep, 512);
 	} else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
-		udc->ep[3].maxpacket = 64;
+		usb_ep_set_maxpacket_limit(&udc->ep[3].ep, 64);
 	} else if (cpu_is_at91sam9263()) {
-		udc->ep[0].maxpacket = 64;
-		udc->ep[3].maxpacket = 64;
+		usb_ep_set_maxpacket_limit(&udc->ep[0].ep, 64);
+		usb_ep_set_maxpacket_limit(&udc->ep[3].ep, 64);
 	}
 
 	udc->udp_baseaddr = ioremap(res->start, resource_size(res));
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 2cb52e0..38bf67b 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -1012,7 +1012,7 @@
 
 }
 
-struct usb_gadget usba_gadget_template = {
+static struct usb_gadget usba_gadget_template = {
 	.ops		= &usba_udc_ops,
 	.max_speed	= USB_SPEED_HIGH,
 	.name		= "atmel_usba_udc",
@@ -1904,7 +1904,7 @@
 		ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
 		ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
 		ep->ep.ops = &usba_ep_ops;
-		ep->ep.maxpacket = ep->fifo_size;
+		usb_ep_set_maxpacket_limit(&ep->ep, ep->fifo_size);
 		ep->udc = udc;
 		INIT_LIST_HEAD(&ep->queue);
 
@@ -1957,7 +1957,8 @@
 		ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
 		ep->ep.ops = &usba_ep_ops;
 		ep->ep.name = pdata->ep[i].name;
-		ep->fifo_size = ep->ep.maxpacket = pdata->ep[i].fifo_size;
+		ep->fifo_size = pdata->ep[i].fifo_size;
+		usb_ep_set_maxpacket_limit(&ep->ep, ep->fifo_size);
 		ep->udc = udc;
 		INIT_LIST_HEAD(&ep->queue);
 		ep->nr_banks = pdata->ep[i].nr_banks;
@@ -1995,14 +1996,12 @@
 	if (irq < 0)
 		return irq;
 
-	pclk = clk_get(&pdev->dev, "pclk");
+	pclk = devm_clk_get(&pdev->dev, "pclk");
 	if (IS_ERR(pclk))
 		return PTR_ERR(pclk);
-	hclk = clk_get(&pdev->dev, "hclk");
-	if (IS_ERR(hclk)) {
-		ret = PTR_ERR(hclk);
-		goto err_get_hclk;
-	}
+	hclk = devm_clk_get(&pdev->dev, "hclk");
+	if (IS_ERR(hclk))
+		return PTR_ERR(hclk);
 
 	spin_lock_init(&udc->lock);
 	udc->pdev = pdev;
@@ -2011,17 +2010,17 @@
 	udc->vbus_pin = -ENODEV;
 
 	ret = -ENOMEM;
-	udc->regs = ioremap(regs->start, resource_size(regs));
+	udc->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
 	if (!udc->regs) {
 		dev_err(&pdev->dev, "Unable to map I/O memory, aborting.\n");
-		goto err_map_regs;
+		return ret;
 	}
 	dev_info(&pdev->dev, "MMIO registers at 0x%08lx mapped at %p\n",
 		 (unsigned long)regs->start, udc->regs);
-	udc->fifo = ioremap(fifo->start, resource_size(fifo));
+	udc->fifo = devm_ioremap(&pdev->dev, fifo->start, resource_size(fifo));
 	if (!udc->fifo) {
 		dev_err(&pdev->dev, "Unable to map FIFO, aborting.\n");
-		goto err_map_fifo;
+		return ret;
 	}
 	dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
 		 (unsigned long)fifo->start, udc->fifo);
@@ -2032,7 +2031,7 @@
 	ret = clk_prepare_enable(pclk);
 	if (ret) {
 		dev_err(&pdev->dev, "Unable to enable pclk, aborting.\n");
-		goto err_clk_enable;
+		return ret;
 	}
 	toggle_bias(0);
 	usba_writel(udc, CTRL, USBA_DISABLE_MASK);
@@ -2043,22 +2042,22 @@
 	else
 		udc->usba_ep = usba_udc_pdata(pdev, udc);
 
-	if (IS_ERR(udc->usba_ep)) {
-		ret = PTR_ERR(udc->usba_ep);
-		goto err_alloc_ep;
-	}
+	if (IS_ERR(udc->usba_ep))
+		return PTR_ERR(udc->usba_ep);
 
-	ret = request_irq(irq, usba_udc_irq, 0, "atmel_usba_udc", udc);
+	ret = devm_request_irq(&pdev->dev, irq, usba_udc_irq, 0,
+				"atmel_usba_udc", udc);
 	if (ret) {
 		dev_err(&pdev->dev, "Cannot request irq %d (error %d)\n",
 			irq, ret);
-		goto err_request_irq;
+		return ret;
 	}
 	udc->irq = irq;
 
 	if (gpio_is_valid(udc->vbus_pin)) {
 		if (!devm_gpio_request(&pdev->dev, udc->vbus_pin, "atmel_usba_udc")) {
-			ret = request_irq(gpio_to_irq(udc->vbus_pin),
+			ret = devm_request_irq(&pdev->dev,
+					gpio_to_irq(udc->vbus_pin),
 					usba_vbus_irq, 0,
 					"atmel_usba_udc", udc);
 			if (ret) {
@@ -2077,31 +2076,13 @@
 
 	ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
 	if (ret)
-		goto err_add_udc;
+		return ret;
 
 	usba_init_debugfs(udc);
 	for (i = 1; i < udc->num_ep; i++)
 		usba_ep_init_debugfs(udc, &udc->usba_ep[i]);
 
 	return 0;
-
-err_add_udc:
-	if (gpio_is_valid(udc->vbus_pin))
-		free_irq(gpio_to_irq(udc->vbus_pin), udc);
-
-	free_irq(irq, udc);
-err_request_irq:
-err_alloc_ep:
-err_clk_enable:
-	iounmap(udc->fifo);
-err_map_fifo:
-	iounmap(udc->regs);
-err_map_regs:
-	clk_put(hclk);
-err_get_hclk:
-	clk_put(pclk);
-
-	return ret;
 }
 
 static int __exit usba_udc_remove(struct platform_device *pdev)
@@ -2117,16 +2098,6 @@
 		usba_ep_cleanup_debugfs(&udc->usba_ep[i]);
 	usba_cleanup_debugfs(udc);
 
-	if (gpio_is_valid(udc->vbus_pin)) {
-		free_irq(gpio_to_irq(udc->vbus_pin), udc);
-	}
-
-	free_irq(udc->irq, udc);
-	iounmap(udc->fifo);
-	iounmap(udc->regs);
-	clk_put(udc->hclk);
-	clk_put(udc->pclk);
-
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c
index c58fcf1..2ac7a8f 100644
--- a/drivers/usb/gadget/bcm63xx_udc.c
+++ b/drivers/usb/gadget/bcm63xx_udc.c
@@ -549,7 +549,7 @@
 
 		if (idx < 0)
 			continue;
-		udc->bep[idx].ep.maxpacket = max_pkt;
+		usb_ep_set_maxpacket_limit(&udc->bep[idx].ep, max_pkt);
 
 		val = (idx << USBD_CSR_EP_LOG_SHIFT) |
 		      (cfg->dir << USBD_CSR_EP_DIR_SHIFT) |
@@ -943,7 +943,7 @@
 		bep->ep.ops = &bcm63xx_udc_ep_ops;
 		list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list);
 		bep->halted = 0;
-		bep->ep.maxpacket = BCM63XX_MAX_CTRL_PKT;
+		usb_ep_set_maxpacket_limit(&bep->ep, BCM63XX_MAX_CTRL_PKT);
 		bep->udc = udc;
 		bep->ep.desc = NULL;
 		INIT_LIST_HEAD(&bep->queue);
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 2018ba1..d742bed 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1452,8 +1452,22 @@
 			struct usb_configuration	*c;
 
 			c = cdev->config;
-			if (c && c->setup)
+			if (!c)
+				goto done;
+
+			/* try current config's setup */
+			if (c->setup) {
 				value = c->setup(c, ctrl);
+				goto done;
+			}
+
+			/* try the only function in the current config */
+			if (!list_is_singular(&c->functions))
+				goto done;
+			f = list_first_entry(&c->functions, struct usb_function,
+					     list);
+			if (f->setup)
+				value = f->setup(f, ctrl);
 		}
 
 		goto done;
@@ -1714,7 +1728,7 @@
 {
 	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
 	struct usb_function		*f;
-	u8				maxpower;
+	u16				maxpower;
 
 	/* REVISIT:  should we have config level
 	 * suspend/resume callbacks?
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 2588511..7d1cc01 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -4,6 +4,7 @@
 #include <linux/device.h>
 #include <linux/usb/composite.h>
 #include <linux/usb/gadget_configfs.h>
+#include "configfs.h"
 
 int check_user_usb_string(const char *name,
 		struct usb_gadget_strings *stringtab_dev)
@@ -564,6 +565,13 @@
 		usb_put_function_instance(fi);
 		return ERR_PTR(ret);
 	}
+	if (fi->set_inst_name) {
+		ret = fi->set_inst_name(fi, instance_name);
+		if (ret) {
+			usb_put_function_instance(fi);
+			return ERR_PTR(ret);
+		}
+	}
 
 	gi = container_of(group, struct gadget_info, functions_group);
 
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 8f4dae3..8c06430 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -951,7 +951,7 @@
 		list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list);
 		ep->halted = ep->wedged = ep->already_seen =
 				ep->setup_stage = 0;
-		ep->ep.maxpacket = ~0;
+		usb_ep_set_maxpacket_limit(&ep->ep, ~0);
 		ep->ep.max_streams = 16;
 		ep->last_io = jiffies;
 		ep->gadget = &dum->gadget;
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index a777f7b..358de32 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -58,7 +58,7 @@
 		return 0;
 
 	/* only support ep0 for portable CONTROL traffic */
-	type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+	type = usb_endpoint_type(desc);
 	if (USB_ENDPOINT_XFER_CONTROL == type)
 		return 0;
 
@@ -129,7 +129,7 @@
 	 * and wants to know the maximum possible, provide the info.
 	 */
 	if (desc->wMaxPacketSize == 0)
-		desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket);
+		desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit);
 
 	/* endpoint maxpacket size is an input parameter, except for bulk
 	 * where it's an output parameter representing the full speed limit.
@@ -145,7 +145,7 @@
 
 	case USB_ENDPOINT_XFER_ISOC:
 		/* ISO:  limit 1023 bytes full speed, 1024 high/super speed */
-		if (ep->maxpacket < max)
+		if (ep->maxpacket_limit < max)
 			return 0;
 		if (!gadget_is_dualspeed(gadget) && max > 1023)
 			return 0;
@@ -178,7 +178,7 @@
 
 	/* report (variable) full speed bulk maxpacket */
 	if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) {
-		int size = ep->maxpacket;
+		int size = ep->maxpacket_limit;
 
 		/* min() doesn't work on bitfields with gcc-3.5 */
 		if (size > 64)
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index 8d9e6f7..798760f 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -691,7 +691,6 @@
 	int			status;
 	struct usb_ep		*ep;
 
-#ifndef USBF_ECM_INCLUDED
 	struct f_ecm_opts	*ecm_opts;
 
 	if (!can_support_ecm(cdev->gadget))
@@ -715,7 +714,7 @@
 			return status;
 		ecm_opts->bound = true;
 	}
-#endif
+
 	us = usb_gstrings_attach(cdev, ecm_strings,
 				 ARRAY_SIZE(ecm_string_defs));
 	if (IS_ERR(us))
@@ -834,74 +833,6 @@
 	return status;
 }
 
-#ifdef USBF_ECM_INCLUDED
-
-static void
-ecm_old_unbind(struct usb_configuration *c, struct usb_function *f)
-{
-	struct f_ecm		*ecm = func_to_ecm(f);
-
-	DBG(c->cdev, "ecm unbind\n");
-
-	usb_free_all_descriptors(f);
-
-	kfree(ecm->notify_req->buf);
-	usb_ep_free_request(ecm->notify, ecm->notify_req);
-	kfree(ecm);
-}
-
-/**
- * ecm_bind_config - add CDC Ethernet network link to a configuration
- * @c: the configuration to support the network link
- * @ethaddr: a buffer in which the ethernet address of the host side
- *	side of the link was recorded
- * @dev: eth_dev structure
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- *
- * Caller must have called @gether_setup().  Caller is also responsible
- * for calling @gether_cleanup() before module unload.
- */
-int
-ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-		struct eth_dev *dev)
-{
-	struct f_ecm	*ecm;
-	int		status;
-
-	if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
-		return -EINVAL;
-
-	/* allocate and initialize one new instance */
-	ecm = kzalloc(sizeof *ecm, GFP_KERNEL);
-	if (!ecm)
-		return -ENOMEM;
-
-	/* export host's Ethernet address in CDC format */
-	snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);
-	ecm_string_defs[1].s = ecm->ethaddr;
-
-	ecm->port.ioport = dev;
-	ecm->port.cdc_filter = DEFAULT_FILTER;
-
-	ecm->port.func.name = "cdc_ethernet";
-	/* descriptors are per-instance copies */
-	ecm->port.func.bind = ecm_bind;
-	ecm->port.func.unbind = ecm_old_unbind;
-	ecm->port.func.set_alt = ecm_set_alt;
-	ecm->port.func.get_alt = ecm_get_alt;
-	ecm->port.func.setup = ecm_setup;
-	ecm->port.func.disable = ecm_disable;
-
-	status = usb_add_function(c, &ecm->port.func);
-	if (status)
-		kfree(ecm);
-	return status;
-}
-
-#else
-
 static inline struct f_ecm_opts *to_f_ecm_opts(struct config_item *item)
 {
 	return container_of(to_config_group(item), struct f_ecm_opts,
@@ -1040,5 +971,3 @@
 DECLARE_USB_FUNCTION_INIT(ecm, ecm_alloc_inst, ecm_alloc);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Brownell");
-
-#endif
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 241fc87..306a2b5 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -22,218 +22,42 @@
 #include <linux/pagemap.h>
 #include <linux/export.h>
 #include <linux/hid.h>
+#include <linux/module.h>
 #include <asm/unaligned.h>
 
 #include <linux/usb/composite.h>
 #include <linux/usb/functionfs.h>
 
+#include "u_fs.h"
+#include "configfs.h"
 
 #define FUNCTIONFS_MAGIC	0xa647361 /* Chosen by a honest dice roll ;) */
 
+/* Variable Length Array Macros **********************************************/
+#define vla_group(groupname) size_t groupname##__next = 0
+#define vla_group_size(groupname) groupname##__next
 
-/* Debugging ****************************************************************/
+#define vla_item(groupname, type, name, n) \
+	size_t groupname##_##name##__offset = ({			       \
+		size_t align_mask = __alignof__(type) - 1;		       \
+		size_t offset = (groupname##__next + align_mask) & ~align_mask;\
+		size_t size = (n) * sizeof(type);			       \
+		groupname##__next = offset + size;			       \
+		offset;							       \
+	})
 
-#ifdef VERBOSE_DEBUG
-#ifndef pr_vdebug
-#  define pr_vdebug pr_debug
-#endif /* pr_vdebug */
-#  define ffs_dump_mem(prefix, ptr, len) \
-	print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len)
-#else
-#ifndef pr_vdebug
-#  define pr_vdebug(...)                 do { } while (0)
-#endif /* pr_vdebug */
-#  define ffs_dump_mem(prefix, ptr, len) do { } while (0)
-#endif /* VERBOSE_DEBUG */
+#define vla_item_with_sz(groupname, type, name, n) \
+	size_t groupname##_##name##__sz = (n) * sizeof(type);		       \
+	size_t groupname##_##name##__offset = ({			       \
+		size_t align_mask = __alignof__(type) - 1;		       \
+		size_t offset = (groupname##__next + align_mask) & ~align_mask;\
+		size_t size = groupname##_##name##__sz;			       \
+		groupname##__next = offset + size;			       \
+		offset;							       \
+	})
 
-#define ENTER()    pr_vdebug("%s()\n", __func__)
-
-
-/* The data structure and setup file ****************************************/
-
-enum ffs_state {
-	/*
-	 * Waiting for descriptors and strings.
-	 *
-	 * In this state no open(2), read(2) or write(2) on epfiles
-	 * may succeed (which should not be the problem as there
-	 * should be no such files opened in the first place).
-	 */
-	FFS_READ_DESCRIPTORS,
-	FFS_READ_STRINGS,
-
-	/*
-	 * We've got descriptors and strings.  We are or have called
-	 * functionfs_ready_callback().  functionfs_bind() may have
-	 * been called but we don't know.
-	 *
-	 * This is the only state in which operations on epfiles may
-	 * succeed.
-	 */
-	FFS_ACTIVE,
-
-	/*
-	 * All endpoints have been closed.  This state is also set if
-	 * we encounter an unrecoverable error.  The only
-	 * unrecoverable error is situation when after reading strings
-	 * from user space we fail to initialise epfiles or
-	 * functionfs_ready_callback() returns with error (<0).
-	 *
-	 * In this state no open(2), read(2) or write(2) (both on ep0
-	 * as well as epfile) may succeed (at this point epfiles are
-	 * unlinked and all closed so this is not a problem; ep0 is
-	 * also closed but ep0 file exists and so open(2) on ep0 must
-	 * fail).
-	 */
-	FFS_CLOSING
-};
-
-
-enum ffs_setup_state {
-	/* There is no setup request pending. */
-	FFS_NO_SETUP,
-	/*
-	 * User has read events and there was a setup request event
-	 * there.  The next read/write on ep0 will handle the
-	 * request.
-	 */
-	FFS_SETUP_PENDING,
-	/*
-	 * There was event pending but before user space handled it
-	 * some other event was introduced which canceled existing
-	 * setup.  If this state is set read/write on ep0 return
-	 * -EIDRM.  This state is only set when adding event.
-	 */
-	FFS_SETUP_CANCELED
-};
-
-
-
-struct ffs_epfile;
-struct ffs_function;
-
-struct ffs_data {
-	struct usb_gadget		*gadget;
-
-	/*
-	 * Protect access read/write operations, only one read/write
-	 * at a time.  As a consequence protects ep0req and company.
-	 * While setup request is being processed (queued) this is
-	 * held.
-	 */
-	struct mutex			mutex;
-
-	/*
-	 * Protect access to endpoint related structures (basically
-	 * usb_ep_queue(), usb_ep_dequeue(), etc. calls) except for
-	 * endpoint zero.
-	 */
-	spinlock_t			eps_lock;
-
-	/*
-	 * XXX REVISIT do we need our own request? Since we are not
-	 * handling setup requests immediately user space may be so
-	 * slow that another setup will be sent to the gadget but this
-	 * time not to us but another function and then there could be
-	 * a race.  Is that the case? Or maybe we can use cdev->req
-	 * after all, maybe we just need some spinlock for that?
-	 */
-	struct usb_request		*ep0req;		/* P: mutex */
-	struct completion		ep0req_completion;	/* P: mutex */
-	int				ep0req_status;		/* P: mutex */
-
-	/* reference counter */
-	atomic_t			ref;
-	/* how many files are opened (EP0 and others) */
-	atomic_t			opened;
-
-	/* EP0 state */
-	enum ffs_state			state;
-
-	/*
-	 * Possible transitions:
-	 * + FFS_NO_SETUP       -> FFS_SETUP_PENDING  -- P: ev.waitq.lock
-	 *               happens only in ep0 read which is P: mutex
-	 * + FFS_SETUP_PENDING  -> FFS_NO_SETUP       -- P: ev.waitq.lock
-	 *               happens only in ep0 i/o  which is P: mutex
-	 * + FFS_SETUP_PENDING  -> FFS_SETUP_CANCELED -- P: ev.waitq.lock
-	 * + FFS_SETUP_CANCELED -> FFS_NO_SETUP       -- cmpxchg
-	 */
-	enum ffs_setup_state		setup_state;
-
-#define FFS_SETUP_STATE(ffs)					\
-	((enum ffs_setup_state)cmpxchg(&(ffs)->setup_state,	\
-				       FFS_SETUP_CANCELED, FFS_NO_SETUP))
-
-	/* Events & such. */
-	struct {
-		u8				types[4];
-		unsigned short			count;
-		/* XXX REVISIT need to update it in some places, or do we? */
-		unsigned short			can_stall;
-		struct usb_ctrlrequest		setup;
-
-		wait_queue_head_t		waitq;
-	} ev; /* the whole structure, P: ev.waitq.lock */
-
-	/* Flags */
-	unsigned long			flags;
-#define FFS_FL_CALL_CLOSED_CALLBACK 0
-#define FFS_FL_BOUND                1
-
-	/* Active function */
-	struct ffs_function		*func;
-
-	/*
-	 * Device name, write once when file system is mounted.
-	 * Intended for user to read if she wants.
-	 */
-	const char			*dev_name;
-	/* Private data for our user (ie. gadget).  Managed by user. */
-	void				*private_data;
-
-	/* filled by __ffs_data_got_descs() */
-	/*
-	 * Real descriptors are 16 bytes after raw_descs (so you need
-	 * to skip 16 bytes (ie. ffs->raw_descs + 16) to get to the
-	 * first full speed descriptor).  raw_descs_length and
-	 * raw_fs_descs_length do not have those 16 bytes added.
-	 */
-	const void			*raw_descs;
-	unsigned			raw_descs_length;
-	unsigned			raw_fs_descs_length;
-	unsigned			fs_descs_count;
-	unsigned			hs_descs_count;
-
-	unsigned short			strings_count;
-	unsigned short			interfaces_count;
-	unsigned short			eps_count;
-	unsigned short			_pad1;
-
-	/* filled by __ffs_data_got_strings() */
-	/* ids in stringtabs are set in functionfs_bind() */
-	const void			*raw_strings;
-	struct usb_gadget_strings	**stringtabs;
-
-	/*
-	 * File system's super block, write once when file system is
-	 * mounted.
-	 */
-	struct super_block		*sb;
-
-	/* File permissions, written once when fs is mounted */
-	struct ffs_file_perms {
-		umode_t				mode;
-		kuid_t				uid;
-		kgid_t				gid;
-	}				file_perms;
-
-	/*
-	 * The endpoint files, filled by ffs_epfiles_create(),
-	 * destroyed by ffs_epfiles_destroy().
-	 */
-	struct ffs_epfile		*epfiles;
-};
+#define vla_ptr(ptr, groupname, name) \
+	((void *) ((char *)ptr + groupname##_##name##__offset))
 
 /* Reference counter handling */
 static void ffs_data_get(struct ffs_data *ffs);
@@ -274,15 +98,12 @@
 	return container_of(f, struct ffs_function, function);
 }
 
-static void ffs_func_free(struct ffs_function *func);
 
 static void ffs_func_eps_disable(struct ffs_function *func);
 static int __must_check ffs_func_eps_enable(struct ffs_function *func);
 
 static int ffs_func_bind(struct usb_configuration *,
 			 struct usb_function *);
-static void ffs_func_unbind(struct usb_configuration *,
-			    struct usb_function *);
 static int ffs_func_set_alt(struct usb_function *, unsigned, unsigned);
 static void ffs_func_disable(struct usb_function *);
 static int ffs_func_setup(struct usb_function *,
@@ -335,6 +156,17 @@
 		   const struct file_operations *fops,
 		   struct dentry **dentry_p);
 
+/* Devices management *******************************************************/
+
+DEFINE_MUTEX(ffs_lock);
+EXPORT_SYMBOL(ffs_lock);
+
+static struct ffs_dev *ffs_find_dev(const char *name);
+static int _ffs_name_dev(struct ffs_dev *dev, const char *name);
+static void *ffs_acquire_dev(const char *dev_name);
+static void ffs_release_dev(struct ffs_data *ffs_data);
+static int ffs_ready(struct ffs_data *ffs);
+static void ffs_closed(struct ffs_data *ffs);
 
 /* Misc helper functions ****************************************************/
 
@@ -460,7 +292,7 @@
 			ffs->state = FFS_ACTIVE;
 			mutex_unlock(&ffs->mutex);
 
-			ret = functionfs_ready_callback(ffs);
+			ret = ffs_ready(ffs);
 			if (unlikely(ret < 0)) {
 				ffs->state = FFS_CLOSING;
 				return ret;
@@ -753,78 +585,71 @@
 			     char __user *buf, size_t len, int read)
 {
 	struct ffs_epfile *epfile = file->private_data;
+	struct usb_gadget *gadget = epfile->ffs->gadget;
 	struct ffs_ep *ep;
 	char *data = NULL;
-	ssize_t ret;
+	ssize_t ret, data_len;
 	int halt;
 
-	goto first_try;
-	do {
+	/* Are we still active? */
+	if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) {
+		ret = -ENODEV;
+		goto error;
+	}
+
+	/* Wait for endpoint to be enabled */
+	ep = epfile->ep;
+	if (!ep) {
+		if (file->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			goto error;
+		}
+
+		ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep));
+		if (ret) {
+			ret = -EINTR;
+			goto error;
+		}
+	}
+
+	/* Do we halt? */
+	halt = !read == !epfile->in;
+	if (halt && epfile->isoc) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* Allocate & copy */
+	if (!halt) {
+		/*
+		 * Controller may require buffer size to be aligned to
+		 * maxpacketsize of an out endpoint.
+		 */
+		data_len = read ? usb_ep_align_maybe(gadget, ep->ep, len) : len;
+
+		data = kmalloc(data_len, GFP_KERNEL);
+		if (unlikely(!data))
+			return -ENOMEM;
+
+		if (!read && unlikely(copy_from_user(data, buf, len))) {
+			ret = -EFAULT;
+			goto error;
+		}
+	}
+
+	/* We will be using request */
+	ret = ffs_mutex_lock(&epfile->mutex, file->f_flags & O_NONBLOCK);
+	if (unlikely(ret))
+		goto error;
+
+	spin_lock_irq(&epfile->ffs->eps_lock);
+
+	if (epfile->ep != ep) {
+		/* In the meantime, endpoint got disabled or changed. */
+		ret = -ESHUTDOWN;
 		spin_unlock_irq(&epfile->ffs->eps_lock);
-		mutex_unlock(&epfile->mutex);
-
-first_try:
-		/* Are we still active? */
-		if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) {
-			ret = -ENODEV;
-			goto error;
-		}
-
-		/* Wait for endpoint to be enabled */
-		ep = epfile->ep;
-		if (!ep) {
-			if (file->f_flags & O_NONBLOCK) {
-				ret = -EAGAIN;
-				goto error;
-			}
-
-			if (wait_event_interruptible(epfile->wait,
-						     (ep = epfile->ep))) {
-				ret = -EINTR;
-				goto error;
-			}
-		}
-
-		/* Do we halt? */
-		halt = !read == !epfile->in;
-		if (halt && epfile->isoc) {
-			ret = -EINVAL;
-			goto error;
-		}
-
-		/* Allocate & copy */
-		if (!halt && !data) {
-			data = kzalloc(len, GFP_KERNEL);
-			if (unlikely(!data))
-				return -ENOMEM;
-
-			if (!read &&
-			    unlikely(__copy_from_user(data, buf, len))) {
-				ret = -EFAULT;
-				goto error;
-			}
-		}
-
-		/* We will be using request */
-		ret = ffs_mutex_lock(&epfile->mutex,
-				     file->f_flags & O_NONBLOCK);
-		if (unlikely(ret))
-			goto error;
-
-		/*
-		 * We're called from user space, we can use _irq rather then
-		 * _irqsave
-		 */
-		spin_lock_irq(&epfile->ffs->eps_lock);
-
-		/*
-		 * While we were acquiring mutex endpoint got disabled
-		 * or changed?
-		 */
-	} while (unlikely(epfile->ep != ep));
-
-	/* Halt */
-	if (unlikely(halt)) {
+	} else if (halt) {
+		/* Halt */
 		if (likely(epfile->ep == ep) && !WARN_ON(!ep->ep))
 			usb_ep_set_halt(ep->ep);
 		spin_unlock_irq(&epfile->ffs->eps_lock);
@@ -837,7 +662,7 @@
 		req->context  = &done;
 		req->complete = ffs_epfile_io_complete;
 		req->buf      = data;
-		req->length   = len;
+		req->length   = data_len;
 
 		ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
 
@@ -849,9 +674,17 @@
 			ret = -EINTR;
 			usb_ep_dequeue(ep->ep, req);
 		} else {
+			/*
+			 * XXX We may end up silently droping data here.
+			 * Since data_len (i.e. req->length) may be bigger
+			 * than len (after being rounded up to maxpacketsize),
+			 * we may end up with more data then user space has
+			 * space for.
+			 */
 			ret = ep->status;
 			if (read && ret > 0 &&
-			    unlikely(copy_to_user(buf, data, ret)))
+			    unlikely(copy_to_user(buf, data,
+						  min_t(size_t, ret, len))))
 				ret = -EFAULT;
 		}
 	}
@@ -1191,7 +1024,7 @@
 		return ERR_PTR(-ENOMEM);
 	}
 
-	ffs_dev = functionfs_acquire_dev_callback(dev_name);
+	ffs_dev = ffs_acquire_dev(dev_name);
 	if (IS_ERR(ffs_dev)) {
 		ffs_data_put(ffs);
 		return ERR_CAST(ffs_dev);
@@ -1201,7 +1034,7 @@
 
 	rv = mount_nodev(t, flags, &data, ffs_sb_fill);
 	if (IS_ERR(rv) && data.ffs_data) {
-		functionfs_release_dev_callback(data.ffs_data);
+		ffs_release_dev(data.ffs_data);
 		ffs_data_put(data.ffs_data);
 	}
 	return rv;
@@ -1214,7 +1047,7 @@
 
 	kill_litter_super(sb);
 	if (sb->s_fs_info) {
-		functionfs_release_dev_callback(sb->s_fs_info);
+		ffs_release_dev(sb->s_fs_info);
 		ffs_data_put(sb->s_fs_info);
 	}
 }
@@ -1327,7 +1160,7 @@
 	ENTER();
 
 	if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags))
-		functionfs_closed_callback(ffs);
+		ffs_closed(ffs);
 
 	BUG_ON(ffs->gadget);
 
@@ -1463,71 +1296,6 @@
 	kfree(epfiles);
 }
 
-static int functionfs_bind_config(struct usb_composite_dev *cdev,
-				  struct usb_configuration *c,
-				  struct ffs_data *ffs)
-{
-	struct ffs_function *func;
-	int ret;
-
-	ENTER();
-
-	func = kzalloc(sizeof *func, GFP_KERNEL);
-	if (unlikely(!func))
-		return -ENOMEM;
-
-	func->function.name    = "Function FS Gadget";
-	func->function.strings = ffs->stringtabs;
-
-	func->function.bind    = ffs_func_bind;
-	func->function.unbind  = ffs_func_unbind;
-	func->function.set_alt = ffs_func_set_alt;
-	func->function.disable = ffs_func_disable;
-	func->function.setup   = ffs_func_setup;
-	func->function.suspend = ffs_func_suspend;
-	func->function.resume  = ffs_func_resume;
-
-	func->conf   = c;
-	func->gadget = cdev->gadget;
-	func->ffs = ffs;
-	ffs_data_get(ffs);
-
-	ret = usb_add_function(c, &func->function);
-	if (unlikely(ret))
-		ffs_func_free(func);
-
-	return ret;
-}
-
-static void ffs_func_free(struct ffs_function *func)
-{
-	struct ffs_ep *ep         = func->eps;
-	unsigned count            = func->ffs->eps_count;
-	unsigned long flags;
-
-	ENTER();
-
-	/* cleanup after autoconfig */
-	spin_lock_irqsave(&func->ffs->eps_lock, flags);
-	do {
-		if (ep->ep && ep->req)
-			usb_ep_free_request(ep->ep, ep->req);
-		ep->req = NULL;
-		++ep;
-	} while (--count);
-	spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
-
-	ffs_data_put(func->ffs);
-
-	kfree(func->eps);
-	/*
-	 * eps and interfaces_nums are allocated in the same chunk so
-	 * only one free is required.  Descriptors are also allocated
-	 * in the same chunk.
-	 */
-
-	kfree(func);
-}
 
 static void ffs_func_eps_disable(struct ffs_function *func)
 {
@@ -1901,30 +1669,34 @@
 
 	/* Allocate everything in one chunk so there's less maintenance. */
 	{
-		struct {
-			struct usb_gadget_strings *stringtabs[lang_count + 1];
-			struct usb_gadget_strings stringtab[lang_count];
-			struct usb_string strings[lang_count*(needed_count+1)];
-		} *d;
 		unsigned i = 0;
+		vla_group(d);
+		vla_item(d, struct usb_gadget_strings *, stringtabs,
+			lang_count + 1);
+		vla_item(d, struct usb_gadget_strings, stringtab, lang_count);
+		vla_item(d, struct usb_string, strings,
+			lang_count*(needed_count+1));
 
-		d = kmalloc(sizeof *d, GFP_KERNEL);
-		if (unlikely(!d)) {
+		char *vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL);
+
+		if (unlikely(!vlabuf)) {
 			kfree(_data);
 			return -ENOMEM;
 		}
 
-		stringtabs = d->stringtabs;
-		t = d->stringtab;
+		/* Initialize the VLA pointers */
+		stringtabs = vla_ptr(vlabuf, d, stringtabs);
+		t = vla_ptr(vlabuf, d, stringtab);
 		i = lang_count;
 		do {
 			*stringtabs++ = t++;
 		} while (--i);
 		*stringtabs = NULL;
 
-		stringtabs = d->stringtabs;
-		t = d->stringtab;
-		s = d->strings;
+		/* stringtabs = vlabuf = d_stringtabs for later kfree */
+		stringtabs = vla_ptr(vlabuf, d, stringtabs);
+		t = vla_ptr(vlabuf, d, stringtab);
+		s = vla_ptr(vlabuf, d, strings);
 		strings = s;
 	}
 
@@ -2187,8 +1959,57 @@
 	return 0;
 }
 
-static int ffs_func_bind(struct usb_configuration *c,
-			 struct usb_function *f)
+static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
+						struct usb_configuration *c)
+{
+	struct ffs_function *func = ffs_func_from_usb(f);
+	struct f_fs_opts *ffs_opts =
+		container_of(f->fi, struct f_fs_opts, func_inst);
+	int ret;
+
+	ENTER();
+
+	/*
+	 * Legacy gadget triggers binding in functionfs_ready_callback,
+	 * which already uses locking; taking the same lock here would
+	 * cause a deadlock.
+	 *
+	 * Configfs-enabled gadgets however do need ffs_dev_lock.
+	 */
+	if (!ffs_opts->no_configfs)
+		ffs_dev_lock();
+	ret = ffs_opts->dev->desc_ready ? 0 : -ENODEV;
+	func->ffs = ffs_opts->dev->ffs_data;
+	if (!ffs_opts->no_configfs)
+		ffs_dev_unlock();
+	if (ret)
+		return ERR_PTR(ret);
+
+	func->conf = c;
+	func->gadget = c->cdev->gadget;
+
+	ffs_data_get(func->ffs);
+
+	/*
+	 * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
+	 * configurations are bound in sequence with list_for_each_entry,
+	 * in each configuration its functions are bound in sequence
+	 * with list_for_each_entry, so we assume no race condition
+	 * with regard to ffs_opts->bound access
+	 */
+	if (!ffs_opts->refcnt) {
+		ret = functionfs_bind(func->ffs, c->cdev);
+		if (ret)
+			return ERR_PTR(ret);
+	}
+	ffs_opts->refcnt++;
+	func->function.strings = func->ffs->stringtabs;
+
+	return ffs_opts;
+}
+
+static int _ffs_func_bind(struct usb_configuration *c,
+			  struct usb_function *f)
 {
 	struct ffs_function *func = ffs_func_from_usb(f);
 	struct ffs_data *ffs = func->ffs;
@@ -2200,16 +2021,16 @@
 	int ret;
 
 	/* Make it a single chunk, less management later on */
-	struct {
-		struct ffs_ep eps[ffs->eps_count];
-		struct usb_descriptor_header
-			*fs_descs[full ? ffs->fs_descs_count + 1 : 0];
-		struct usb_descriptor_header
-			*hs_descs[high ? ffs->hs_descs_count + 1 : 0];
-		short inums[ffs->interfaces_count];
-		char raw_descs[high ? ffs->raw_descs_length
-				    : ffs->raw_fs_descs_length];
-	} *data;
+	vla_group(d);
+	vla_item_with_sz(d, struct ffs_ep, eps, ffs->eps_count);
+	vla_item_with_sz(d, struct usb_descriptor_header *, fs_descs,
+		full ? ffs->fs_descs_count + 1 : 0);
+	vla_item_with_sz(d, struct usb_descriptor_header *, hs_descs,
+		high ? ffs->hs_descs_count + 1 : 0);
+	vla_item_with_sz(d, short, inums, ffs->interfaces_count);
+	vla_item_with_sz(d, char, raw_descs,
+		high ? ffs->raw_descs_length : ffs->raw_fs_descs_length);
+	char *vlabuf;
 
 	ENTER();
 
@@ -2217,21 +2038,28 @@
 	if (unlikely(!(full | high)))
 		return -ENOTSUPP;
 
-	/* Allocate */
-	data = kmalloc(sizeof *data, GFP_KERNEL);
-	if (unlikely(!data))
+	/* Allocate a single chunk, less management later on */
+	vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL);
+	if (unlikely(!vlabuf))
 		return -ENOMEM;
 
 	/* Zero */
-	memset(data->eps, 0, sizeof data->eps);
-	memcpy(data->raw_descs, ffs->raw_descs + 16, sizeof data->raw_descs);
-	memset(data->inums, 0xff, sizeof data->inums);
-	for (ret = ffs->eps_count; ret; --ret)
-		data->eps[ret].num = -1;
+	memset(vla_ptr(vlabuf, d, eps), 0, d_eps__sz);
+	memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs + 16,
+	       d_raw_descs__sz);
+	memset(vla_ptr(vlabuf, d, inums), 0xff, d_inums__sz);
+	for (ret = ffs->eps_count; ret; --ret) {
+		struct ffs_ep *ptr;
 
-	/* Save pointers */
-	func->eps             = data->eps;
-	func->interfaces_nums = data->inums;
+		ptr = vla_ptr(vlabuf, d, eps);
+		ptr[ret].num = -1;
+	}
+
+	/* Save pointers
+	 * d_eps == vlabuf, func->eps used to kfree vlabuf later
+	*/
+	func->eps             = vla_ptr(vlabuf, d, eps);
+	func->interfaces_nums = vla_ptr(vlabuf, d, inums);
 
 	/*
 	 * Go through all the endpoint descriptors and allocate
@@ -2239,10 +2067,10 @@
 	 * numbers without worrying that it may be described later on.
 	 */
 	if (likely(full)) {
-		func->function.fs_descriptors = data->fs_descs;
+		func->function.fs_descriptors = vla_ptr(vlabuf, d, fs_descs);
 		ret = ffs_do_descs(ffs->fs_descs_count,
-				   data->raw_descs,
-				   sizeof data->raw_descs,
+				   vla_ptr(vlabuf, d, raw_descs),
+				   d_raw_descs__sz,
 				   __ffs_func_bind_do_descs, func);
 		if (unlikely(ret < 0))
 			goto error;
@@ -2251,10 +2079,10 @@
 	}
 
 	if (likely(high)) {
-		func->function.hs_descriptors = data->hs_descs;
+		func->function.hs_descriptors = vla_ptr(vlabuf, d, hs_descs);
 		ret = ffs_do_descs(ffs->hs_descs_count,
-				   data->raw_descs + ret,
-				   (sizeof data->raw_descs) - ret,
+				   vla_ptr(vlabuf, d, raw_descs) + ret,
+				   d_raw_descs__sz - ret,
 				   __ffs_func_bind_do_descs, func);
 		if (unlikely(ret < 0))
 			goto error;
@@ -2267,7 +2095,7 @@
 	 */
 	ret = ffs_do_descs(ffs->fs_descs_count +
 			   (high ? ffs->hs_descs_count : 0),
-			   data->raw_descs, sizeof data->raw_descs,
+			   vla_ptr(vlabuf, d, raw_descs), d_raw_descs__sz,
 			   __ffs_func_bind_do_nums, func);
 	if (unlikely(ret < 0))
 		goto error;
@@ -2281,27 +2109,20 @@
 	return ret;
 }
 
+static int ffs_func_bind(struct usb_configuration *c,
+			 struct usb_function *f)
+{
+	struct f_fs_opts *ffs_opts = ffs_do_functionfs_bind(f, c);
+
+	if (IS_ERR(ffs_opts))
+		return PTR_ERR(ffs_opts);
+
+	return _ffs_func_bind(c, f);
+}
+
 
 /* Other USB function hooks *************************************************/
 
-static void ffs_func_unbind(struct usb_configuration *c,
-			    struct usb_function *f)
-{
-	struct ffs_function *func = ffs_func_from_usb(f);
-	struct ffs_data *ffs = func->ffs;
-
-	ENTER();
-
-	if (ffs->func == func) {
-		ffs_func_eps_disable(func);
-		ffs->func = NULL;
-	}
-
-	ffs_event_add(ffs, FUNCTIONFS_UNBIND);
-
-	ffs_func_free(func);
-}
-
 static int ffs_func_set_alt(struct usb_function *f,
 			    unsigned interface, unsigned alt)
 {
@@ -2428,6 +2249,411 @@
 }
 
 
+/* Devices management *******************************************************/
+
+static LIST_HEAD(ffs_devices);
+
+static struct ffs_dev *_ffs_find_dev(const char *name)
+{
+	struct ffs_dev *dev;
+
+	list_for_each_entry(dev, &ffs_devices, entry) {
+		if (!dev->name || !name)
+			continue;
+		if (strcmp(dev->name, name) == 0)
+			return dev;
+	}
+
+	return NULL;
+}
+
+/*
+ * ffs_lock must be taken by the caller of this function
+ */
+static struct ffs_dev *ffs_get_single_dev(void)
+{
+	struct ffs_dev *dev;
+
+	if (list_is_singular(&ffs_devices)) {
+		dev = list_first_entry(&ffs_devices, struct ffs_dev, entry);
+		if (dev->single)
+			return dev;
+	}
+
+	return NULL;
+}
+
+/*
+ * ffs_lock must be taken by the caller of this function
+ */
+static struct ffs_dev *ffs_find_dev(const char *name)
+{
+	struct ffs_dev *dev;
+
+	dev = ffs_get_single_dev();
+	if (dev)
+		return dev;
+
+	return _ffs_find_dev(name);
+}
+
+/* Configfs support *********************************************************/
+
+static inline struct f_fs_opts *to_ffs_opts(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct f_fs_opts,
+			    func_inst.group);
+}
+
+static void ffs_attr_release(struct config_item *item)
+{
+	struct f_fs_opts *opts = to_ffs_opts(item);
+
+	usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations ffs_item_ops = {
+	.release	= ffs_attr_release,
+};
+
+static struct config_item_type ffs_func_type = {
+	.ct_item_ops	= &ffs_item_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+
+/* Function registration interface ******************************************/
+
+static void ffs_free_inst(struct usb_function_instance *f)
+{
+	struct f_fs_opts *opts;
+
+	opts = to_f_fs_opts(f);
+	ffs_dev_lock();
+	ffs_free_dev(opts->dev);
+	ffs_dev_unlock();
+	kfree(opts);
+}
+
+#define MAX_INST_NAME_LEN	40
+
+static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name)
+{
+	struct f_fs_opts *opts;
+	char *ptr;
+	const char *tmp;
+	int name_len, ret;
+
+	name_len = strlen(name) + 1;
+	if (name_len > MAX_INST_NAME_LEN)
+		return -ENAMETOOLONG;
+
+	ptr = kstrndup(name, name_len, GFP_KERNEL);
+	if (!ptr)
+		return -ENOMEM;
+
+	opts = to_f_fs_opts(fi);
+	tmp = NULL;
+
+	ffs_dev_lock();
+
+	tmp = opts->dev->name_allocated ? opts->dev->name : NULL;
+	ret = _ffs_name_dev(opts->dev, ptr);
+	if (ret) {
+		kfree(ptr);
+		ffs_dev_unlock();
+		return ret;
+	}
+	opts->dev->name_allocated = true;
+
+	ffs_dev_unlock();
+
+	kfree(tmp);
+
+	return 0;
+}
+
+static struct usb_function_instance *ffs_alloc_inst(void)
+{
+	struct f_fs_opts *opts;
+	struct ffs_dev *dev;
+
+	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+	if (!opts)
+		return ERR_PTR(-ENOMEM);
+
+	opts->func_inst.set_inst_name = ffs_set_inst_name;
+	opts->func_inst.free_func_inst = ffs_free_inst;
+	ffs_dev_lock();
+	dev = ffs_alloc_dev();
+	ffs_dev_unlock();
+	if (IS_ERR(dev)) {
+		kfree(opts);
+		return ERR_CAST(dev);
+	}
+	opts->dev = dev;
+	dev->opts = opts;
+
+	config_group_init_type_name(&opts->func_inst.group, "",
+				    &ffs_func_type);
+	return &opts->func_inst;
+}
+
+static void ffs_free(struct usb_function *f)
+{
+	kfree(ffs_func_from_usb(f));
+}
+
+static void ffs_func_unbind(struct usb_configuration *c,
+			    struct usb_function *f)
+{
+	struct ffs_function *func = ffs_func_from_usb(f);
+	struct ffs_data *ffs = func->ffs;
+	struct f_fs_opts *opts =
+		container_of(f->fi, struct f_fs_opts, func_inst);
+	struct ffs_ep *ep = func->eps;
+	unsigned count = ffs->eps_count;
+	unsigned long flags;
+
+	ENTER();
+	if (ffs->func == func) {
+		ffs_func_eps_disable(func);
+		ffs->func = NULL;
+	}
+
+	if (!--opts->refcnt)
+		functionfs_unbind(ffs);
+
+	/* cleanup after autoconfig */
+	spin_lock_irqsave(&func->ffs->eps_lock, flags);
+	do {
+		if (ep->ep && ep->req)
+			usb_ep_free_request(ep->ep, ep->req);
+		ep->req = NULL;
+		++ep;
+	} while (--count);
+	spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
+	kfree(func->eps);
+	func->eps = NULL;
+	/*
+	 * eps, descriptors and interfaces_nums are allocated in the
+	 * same chunk so only one free is required.
+	 */
+	func->function.fs_descriptors = NULL;
+	func->function.hs_descriptors = NULL;
+	func->interfaces_nums = NULL;
+
+	ffs_event_add(ffs, FUNCTIONFS_UNBIND);
+}
+
+static struct usb_function *ffs_alloc(struct usb_function_instance *fi)
+{
+	struct ffs_function *func;
+
+	ENTER();
+
+	func = kzalloc(sizeof(*func), GFP_KERNEL);
+	if (unlikely(!func))
+		return ERR_PTR(-ENOMEM);
+
+	func->function.name    = "Function FS Gadget";
+
+	func->function.bind    = ffs_func_bind;
+	func->function.unbind  = ffs_func_unbind;
+	func->function.set_alt = ffs_func_set_alt;
+	func->function.disable = ffs_func_disable;
+	func->function.setup   = ffs_func_setup;
+	func->function.suspend = ffs_func_suspend;
+	func->function.resume  = ffs_func_resume;
+	func->function.free_func = ffs_free;
+
+	return &func->function;
+}
+
+/*
+ * ffs_lock must be taken by the caller of this function
+ */
+struct ffs_dev *ffs_alloc_dev(void)
+{
+	struct ffs_dev *dev;
+	int ret;
+
+	if (ffs_get_single_dev())
+			return ERR_PTR(-EBUSY);
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	if (list_empty(&ffs_devices)) {
+		ret = functionfs_init();
+		if (ret) {
+			kfree(dev);
+			return ERR_PTR(ret);
+		}
+	}
+
+	list_add(&dev->entry, &ffs_devices);
+
+	return dev;
+}
+
+/*
+ * ffs_lock must be taken by the caller of this function
+ * The caller is responsible for "name" being available whenever f_fs needs it
+ */
+static int _ffs_name_dev(struct ffs_dev *dev, const char *name)
+{
+	struct ffs_dev *existing;
+
+	existing = _ffs_find_dev(name);
+	if (existing)
+		return -EBUSY;
+	
+	dev->name = name;
+
+	return 0;
+}
+
+/*
+ * The caller is responsible for "name" being available whenever f_fs needs it
+ */
+int ffs_name_dev(struct ffs_dev *dev, const char *name)
+{
+	int ret;
+
+	ffs_dev_lock();
+	ret = _ffs_name_dev(dev, name);
+	ffs_dev_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL(ffs_name_dev);
+
+int ffs_single_dev(struct ffs_dev *dev)
+{
+	int ret;
+
+	ret = 0;
+	ffs_dev_lock();
+
+	if (!list_is_singular(&ffs_devices))
+		ret = -EBUSY;
+	else
+		dev->single = true;
+
+	ffs_dev_unlock();
+	return ret;
+}
+EXPORT_SYMBOL(ffs_single_dev);
+
+/*
+ * ffs_lock must be taken by the caller of this function
+ */
+void ffs_free_dev(struct ffs_dev *dev)
+{
+	list_del(&dev->entry);
+	if (dev->name_allocated)
+		kfree(dev->name);
+	kfree(dev);
+	if (list_empty(&ffs_devices))
+		functionfs_cleanup();
+}
+
+static void *ffs_acquire_dev(const char *dev_name)
+{
+	struct ffs_dev *ffs_dev;
+
+	ENTER();
+	ffs_dev_lock();
+
+	ffs_dev = ffs_find_dev(dev_name);
+	if (!ffs_dev)
+		ffs_dev = ERR_PTR(-ENODEV);
+	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);
+	else
+		ffs_dev->mounted = true;
+
+	ffs_dev_unlock();
+	return ffs_dev;
+}
+
+static void ffs_release_dev(struct ffs_data *ffs_data)
+{
+	struct ffs_dev *ffs_dev;
+
+	ENTER();
+	ffs_dev_lock();
+
+	ffs_dev = ffs_data->private_data;
+	if (ffs_dev)
+		ffs_dev->mounted = false;
+	
+	if (ffs_dev->ffs_release_dev_callback)
+		ffs_dev->ffs_release_dev_callback(ffs_dev);
+
+	ffs_dev_unlock();
+}
+
+static int ffs_ready(struct ffs_data *ffs)
+{
+	struct ffs_dev *ffs_obj;
+	int ret = 0;
+
+	ENTER();
+	ffs_dev_lock();
+
+	ffs_obj = ffs->private_data;
+	if (!ffs_obj) {
+		ret = -EINVAL;
+		goto done;
+	}
+	if (WARN_ON(ffs_obj->desc_ready)) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	ffs_obj->desc_ready = true;
+	ffs_obj->ffs_data = ffs;
+
+	if (ffs_obj->ffs_ready_callback)
+		ret = ffs_obj->ffs_ready_callback(ffs);
+
+done:
+	ffs_dev_unlock();
+	return ret;
+}
+
+static void ffs_closed(struct ffs_data *ffs)
+{
+	struct ffs_dev *ffs_obj;
+
+	ENTER();
+	ffs_dev_lock();
+
+	ffs_obj = ffs->private_data;
+	if (!ffs_obj)
+		goto done;
+
+	ffs_obj->desc_ready = false;
+
+	if (ffs_obj->ffs_closed_callback)
+		ffs_obj->ffs_closed_callback(ffs);
+
+	if (!ffs_obj->opts || ffs_obj->opts->no_configfs
+	    || !ffs_obj->opts->func_inst.group.cg_item.ci_parent)
+		goto done;
+
+	unregister_gadget_item(ffs_obj->opts->
+			       func_inst.group.cg_item.ci_parent->ci_parent);
+done:
+	ffs_dev_unlock();
+}
+
 /* Misc helper functions ****************************************************/
 
 static int ffs_mutex_lock(struct mutex *mutex, unsigned nonblock)
@@ -2458,3 +2684,7 @@
 
 	return data;
 }
+
+DECLARE_USB_FUNCTION_INIT(ffs, ffs_alloc_inst, ffs_alloc);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michal Nazarewicz");
diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c
index 6e69a8e..a95290a 100644
--- a/drivers/usb/gadget/f_hid.c
+++ b/drivers/usb/gadget/f_hid.c
@@ -20,6 +20,8 @@
 #include <linux/sched.h>
 #include <linux/usb/g_hid.h>
 
+#include "u_f.h"
+
 static int major, minors;
 static struct class *hidg_class;
 
@@ -334,20 +336,10 @@
 /*-------------------------------------------------------------------------*/
 /*                                usb_function                             */
 
-static struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep, unsigned length)
+static inline struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep,
+						    unsigned length)
 {
-	struct usb_request *req;
-
-	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
-	if (req) {
-		req->length = length;
-		req->buf = kmalloc(length, GFP_ATOMIC);
-		if (!req->buf) {
-			usb_ep_free_request(ep, req);
-			req = NULL;
-		}
-	}
-	return req;
+	return alloc_ep_req(ep, length, length);
 }
 
 static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index 4a3873a..4557cd0 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -20,6 +20,7 @@
 #include <linux/usb/composite.h>
 
 #include "g_zero.h"
+#include "u_f.h"
 
 /*
  * LOOPBACK FUNCTION ... a testing vehicle for USB peripherals,
@@ -119,7 +120,7 @@
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 
-struct usb_ss_ep_comp_descriptor ss_loop_source_comp_desc = {
+static struct usb_ss_ep_comp_descriptor ss_loop_source_comp_desc = {
 	.bLength =		USB_DT_SS_EP_COMP_SIZE,
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 	.bMaxBurst =		0,
@@ -135,7 +136,7 @@
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 
-struct usb_ss_ep_comp_descriptor ss_loop_sink_comp_desc = {
+static struct usb_ss_ep_comp_descriptor ss_loop_sink_comp_desc = {
 	.bLength =		USB_DT_SS_EP_COMP_SIZE,
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 	.bMaxBurst =		0,
@@ -230,6 +231,14 @@
 
 static void lb_free_func(struct usb_function *f)
 {
+	struct f_lb_opts *opts;
+
+	opts = container_of(f->fi, struct f_lb_opts, func_inst);
+
+	mutex_lock(&opts->lock);
+	opts->refcnt--;
+	mutex_unlock(&opts->lock);
+
 	usb_free_all_descriptors(f);
 	kfree(func_to_loop(f));
 }
@@ -293,6 +302,11 @@
 	VDBG(cdev, "%s disabled\n", loop->function.name);
 }
 
+static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len)
+{
+	return alloc_ep_req(ep, len, buflen);
+}
+
 static int
 enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
 {
@@ -332,7 +346,7 @@
 	 * than 'buflen' bytes each.
 	 */
 	for (i = 0; i < qlen && result == 0; i++) {
-		req = alloc_ep_req(ep, 0);
+		req = lb_alloc_ep_req(ep, 0);
 		if (req) {
 			req->complete = loopback_complete;
 			result = usb_ep_queue(ep, req, GFP_ATOMIC);
@@ -380,6 +394,11 @@
 		return ERR_PTR(-ENOMEM);
 
 	lb_opts = container_of(fi, struct f_lb_opts, func_inst);
+
+	mutex_lock(&lb_opts->lock);
+	lb_opts->refcnt++;
+	mutex_unlock(&lb_opts->lock);
+
 	buflen = lb_opts->bulk_buflen;
 	qlen = lb_opts->qlen;
 	if (!qlen)
@@ -396,6 +415,118 @@
 	return &loop->function;
 }
 
+static inline struct f_lb_opts *to_f_lb_opts(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct f_lb_opts,
+			    func_inst.group);
+}
+
+CONFIGFS_ATTR_STRUCT(f_lb_opts);
+CONFIGFS_ATTR_OPS(f_lb_opts);
+
+static void lb_attr_release(struct config_item *item)
+{
+	struct f_lb_opts *lb_opts = to_f_lb_opts(item);
+
+	usb_put_function_instance(&lb_opts->func_inst);
+}
+
+static struct configfs_item_operations lb_item_ops = {
+	.release		= lb_attr_release,
+	.show_attribute		= f_lb_opts_attr_show,
+	.store_attribute	= f_lb_opts_attr_store,
+};
+
+static ssize_t f_lb_opts_qlen_show(struct f_lb_opts *opts, char *page)
+{
+	int result;
+
+	mutex_lock(&opts->lock);
+	result = sprintf(page, "%d", opts->qlen);
+	mutex_unlock(&opts->lock);
+
+	return result;
+}
+
+static ssize_t f_lb_opts_qlen_store(struct f_lb_opts *opts,
+				    const char *page, size_t len)
+{
+	int ret;
+	u32 num;
+
+	mutex_lock(&opts->lock);
+	if (opts->refcnt) {
+		ret = -EBUSY;
+		goto end;
+	}
+
+	ret = kstrtou32(page, 0, &num);
+	if (ret)
+		goto end;
+
+	opts->qlen = num;
+	ret = len;
+end:
+	mutex_unlock(&opts->lock);
+	return ret;
+}
+
+static struct f_lb_opts_attribute f_lb_opts_qlen =
+	__CONFIGFS_ATTR(qlen, S_IRUGO | S_IWUSR,
+			f_lb_opts_qlen_show,
+			f_lb_opts_qlen_store);
+
+static ssize_t f_lb_opts_bulk_buflen_show(struct f_lb_opts *opts, char *page)
+{
+	int result;
+
+	mutex_lock(&opts->lock);
+	result = sprintf(page, "%d", opts->bulk_buflen);
+	mutex_unlock(&opts->lock);
+
+	return result;
+}
+
+static ssize_t f_lb_opts_bulk_buflen_store(struct f_lb_opts *opts,
+				    const char *page, size_t len)
+{
+	int ret;
+	u32 num;
+
+	mutex_lock(&opts->lock);
+	if (opts->refcnt) {
+		ret = -EBUSY;
+		goto end;
+	}
+
+	ret = kstrtou32(page, 0, &num);
+	if (ret)
+		goto end;
+
+	opts->bulk_buflen = num;
+	ret = len;
+end:
+	mutex_unlock(&opts->lock);
+	return ret;
+}
+
+static struct f_lb_opts_attribute f_lb_opts_bulk_buflen =
+	__CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR,
+			f_lb_opts_bulk_buflen_show,
+			f_lb_opts_bulk_buflen_store);
+
+static struct configfs_attribute *lb_attrs[] = {
+	&f_lb_opts_qlen.attr,
+	&f_lb_opts_bulk_buflen.attr,
+	NULL,
+};
+
+static struct config_item_type lb_func_type = {
+	.ct_item_ops    = &lb_item_ops,
+	.ct_attrs	= lb_attrs,
+	.ct_owner       = THIS_MODULE,
+};
+
 static void lb_free_instance(struct usb_function_instance *fi)
 {
 	struct f_lb_opts *lb_opts;
@@ -411,7 +542,14 @@
 	lb_opts = kzalloc(sizeof(*lb_opts), GFP_KERNEL);
 	if (!lb_opts)
 		return ERR_PTR(-ENOMEM);
+	mutex_init(&lb_opts->lock);
 	lb_opts->func_inst.free_func_inst = lb_free_instance;
+	lb_opts->bulk_buflen = GZERO_BULK_BUFLEN;
+	lb_opts->qlen = GZERO_QLEN;
+
+	config_group_init_type_name(&lb_opts->func_inst.group, "",
+				    &lb_func_type);
+
 	return  &lb_opts->func_inst;
 }
 DECLARE_USB_FUNCTION(Loopback, loopback_alloc_instance, loopback_alloc);
diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c
index 263e721..36d4bb2 100644
--- a/drivers/usb/gadget/f_midi.c
+++ b/drivers/usb/gadget/f_midi.c
@@ -32,6 +32,8 @@
 #include <linux/usb/audio.h>
 #include <linux/usb/midi.h>
 
+#include "u_f.h"
+
 MODULE_AUTHOR("Ben Williamson");
 MODULE_LICENSE("GPL v2");
 
@@ -191,20 +193,10 @@
 	NULL,
 };
 
-static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
+static inline struct usb_request *midi_alloc_ep_req(struct usb_ep *ep,
+						    unsigned length)
 {
-	struct usb_request *req;
-
-	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
-	if (req) {
-		req->length = length;
-		req->buf = kmalloc(length, GFP_ATOMIC);
-		if (!req->buf) {
-			usb_ep_free_request(ep, req);
-			req = NULL;
-		}
-	}
-	return req;
+	return alloc_ep_req(ep, length, length);
 }
 
 static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
@@ -365,7 +357,7 @@
 	/* allocate a bunch of read buffers and queue them all at once. */
 	for (i = 0; i < midi->qlen && err == 0; i++) {
 		struct usb_request *req =
-			alloc_ep_req(midi->out_ep, midi->buflen);
+			midi_alloc_ep_req(midi->out_ep, midi->buflen);
 		if (req == NULL)
 			return -ENOMEM;
 
@@ -546,7 +538,7 @@
 		return;
 
 	if (!req)
-		req = alloc_ep_req(ep, midi->buflen);
+		req = midi_alloc_ep_req(ep, midi->buflen);
 
 	if (!req) {
 		ERROR(midi, "gmidi_transmit: alloc_ep_request failed\n");
diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c
index 1c28fe1..a9499fd 100644
--- a/drivers/usb/gadget/f_ncm.c
+++ b/drivers/usb/gadget/f_ncm.c
@@ -1386,7 +1386,7 @@
 	usb_ep_free_request(ncm->notify, ncm->notify_req);
 }
 
-struct usb_function *ncm_alloc(struct usb_function_instance *fi)
+static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
 {
 	struct f_ncm		*ncm;
 	struct f_ncm_opts	*opts;
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c
index ad39f1d..aebae18 100644
--- a/drivers/usb/gadget/f_obex.c
+++ b/drivers/usb/gadget/f_obex.c
@@ -499,7 +499,7 @@
 	usb_free_all_descriptors(f);
 }
 
-struct usb_function *obex_alloc(struct usb_function_instance *fi)
+static struct usb_function *obex_alloc(struct usb_function_instance *fi)
 {
 	struct f_obex	*obex;
 	struct f_serial_opts *opts;
diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c
index eb3aa81..f2b7817 100644
--- a/drivers/usb/gadget/f_phonet.c
+++ b/drivers/usb/gadget/f_phonet.c
@@ -689,7 +689,7 @@
 	usb_free_all_descriptors(f);
 }
 
-struct usb_function *phonet_alloc(struct usb_function_instance *fi)
+static struct usb_function *phonet_alloc(struct usb_function_instance *fi)
 {
 	struct f_phonet *fp;
 	struct f_phonet_opts *opts;
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 717ed7f..c11761c 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -675,7 +675,6 @@
 	int			status;
 	struct usb_ep		*ep;
 
-#ifndef USB_FRNDIS_INCLUDED
 	struct f_rndis_opts *rndis_opts;
 
 	if (!can_support_rndis(c))
@@ -697,7 +696,7 @@
 			return status;
 		rndis_opts->bound = true;
 	}
-#endif
+
 	us = usb_gstrings_attach(cdev, rndis_strings,
 				 ARRAY_SIZE(rndis_string_defs));
 	if (IS_ERR(us))
@@ -782,13 +781,6 @@
 	rndis->port.open = rndis_open;
 	rndis->port.close = rndis_close;
 
-#ifdef USB_FRNDIS_INCLUDED
-	status = rndis_register(rndis_response_available, rndis);
-	if (status < 0)
-		goto fail;
-	rndis->config = status;
-#endif
-
 	rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0);
 	rndis_set_host_mac(rndis->config, rndis->ethaddr);
 
@@ -830,66 +822,6 @@
 	return status;
 }
 
-#ifdef USB_FRNDIS_INCLUDED
-
-static void
-rndis_old_unbind(struct usb_configuration *c, struct usb_function *f)
-{
-	struct f_rndis		*rndis = func_to_rndis(f);
-
-	rndis_deregister(rndis->config);
-
-	usb_free_all_descriptors(f);
-
-	kfree(rndis->notify_req->buf);
-	usb_ep_free_request(rndis->notify, rndis->notify_req);
-
-	kfree(rndis);
-}
-
-int
-rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-		u32 vendorID, const char *manufacturer, struct eth_dev *dev)
-{
-	struct f_rndis	*rndis;
-	int		status;
-
-	/* allocate and initialize one new instance */
-	status = -ENOMEM;
-	rndis = kzalloc(sizeof *rndis, GFP_KERNEL);
-	if (!rndis)
-		goto fail;
-
-	memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);
-	rndis->vendorID = vendorID;
-	rndis->manufacturer = manufacturer;
-
-	rndis->port.ioport = dev;
-	/* RNDIS activates when the host changes this filter */
-	rndis->port.cdc_filter = 0;
-
-	/* RNDIS has special (and complex) framing */
-	rndis->port.header_len = sizeof(struct rndis_packet_msg_type);
-	rndis->port.wrap = rndis_add_header;
-	rndis->port.unwrap = rndis_rm_hdr;
-
-	rndis->port.func.name = "rndis";
-	/* descriptors are per-instance copies */
-	rndis->port.func.bind = rndis_bind;
-	rndis->port.func.unbind = rndis_old_unbind;
-	rndis->port.func.set_alt = rndis_set_alt;
-	rndis->port.func.setup = rndis_setup;
-	rndis->port.func.disable = rndis_disable;
-
-	status = usb_add_function(c, &rndis->port.func);
-	if (status)
-		kfree(rndis);
-fail:
-	return status;
-}
-
-#else
-
 void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net)
 {
 	struct f_rndis_opts *opts;
@@ -1047,8 +979,26 @@
 	return &rndis->port.func;
 }
 
-DECLARE_USB_FUNCTION_INIT(rndis, rndis_alloc_inst, rndis_alloc);
+DECLARE_USB_FUNCTION(rndis, rndis_alloc_inst, rndis_alloc);
+
+static int __init rndis_mod_init(void)
+{
+	int ret;
+
+	ret = rndis_init();
+	if (ret)
+		return ret;
+
+	return usb_function_register(&rndisusb_func);
+}
+module_init(rndis_mod_init);
+
+static void __exit rndis_mod_exit(void)
+{
+	usb_function_unregister(&rndisusb_func);
+	rndis_exit();
+}
+module_exit(rndis_mod_exit);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Brownell");
-
-#endif
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index 981113c..9ecbcbf 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -354,7 +354,7 @@
 	usb_free_all_descriptors(f);
 }
 
-struct usb_function *gser_alloc(struct usb_function_instance *fi)
+static struct usb_function *gser_alloc(struct usb_function_instance *fi)
 {
 	struct f_gser	*gser;
 	struct f_serial_opts *opts;
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index a889585..d3cd52d 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -21,6 +21,7 @@
 
 #include "g_zero.h"
 #include "gadget_chips.h"
+#include "u_f.h"
 
 /*
  * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral
@@ -201,7 +202,7 @@
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 
-struct usb_ss_ep_comp_descriptor ss_source_comp_desc = {
+static struct usb_ss_ep_comp_descriptor ss_source_comp_desc = {
 	.bLength =		USB_DT_SS_EP_COMP_SIZE,
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 
@@ -218,7 +219,7 @@
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 
-struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = {
+static struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = {
 	.bLength =		USB_DT_SS_EP_COMP_SIZE,
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 
@@ -236,7 +237,7 @@
 	.bInterval =		4,
 };
 
-struct usb_ss_ep_comp_descriptor ss_iso_source_comp_desc = {
+static struct usb_ss_ep_comp_descriptor ss_iso_source_comp_desc = {
 	.bLength =		USB_DT_SS_EP_COMP_SIZE,
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 
@@ -254,7 +255,7 @@
 	.bInterval =		4,
 };
 
-struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = {
+static struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = {
 	.bLength =		USB_DT_SS_EP_COMP_SIZE,
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 
@@ -301,23 +302,9 @@
 
 /*-------------------------------------------------------------------------*/
 
-struct usb_request *alloc_ep_req(struct usb_ep *ep, int len)
+static inline struct usb_request *ss_alloc_ep_req(struct usb_ep *ep, int len)
 {
-	struct usb_request      *req;
-
-	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
-	if (req) {
-		if (len)
-			req->length = len;
-		else
-			req->length = buflen;
-		req->buf = kmalloc(req->length, GFP_ATOMIC);
-		if (!req->buf) {
-			usb_ep_free_request(ep, req);
-			req = NULL;
-		}
-	}
-	return req;
+	return alloc_ep_req(ep, len, buflen);
 }
 
 void free_ep_req(struct usb_ep *ep, struct usb_request *req)
@@ -490,6 +477,14 @@
 static void
 sourcesink_free_func(struct usb_function *f)
 {
+	struct f_ss_opts *opts;
+
+	opts = container_of(f->fi, struct f_ss_opts, func_inst);
+
+	mutex_lock(&opts->lock);
+	opts->refcnt--;
+	mutex_unlock(&opts->lock);
+
 	usb_free_all_descriptors(f);
 	kfree(func_to_ss(f));
 }
@@ -628,10 +623,10 @@
 				break;
 			}
 			ep = is_in ? ss->iso_in_ep : ss->iso_out_ep;
-			req = alloc_ep_req(ep, size);
+			req = ss_alloc_ep_req(ep, size);
 		} else {
 			ep = is_in ? ss->in_ep : ss->out_ep;
-			req = alloc_ep_req(ep, 0);
+			req = ss_alloc_ep_req(ep, 0);
 		}
 
 		if (!req)
@@ -878,6 +873,11 @@
 		return NULL;
 
 	ss_opts =  container_of(fi, struct f_ss_opts, func_inst);
+
+	mutex_lock(&ss_opts->lock);
+	ss_opts->refcnt++;
+	mutex_unlock(&ss_opts->lock);
+
 	pattern = ss_opts->pattern;
 	isoc_interval = ss_opts->isoc_interval;
 	isoc_maxpacket = ss_opts->isoc_maxpacket;
@@ -898,6 +898,303 @@
 	return &ss->function;
 }
 
+static inline struct f_ss_opts *to_f_ss_opts(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct f_ss_opts,
+			    func_inst.group);
+}
+
+CONFIGFS_ATTR_STRUCT(f_ss_opts);
+CONFIGFS_ATTR_OPS(f_ss_opts);
+
+static void ss_attr_release(struct config_item *item)
+{
+	struct f_ss_opts *ss_opts = to_f_ss_opts(item);
+
+	usb_put_function_instance(&ss_opts->func_inst);
+}
+
+static struct configfs_item_operations ss_item_ops = {
+	.release		= ss_attr_release,
+	.show_attribute		= f_ss_opts_attr_show,
+	.store_attribute	= f_ss_opts_attr_store,
+};
+
+static ssize_t f_ss_opts_pattern_show(struct f_ss_opts *opts, char *page)
+{
+	int result;
+
+	mutex_lock(&opts->lock);
+	result = sprintf(page, "%d", opts->pattern);
+	mutex_unlock(&opts->lock);
+
+	return result;
+}
+
+static ssize_t f_ss_opts_pattern_store(struct f_ss_opts *opts,
+				       const char *page, size_t len)
+{
+	int ret;
+	u8 num;
+
+	mutex_lock(&opts->lock);
+	if (opts->refcnt) {
+		ret = -EBUSY;
+		goto end;
+	}
+
+	ret = kstrtou8(page, 0, &num);
+	if (ret)
+		goto end;
+
+	if (num != 0 && num != 1 && num != 2) {
+		ret = -EINVAL;
+		goto end;
+	}
+
+	opts->pattern = num;
+	ret = len;
+end:
+	mutex_unlock(&opts->lock);
+	return ret;
+}
+
+static struct f_ss_opts_attribute f_ss_opts_pattern =
+	__CONFIGFS_ATTR(pattern, S_IRUGO | S_IWUSR,
+			f_ss_opts_pattern_show,
+			f_ss_opts_pattern_store);
+
+static ssize_t f_ss_opts_isoc_interval_show(struct f_ss_opts *opts, char *page)
+{
+	int result;
+
+	mutex_lock(&opts->lock);
+	result = sprintf(page, "%d", opts->isoc_interval);
+	mutex_unlock(&opts->lock);
+
+	return result;
+}
+
+static ssize_t f_ss_opts_isoc_interval_store(struct f_ss_opts *opts,
+				       const char *page, size_t len)
+{
+	int ret;
+	u8 num;
+
+	mutex_lock(&opts->lock);
+	if (opts->refcnt) {
+		ret = -EBUSY;
+		goto end;
+	}
+
+	ret = kstrtou8(page, 0, &num);
+	if (ret)
+		goto end;
+
+	if (num > 16) {
+		ret = -EINVAL;
+		goto end;
+	}
+
+	opts->isoc_interval = num;
+	ret = len;
+end:
+	mutex_unlock(&opts->lock);
+	return ret;
+}
+
+static struct f_ss_opts_attribute f_ss_opts_isoc_interval =
+	__CONFIGFS_ATTR(isoc_interval, S_IRUGO | S_IWUSR,
+			f_ss_opts_isoc_interval_show,
+			f_ss_opts_isoc_interval_store);
+
+static ssize_t f_ss_opts_isoc_maxpacket_show(struct f_ss_opts *opts, char *page)
+{
+	int result;
+
+	mutex_lock(&opts->lock);
+	result = sprintf(page, "%d", opts->isoc_maxpacket);
+	mutex_unlock(&opts->lock);
+
+	return result;
+}
+
+static ssize_t f_ss_opts_isoc_maxpacket_store(struct f_ss_opts *opts,
+				       const char *page, size_t len)
+{
+	int ret;
+	u16 num;
+
+	mutex_lock(&opts->lock);
+	if (opts->refcnt) {
+		ret = -EBUSY;
+		goto end;
+	}
+
+	ret = kstrtou16(page, 0, &num);
+	if (ret)
+		goto end;
+
+	if (num > 1024) {
+		ret = -EINVAL;
+		goto end;
+	}
+
+	opts->isoc_maxpacket = num;
+	ret = len;
+end:
+	mutex_unlock(&opts->lock);
+	return ret;
+}
+
+static struct f_ss_opts_attribute f_ss_opts_isoc_maxpacket =
+	__CONFIGFS_ATTR(isoc_maxpacket, S_IRUGO | S_IWUSR,
+			f_ss_opts_isoc_maxpacket_show,
+			f_ss_opts_isoc_maxpacket_store);
+
+static ssize_t f_ss_opts_isoc_mult_show(struct f_ss_opts *opts, char *page)
+{
+	int result;
+
+	mutex_lock(&opts->lock);
+	result = sprintf(page, "%d", opts->isoc_mult);
+	mutex_unlock(&opts->lock);
+
+	return result;
+}
+
+static ssize_t f_ss_opts_isoc_mult_store(struct f_ss_opts *opts,
+				       const char *page, size_t len)
+{
+	int ret;
+	u8 num;
+
+	mutex_lock(&opts->lock);
+	if (opts->refcnt) {
+		ret = -EBUSY;
+		goto end;
+	}
+
+	ret = kstrtou8(page, 0, &num);
+	if (ret)
+		goto end;
+
+	if (num > 2) {
+		ret = -EINVAL;
+		goto end;
+	}
+
+	opts->isoc_mult = num;
+	ret = len;
+end:
+	mutex_unlock(&opts->lock);
+	return ret;
+}
+
+static struct f_ss_opts_attribute f_ss_opts_isoc_mult =
+	__CONFIGFS_ATTR(isoc_mult, S_IRUGO | S_IWUSR,
+			f_ss_opts_isoc_mult_show,
+			f_ss_opts_isoc_mult_store);
+
+static ssize_t f_ss_opts_isoc_maxburst_show(struct f_ss_opts *opts, char *page)
+{
+	int result;
+
+	mutex_lock(&opts->lock);
+	result = sprintf(page, "%d", opts->isoc_maxburst);
+	mutex_unlock(&opts->lock);
+
+	return result;
+}
+
+static ssize_t f_ss_opts_isoc_maxburst_store(struct f_ss_opts *opts,
+				       const char *page, size_t len)
+{
+	int ret;
+	u8 num;
+
+	mutex_lock(&opts->lock);
+	if (opts->refcnt) {
+		ret = -EBUSY;
+		goto end;
+	}
+
+	ret = kstrtou8(page, 0, &num);
+	if (ret)
+		goto end;
+
+	if (num > 15) {
+		ret = -EINVAL;
+		goto end;
+	}
+
+	opts->isoc_maxburst = num;
+	ret = len;
+end:
+	mutex_unlock(&opts->lock);
+	return ret;
+}
+
+static struct f_ss_opts_attribute f_ss_opts_isoc_maxburst =
+	__CONFIGFS_ATTR(isoc_maxburst, S_IRUGO | S_IWUSR,
+			f_ss_opts_isoc_maxburst_show,
+			f_ss_opts_isoc_maxburst_store);
+
+static ssize_t f_ss_opts_bulk_buflen_show(struct f_ss_opts *opts, char *page)
+{
+	int result;
+
+	mutex_lock(&opts->lock);
+	result = sprintf(page, "%d", opts->bulk_buflen);
+	mutex_unlock(&opts->lock);
+
+	return result;
+}
+
+static ssize_t f_ss_opts_bulk_buflen_store(struct f_ss_opts *opts,
+					   const char *page, size_t len)
+{
+	int ret;
+	u32 num;
+
+	mutex_lock(&opts->lock);
+	if (opts->refcnt) {
+		ret = -EBUSY;
+		goto end;
+	}
+
+	ret = kstrtou32(page, 0, &num);
+	if (ret)
+		goto end;
+
+	opts->bulk_buflen = num;
+	ret = len;
+end:
+	mutex_unlock(&opts->lock);
+	return ret;
+}
+
+static struct f_ss_opts_attribute f_ss_opts_bulk_buflen =
+	__CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR,
+			f_ss_opts_bulk_buflen_show,
+			f_ss_opts_bulk_buflen_store);
+
+static struct configfs_attribute *ss_attrs[] = {
+	&f_ss_opts_pattern.attr,
+	&f_ss_opts_isoc_interval.attr,
+	&f_ss_opts_isoc_maxpacket.attr,
+	&f_ss_opts_isoc_mult.attr,
+	&f_ss_opts_isoc_maxburst.attr,
+	&f_ss_opts_bulk_buflen.attr,
+	NULL,
+};
+
+static struct config_item_type ss_func_type = {
+	.ct_item_ops    = &ss_item_ops,
+	.ct_attrs	= ss_attrs,
+	.ct_owner       = THIS_MODULE,
+};
+
 static void source_sink_free_instance(struct usb_function_instance *fi)
 {
 	struct f_ss_opts *ss_opts;
@@ -913,7 +1210,15 @@
 	ss_opts = kzalloc(sizeof(*ss_opts), GFP_KERNEL);
 	if (!ss_opts)
 		return ERR_PTR(-ENOMEM);
+	mutex_init(&ss_opts->lock);
 	ss_opts->func_inst.free_func_inst = source_sink_free_instance;
+	ss_opts->isoc_interval = GZERO_ISOC_INTERVAL;
+	ss_opts->isoc_maxpacket = GZERO_ISOC_MAXPACKET;
+	ss_opts->bulk_buflen = GZERO_BULK_BUFLEN;
+
+	config_group_init_type_name(&ss_opts->func_inst.group, "",
+				    &ss_func_type);
+
 	return &ss_opts->func_inst;
 }
 DECLARE_USB_FUNCTION(SourceSink, source_sink_alloc_inst,
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
index 7c8674f..f1a5919 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/f_subset.c
@@ -301,7 +301,6 @@
 	int			status;
 	struct usb_ep		*ep;
 
-#ifndef USB_FSUBSET_INCLUDED
 	struct f_gether_opts	*gether_opts;
 
 	gether_opts = container_of(f->fi, struct f_gether_opts, func_inst);
@@ -322,7 +321,7 @@
 			return status;
 		gether_opts->bound = true;
 	}
-#endif
+
 	us = usb_gstrings_attach(cdev, geth_strings,
 				 ARRAY_SIZE(geth_string_defs));
 	if (IS_ERR(us))
@@ -393,61 +392,6 @@
 	return status;
 }
 
-#ifdef USB_FSUBSET_INCLUDED
-
-static void
-geth_old_unbind(struct usb_configuration *c, struct usb_function *f)
-{
-	geth_string_defs[0].id = 0;
-	usb_free_all_descriptors(f);
-	kfree(func_to_geth(f));
-}
-
-/**
- * geth_bind_config - add CDC Subset network link to a configuration
- * @c: the configuration to support the network link
- * @ethaddr: a buffer in which the ethernet address of the host side
- *	side of the link was recorded
- * @dev: eth_dev structure
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- *
- * Caller must have called @gether_setup().  Caller is also responsible
- * for calling @gether_cleanup() before module unload.
- */
-int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-		struct eth_dev *dev)
-{
-	struct f_gether	*geth;
-	int		status;
-
-	/* allocate and initialize one new instance */
-	geth = kzalloc(sizeof *geth, GFP_KERNEL);
-	if (!geth)
-		return -ENOMEM;
-
-	/* export host's Ethernet address in CDC format */
-	snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);
-	geth_string_defs[1].s = geth->ethaddr;
-
-	geth->port.ioport = dev;
-	geth->port.cdc_filter = DEFAULT_FILTER;
-
-	geth->port.func.name = "cdc_subset";
-	geth->port.func.bind = geth_bind;
-	geth->port.func.unbind = geth_old_unbind;
-	geth->port.func.set_alt = geth_set_alt;
-	geth->port.func.disable = geth_disable;
-
-	status = usb_add_function(c, &geth->port.func);
-	if (status)
-		kfree(geth);
-	return status;
-}
-
-#else
-
 static inline struct f_gether_opts *to_f_gether_opts(struct config_item *item)
 {
 	return container_of(to_config_group(item), struct f_gether_opts,
@@ -573,5 +517,3 @@
 DECLARE_USB_FUNCTION_INIT(geth, geth_alloc_inst, geth_alloc);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Brownell");
-
-#endif
diff --git a/drivers/usb/gadget/fotg210-udc.c b/drivers/usb/gadget/fotg210-udc.c
index bbbfd19..2d03052 100644
--- a/drivers/usb/gadget/fotg210-udc.c
+++ b/drivers/usb/gadget/fotg210-udc.c
@@ -1157,8 +1157,9 @@
 		INIT_LIST_HEAD(&ep->queue);
 		ep->ep.name = fotg210_ep_name[i];
 		ep->ep.ops = &fotg210_ep_ops;
+		usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
 	}
-	fotg210->ep[0]->ep.maxpacket = 0x40;
+	usb_ep_set_maxpacket_limit(&fotg210->ep[0]->ep, 0x40);
 	fotg210->gadget.ep0 = &fotg210->ep[0]->ep;
 	INIT_LIST_HEAD(&fotg210->gadget.ep0->ep_list);
 
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index 6315ee6..f60d4da 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2429,7 +2429,7 @@
 
 	ep->ep.ops = &qe_ep_ops;
 	ep->stopped = 1;
-	ep->ep.maxpacket = (unsigned short) ~0;
+	usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
 	ep->ep.desc = NULL;
 	ep->dir = 0xff;
 	ep->epnum = (u8)pipe_num;
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index b7dea4e..15960af 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -2311,7 +2311,7 @@
 	/* for ep0: maxP defined in desc
 	 * for other eps, maxP is set by epautoconfig() called by gadget layer
 	 */
-	ep->ep.maxpacket = (unsigned short) ~0;
+	usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
 
 	/* the queue lists any req for this ep */
 	INIT_LIST_HEAD(&ep->queue);
@@ -2469,7 +2469,8 @@
 	 * for other eps, gadget layer called ep_enable with defined desc
 	 */
 	udc_controller->eps[0].ep.desc = &fsl_ep0_desc;
-	udc_controller->eps[0].ep.maxpacket = USB_MAX_CTRL_PAYLOAD;
+	usb_ep_set_maxpacket_limit(&udc_controller->eps[0].ep,
+				   USB_MAX_CTRL_PAYLOAD);
 
 	/* setup the udc->eps[] for non-control endpoints and link
 	 * to gadget.ep_list */
diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c
index b278abe..6423f18 100644
--- a/drivers/usb/gadget/fusb300_udc.c
+++ b/drivers/usb/gadget/fusb300_udc.c
@@ -1452,9 +1452,9 @@
 		INIT_LIST_HEAD(&ep->queue);
 		ep->ep.name = fusb300_ep_name[i];
 		ep->ep.ops = &fusb300_ep_ops;
-		ep->ep.maxpacket = HS_BULK_MAX_PACKET_SIZE;
+		usb_ep_set_maxpacket_limit(&ep->ep, HS_BULK_MAX_PACKET_SIZE);
 	}
-	fusb300->ep[0]->ep.maxpacket = HS_CTL_MAX_PACKET_SIZE;
+	usb_ep_set_maxpacket_limit(&fusb300->ep[0]->ep, HS_CTL_MAX_PACKET_SIZE);
 	fusb300->ep[0]->epnum = 0;
 	fusb300->gadget.ep0 = &fusb300->ep[0]->ep;
 	INIT_LIST_HEAD(&fusb300->gadget.ep0->ep_list);
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index 2344efe..fe12e6a 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -13,14 +13,10 @@
 #define pr_fmt(fmt) "g_ffs: " fmt
 
 #include <linux/module.h>
-/*
- * kbuild is not very cooperative with respect to linking separately
- * compiled library objects into one module.  So for now we won't use
- * separate compilation ... ensuring init/exit sections work to shrink
- * the runtime footprint, and giving us at least some parts of what
- * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
- */
+
 #if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
+#include <linux/netdevice.h>
+
 #  if defined USB_ETH_RNDIS
 #    undef USB_ETH_RNDIS
 #  endif
@@ -28,31 +24,31 @@
 #    define USB_ETH_RNDIS y
 #  endif
 
-#define USBF_ECM_INCLUDED
-#  include "f_ecm.c"
-#define USB_FSUBSET_INCLUDED
-#  include "f_subset.c"
+#  include "u_ecm.h"
+#  include "u_gether.h"
 #  ifdef USB_ETH_RNDIS
-#    define USB_FRNDIS_INCLUDED
-#    include "f_rndis.c"
+#    include "u_rndis.h"
 #    include "rndis.h"
 #  endif
 #  include "u_ether.h"
 
-static u8 gfs_host_mac[ETH_ALEN];
-static struct eth_dev *the_dev;
+USB_ETHERNET_MODULE_PARAMETERS();
+
 #  ifdef CONFIG_USB_FUNCTIONFS_ETH
-static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-		struct eth_dev *dev);
+static int eth_bind_config(struct usb_configuration *c);
+static struct usb_function_instance *fi_ecm;
+static struct usb_function *f_ecm;
+static struct usb_function_instance *fi_geth;
+static struct usb_function *f_geth;
 #  endif
-#else
-#  define the_dev	NULL
-#  define gether_cleanup(dev) do { } while (0)
-#  define gfs_host_mac NULL
-struct eth_dev;
+#  ifdef CONFIG_USB_FUNCTIONFS_RNDIS
+static int bind_rndis_config(struct usb_configuration *c);
+static struct usb_function_instance *fi_rndis;
+static struct usb_function *f_rndis;
+#  endif
 #endif
 
-#include "f_fs.c"
+#include "u_fs.h"
 
 #define DRIVER_NAME	"g_ffs"
 #define DRIVER_DESC	"USB Function Filesystem"
@@ -67,19 +63,8 @@
 
 #define GFS_MAX_DEVS	10
 
-struct gfs_ffs_obj {
-	const char *name;
-	bool mounted;
-	bool desc_ready;
-	struct ffs_data *ffs_data;
-};
-
 USB_GADGET_COMPOSITE_OPTIONS();
 
-#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
-USB_ETHERNET_MODULE_PARAMETERS();
-#endif
-
 static struct usb_device_descriptor gfs_dev_desc = {
 	.bLength		= sizeof gfs_dev_desc,
 	.bDescriptorType	= USB_DT_DEVICE,
@@ -146,12 +131,12 @@
 
 struct gfs_configuration {
 	struct usb_configuration c;
-	int (*eth)(struct usb_configuration *c, u8 *ethaddr,
-			struct eth_dev *dev);
+	int (*eth)(struct usb_configuration *c);
+	int num;
 } gfs_configurations[] = {
 #ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 	{
-		.eth		= rndis_bind_config,
+		.eth		= bind_rndis_config,
 	},
 #endif
 
@@ -167,10 +152,15 @@
 #endif
 };
 
+static void *functionfs_acquire_dev(struct ffs_dev *dev);
+static void functionfs_release_dev(struct ffs_dev *dev);
+static int functionfs_ready_callback(struct ffs_data *ffs);
+static void functionfs_closed_callback(struct ffs_data *ffs);
 static int gfs_bind(struct usb_composite_dev *cdev);
 static int gfs_unbind(struct usb_composite_dev *cdev);
 static int gfs_do_config(struct usb_configuration *c);
 
+
 static __refdata struct usb_composite_driver gfs_driver = {
 	.name		= DRIVER_NAME,
 	.dev		= &gfs_dev_desc,
@@ -180,205 +170,243 @@
 	.unbind		= gfs_unbind,
 };
 
-static DEFINE_MUTEX(gfs_lock);
 static unsigned int missing_funcs;
-static bool gfs_ether_setup;
 static bool gfs_registered;
 static bool gfs_single_func;
-static struct gfs_ffs_obj *ffs_tab;
+static struct usb_function_instance **fi_ffs;
+static struct usb_function **f_ffs[] = {
+#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
+	NULL,
+#endif
+
+#ifdef CONFIG_USB_FUNCTIONFS_ETH
+	NULL,
+#endif
+
+#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
+	NULL,
+#endif
+};
+
+#define N_CONF ARRAY_SIZE(f_ffs)
 
 static int __init gfs_init(void)
 {
+	struct f_fs_opts *opts;
 	int i;
+	int ret = 0;
 
 	ENTER();
 
-	if (!func_num) {
+	if (func_num < 2) {
 		gfs_single_func = true;
 		func_num = 1;
 	}
 
-	ffs_tab = kcalloc(func_num, sizeof *ffs_tab, GFP_KERNEL);
-	if (!ffs_tab)
-		return -ENOMEM;
+	/*
+	 * Allocate in one chunk for easier maintenance
+	 */
+	f_ffs[0] = kcalloc(func_num * N_CONF, sizeof(*f_ffs), GFP_KERNEL);
+	if (!f_ffs[0]) {
+		ret = -ENOMEM;
+		goto no_func;
+	}
+	for (i = 1; i < N_CONF; ++i)
+		f_ffs[i] = f_ffs[0] + i * func_num;
 
-	if (!gfs_single_func)
-		for (i = 0; i < func_num; i++)
-			ffs_tab[i].name = func_names[i];
+	fi_ffs = kcalloc(func_num, sizeof(*fi_ffs), GFP_KERNEL);
+	if (!fi_ffs) {
+		ret = -ENOMEM;
+		goto no_func;
+	}
+
+	for (i = 0; i < func_num; i++) {
+		fi_ffs[i] = usb_get_function_instance("ffs");
+		if (IS_ERR(fi_ffs[i])) {
+			ret = PTR_ERR(fi_ffs[i]);
+			--i;
+			goto no_dev;
+		}
+		opts = to_f_fs_opts(fi_ffs[i]);
+		if (gfs_single_func)
+			ret = ffs_single_dev(opts->dev);
+		else
+			ret = ffs_name_dev(opts->dev, func_names[i]);
+		if (ret)
+			goto no_dev;
+		opts->dev->ffs_ready_callback = functionfs_ready_callback;
+		opts->dev->ffs_closed_callback = functionfs_closed_callback;
+		opts->dev->ffs_acquire_dev_callback = functionfs_acquire_dev;
+		opts->dev->ffs_release_dev_callback = functionfs_release_dev;
+		opts->no_configfs = true;
+	}
 
 	missing_funcs = func_num;
 
-	return functionfs_init();
+	return 0;
+no_dev:
+	while (i >= 0)
+		usb_put_function_instance(fi_ffs[i--]);
+	kfree(fi_ffs);
+no_func:
+	kfree(f_ffs[0]);
+	return ret;
 }
 module_init(gfs_init);
 
 static void __exit gfs_exit(void)
 {
+	int i;
+
 	ENTER();
-	mutex_lock(&gfs_lock);
 
 	if (gfs_registered)
 		usb_composite_unregister(&gfs_driver);
 	gfs_registered = false;
 
-	functionfs_cleanup();
+	kfree(f_ffs[0]);
 
-	mutex_unlock(&gfs_lock);
-	kfree(ffs_tab);
+	for (i = 0; i < func_num; i++)
+		usb_put_function_instance(fi_ffs[i]);
+
+	kfree(fi_ffs);
 }
 module_exit(gfs_exit);
 
-static struct gfs_ffs_obj *gfs_find_dev(const char *dev_name)
+static void *functionfs_acquire_dev(struct ffs_dev *dev)
 {
-	int i;
-
-	ENTER();
-
-	if (gfs_single_func)
-		return &ffs_tab[0];
-
-	for (i = 0; i < func_num; i++)
-		if (strcmp(ffs_tab[i].name, dev_name) == 0)
-			return &ffs_tab[i];
-
-	return NULL;
+	if (!try_module_get(THIS_MODULE))
+		return ERR_PTR(-ENODEV);
+	
+	return 0;
 }
 
+static void functionfs_release_dev(struct ffs_dev *dev)
+{
+	module_put(THIS_MODULE);
+}
+
+/*
+ * The caller of this function takes ffs_lock 
+ */
 static int functionfs_ready_callback(struct ffs_data *ffs)
 {
-	struct gfs_ffs_obj *ffs_obj;
-	int ret;
+	int ret = 0;
 
-	ENTER();
-	mutex_lock(&gfs_lock);
+	if (--missing_funcs)
+		return 0;
 
-	ffs_obj = ffs->private_data;
-	if (!ffs_obj) {
-		ret = -EINVAL;
-		goto done;
-	}
+	if (gfs_registered)
+		return -EBUSY;
 
-	if (WARN_ON(ffs_obj->desc_ready)) {
-		ret = -EBUSY;
-		goto done;
-	}
-	ffs_obj->desc_ready = true;
-	ffs_obj->ffs_data = ffs;
-
-	if (--missing_funcs) {
-		ret = 0;
-		goto done;
-	}
-
-	if (gfs_registered) {
-		ret = -EBUSY;
-		goto done;
-	}
 	gfs_registered = true;
 
 	ret = usb_composite_probe(&gfs_driver);
 	if (unlikely(ret < 0))
 		gfs_registered = false;
-
-done:
-	mutex_unlock(&gfs_lock);
+	
 	return ret;
 }
 
+/*
+ * The caller of this function takes ffs_lock 
+ */
 static void functionfs_closed_callback(struct ffs_data *ffs)
 {
-	struct gfs_ffs_obj *ffs_obj;
-
-	ENTER();
-	mutex_lock(&gfs_lock);
-
-	ffs_obj = ffs->private_data;
-	if (!ffs_obj)
-		goto done;
-
-	ffs_obj->desc_ready = false;
 	missing_funcs++;
 
 	if (gfs_registered)
 		usb_composite_unregister(&gfs_driver);
 	gfs_registered = false;
-
-done:
-	mutex_unlock(&gfs_lock);
-}
-
-static void *functionfs_acquire_dev_callback(const char *dev_name)
-{
-	struct gfs_ffs_obj *ffs_dev;
-
-	ENTER();
-	mutex_lock(&gfs_lock);
-
-	ffs_dev = gfs_find_dev(dev_name);
-	if (!ffs_dev) {
-		ffs_dev = ERR_PTR(-ENODEV);
-		goto done;
-	}
-
-	if (ffs_dev->mounted) {
-		ffs_dev = ERR_PTR(-EBUSY);
-		goto done;
-	}
-	ffs_dev->mounted = true;
-
-done:
-	mutex_unlock(&gfs_lock);
-	return ffs_dev;
-}
-
-static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
-{
-	struct gfs_ffs_obj *ffs_dev;
-
-	ENTER();
-	mutex_lock(&gfs_lock);
-
-	ffs_dev = ffs_data->private_data;
-	if (ffs_dev)
-		ffs_dev->mounted = false;
-
-	mutex_unlock(&gfs_lock);
 }
 
 /*
- * It is assumed that gfs_bind is called from a context where gfs_lock is held
+ * It is assumed that gfs_bind is called from a context where ffs_lock is held
  */
 static int gfs_bind(struct usb_composite_dev *cdev)
 {
+#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
+	struct net_device *net;
+#endif
 	int ret, i;
 
 	ENTER();
 
 	if (missing_funcs)
 		return -ENODEV;
-#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
-	the_dev = gether_setup(cdev->gadget, dev_addr, host_addr, gfs_host_mac,
-			       qmult);
-#endif
-	if (IS_ERR(the_dev)) {
-		ret = PTR_ERR(the_dev);
-		goto error_quick;
+#if defined CONFIG_USB_FUNCTIONFS_ETH
+	if (can_support_ecm(cdev->gadget)) {
+		struct f_ecm_opts *ecm_opts;
+
+		fi_ecm = usb_get_function_instance("ecm");
+		if (IS_ERR(fi_ecm))
+			return PTR_ERR(fi_ecm);
+		ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
+		net = ecm_opts->net;
+	} else {
+		struct f_gether_opts *geth_opts;
+
+		fi_geth = usb_get_function_instance("geth");
+		if (IS_ERR(fi_geth))
+			return PTR_ERR(fi_geth);
+		geth_opts = container_of(fi_geth, struct f_gether_opts,
+					 func_inst);
+		net = geth_opts->net;
 	}
-	gfs_ether_setup = true;
+#endif
 
-	ret = usb_string_ids_tab(cdev, gfs_strings);
-	if (unlikely(ret < 0))
-		goto error;
-	gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
+#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
+	{
+		struct f_rndis_opts *rndis_opts;
 
-	for (i = func_num; i--; ) {
-		ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);
-		if (unlikely(ret < 0)) {
-			while (++i < func_num)
-				functionfs_unbind(ffs_tab[i].ffs_data);
+		fi_rndis = usb_get_function_instance("rndis");
+		if (IS_ERR(fi_rndis)) {
+			ret = PTR_ERR(fi_rndis);
 			goto error;
 		}
+		rndis_opts = container_of(fi_rndis, struct f_rndis_opts,
+					  func_inst);
+#ifndef CONFIG_USB_FUNCTIONFS_ETH
+		net = rndis_opts->net;
+#endif
 	}
+#endif
+
+#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
+	gether_set_qmult(net, qmult);
+	if (!gether_set_host_addr(net, host_addr))
+		pr_info("using host ethernet address: %s", host_addr);
+	if (!gether_set_dev_addr(net, dev_addr))
+		pr_info("using self ethernet address: %s", dev_addr);
+#endif
+
+#if defined CONFIG_USB_FUNCTIONFS_RNDIS && defined CONFIG_USB_FUNCTIONFS_ETH
+	gether_set_gadget(net, cdev->gadget);
+	ret = gether_register_netdev(net);
+	if (ret)
+		goto error_rndis;
+
+	if (can_support_ecm(cdev->gadget)) {
+		struct f_ecm_opts *ecm_opts;
+
+		ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
+		ecm_opts->bound = true;
+	} else {
+		struct f_gether_opts *geth_opts;
+
+		geth_opts = container_of(fi_geth, struct f_gether_opts,
+					 func_inst);
+		geth_opts->bound = true;
+	}
+
+	rndis_borrow_net(fi_rndis, net);
+#endif
+
+	/* TODO: gstrings_attach? */
+	ret = usb_string_ids_tab(cdev, gfs_strings);
+	if (unlikely(ret < 0))
+		goto error_rndis;
+	gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
 
 	for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
 		struct gfs_configuration *c = gfs_configurations + i;
@@ -389,6 +417,8 @@
 		c->c.bConfigurationValue	= 1 + i;
 		c->c.bmAttributes		= USB_CONFIG_ATT_SELFPOWER;
 
+		c->num = i;
+
 		ret = usb_add_config(cdev, &c->c, gfs_do_config);
 		if (unlikely(ret < 0))
 			goto error_unbind;
@@ -396,18 +426,24 @@
 	usb_composite_overwrite_options(cdev, &coverwrite);
 	return 0;
 
+/* TODO */
 error_unbind:
-	for (i = 0; i < func_num; i++)
-		functionfs_unbind(ffs_tab[i].ffs_data);
+error_rndis:
+#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
+	usb_put_function_instance(fi_rndis);
 error:
-	gether_cleanup(the_dev);
-error_quick:
-	gfs_ether_setup = false;
+#endif
+#if defined CONFIG_USB_FUNCTIONFS_ETH
+	if (can_support_ecm(cdev->gadget))
+		usb_put_function_instance(fi_ecm);
+	else
+		usb_put_function_instance(fi_geth);
+#endif
 	return ret;
 }
 
 /*
- * It is assumed that gfs_unbind is called from a context where gfs_lock is held
+ * It is assumed that gfs_unbind is called from a context where ffs_lock is held
  */
 static int gfs_unbind(struct usb_composite_dev *cdev)
 {
@@ -415,28 +451,30 @@
 
 	ENTER();
 
-	/*
-	 * We may have been called in an error recovery from
-	 * composite_bind() after gfs_unbind() failure so we need to
-	 * check if gfs_ffs_data is not NULL since gfs_bind() handles
-	 * all error recovery itself.  I'd rather we werent called
-	 * from composite on orror recovery, but what you're gonna
-	 * do...?
-	 */
-	if (gfs_ether_setup)
-		gether_cleanup(the_dev);
-	gfs_ether_setup = false;
 
-	for (i = func_num; i--; )
-		if (ffs_tab[i].ffs_data)
-			functionfs_unbind(ffs_tab[i].ffs_data);
+#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
+	usb_put_function(f_rndis);
+	usb_put_function_instance(fi_rndis);
+#endif
+
+#if defined CONFIG_USB_FUNCTIONFS_ETH
+	if (can_support_ecm(cdev->gadget)) {
+		usb_put_function(f_ecm);
+		usb_put_function_instance(fi_ecm);
+	} else {
+		usb_put_function(f_geth);
+		usb_put_function_instance(fi_geth);
+	}
+#endif
+	for (i = 0; i < N_CONF * func_num; ++i)
+		usb_put_function(*(f_ffs[0] + i));
 
 	return 0;
 }
 
 /*
  * It is assumed that gfs_do_config is called from a context where
- * gfs_lock is held
+ * ffs_lock is held
  */
 static int gfs_do_config(struct usb_configuration *c)
 {
@@ -454,15 +492,22 @@
 	}
 
 	if (gc->eth) {
-		ret = gc->eth(c, gfs_host_mac, the_dev);
+		ret = gc->eth(c);
 		if (unlikely(ret < 0))
 			return ret;
 	}
 
 	for (i = 0; i < func_num; i++) {
-		ret = functionfs_bind_config(c->cdev, c, ffs_tab[i].ffs_data);
-		if (unlikely(ret < 0))
-			return ret;
+		f_ffs[gc->num][i] = usb_get_function(fi_ffs[i]);
+		if (IS_ERR(f_ffs[gc->num][i])) {
+			ret = PTR_ERR(f_ffs[gc->num][i]);
+			goto error;
+		}
+		ret = usb_add_function(c, f_ffs[gc->num][i]);
+		if (ret < 0) {
+			usb_put_function(f_ffs[gc->num][i]);
+			goto error;
+		}
 	}
 
 	/*
@@ -479,16 +524,59 @@
 		c->interface[c->next_interface_id] = NULL;
 
 	return 0;
+error:
+	while (--i >= 0) {
+		if (!IS_ERR(f_ffs[gc->num][i]))
+			usb_remove_function(c, f_ffs[gc->num][i]);
+		usb_put_function(f_ffs[gc->num][i]);
+	}
+	return ret;
 }
 
 #ifdef CONFIG_USB_FUNCTIONFS_ETH
 
-static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-		struct eth_dev *dev)
+static int eth_bind_config(struct usb_configuration *c)
 {
-	return can_support_ecm(c->cdev->gadget)
-		? ecm_bind_config(c, ethaddr, dev)
-		: geth_bind_config(c, ethaddr, dev);
+	int status = 0;
+
+	if (can_support_ecm(c->cdev->gadget)) {
+		f_ecm = usb_get_function(fi_ecm);
+		if (IS_ERR(f_ecm))
+			return PTR_ERR(f_ecm);
+
+		status = usb_add_function(c, f_ecm);
+		if (status < 0)
+			usb_put_function(f_ecm);
+
+	} else {
+		f_geth = usb_get_function(fi_geth);
+		if (IS_ERR(f_geth))
+			return PTR_ERR(f_geth);
+
+		status = usb_add_function(c, f_geth);
+		if (status < 0)
+			usb_put_function(f_geth);
+	}
+	return status;
+}
+
+#endif
+
+#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
+
+static int bind_rndis_config(struct usb_configuration *c)
+{
+	int status = 0;
+
+	f_rndis = usb_get_function(fi_rndis);
+	if (IS_ERR(f_rndis))
+		return PTR_ERR(f_rndis);
+
+	status = usb_add_function(c, f_rndis);
+	if (status < 0)
+		usb_put_function(f_rndis);
+
+	return status;
 }
 
 #endif
diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h
index ef3e851..15f1809 100644
--- a/drivers/usb/gadget/g_zero.h
+++ b/drivers/usb/gadget/g_zero.h
@@ -6,6 +6,11 @@
 #ifndef __G_ZERO_H
 #define __G_ZERO_H
 
+#define GZERO_BULK_BUFLEN	4096
+#define GZERO_QLEN		32
+#define GZERO_ISOC_INTERVAL	4
+#define GZERO_ISOC_MAXPACKET	1024
+
 struct usb_zero_options {
 	unsigned pattern;
 	unsigned isoc_interval;
@@ -24,19 +29,36 @@
 	unsigned isoc_mult;
 	unsigned isoc_maxburst;
 	unsigned bulk_buflen;
+
+	/*
+	 * Read/write access to configfs attributes is handled by configfs.
+	 *
+	 * This is to protect the data from concurrent access by read/write
+	 * and create symlink/remove symlink.
+	 */
+	struct mutex			lock;
+	int				refcnt;
 };
 
 struct f_lb_opts {
 	struct usb_function_instance func_inst;
 	unsigned bulk_buflen;
 	unsigned qlen;
+
+	/*
+	 * Read/write access to configfs attributes is handled by configfs.
+	 *
+	 * This is to protect the data from concurrent access by read/write
+	 * and create symlink/remove symlink.
+	 */
+	struct mutex			lock;
+	int				refcnt;
 };
 
 void lb_modexit(void);
 int lb_modinit(void);
 
 /* common utilities */
-struct usb_request *alloc_ep_req(struct usb_ep *ep, int len);
 void free_ep_req(struct usb_ep *ep, struct usb_request *req);
 void disable_endpoints(struct usb_composite_dev *cdev,
 		struct usb_ep *in, struct usb_ep *out,
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index f827680..f66f3a7 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -231,7 +231,7 @@
 		}
 	}
 
-	ep->ep.maxpacket = MAX_FIFO_SIZE;
+	usb_ep_set_maxpacket_limit(&ep->ep, MAX_FIFO_SIZE);
 	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	ep->irqs = 0;
@@ -1251,7 +1251,7 @@
 	}
 
 	dev->ep[0].reg_mode = NULL;
-	dev->ep[0].ep.maxpacket = MAX_EP0_SIZE;
+	usb_ep_set_maxpacket_limit(&dev->ep[0].ep, MAX_EP0_SIZE);
 	list_del_init (&dev->ep[0].ep.ep_list);
 }
 
@@ -1350,16 +1350,12 @@
 	return 0;
 }
 
-static void
-stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
+static void stop_activity(struct goku_udc *dev)
 {
 	unsigned	i;
 
 	DBG (dev, "%s\n", __func__);
 
-	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-		driver = NULL;
-
 	/* disconnect gadget driver after quiesceing hw and the driver */
 	udc_reset (dev);
 	for (i = 0; i < 4; i++)
@@ -1377,7 +1373,7 @@
 
 	spin_lock_irqsave(&dev->lock, flags);
 	dev->driver = NULL;
-	stop_activity(dev, driver);
+	stop_activity(dev);
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 	return 0;
@@ -1521,7 +1517,7 @@
 	if (unlikely(stat & INT_DEVWIDE)) {
 		if (stat & INT_SYSERROR) {
 			ERROR(dev, "system error\n");
-			stop_activity(dev, dev->driver);
+			stop_activity(dev);
 			stat = 0;
 			handled = 1;
 			// FIXME have a neater way to prevent re-enumeration
@@ -1536,7 +1532,7 @@
 			} else {
 				DBG(dev, "disconnect\n");
 				if (dev->gadget.speed == USB_SPEED_FULL)
-					stop_activity(dev, dev->driver);
+					stop_activity(dev);
 				dev->ep0state = EP0_DISCONNECT;
 				dev->int_enable = INT_DEVWIDE;
 				writel(dev->int_enable, &dev->regs->int_enable);
diff --git a/drivers/usb/gadget/gr_udc.c b/drivers/usb/gadget/gr_udc.c
new file mode 100644
index 0000000..5f9c659
--- /dev/null
+++ b/drivers/usb/gadget/gr_udc.c
@@ -0,0 +1,2242 @@
+/*
+ * USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC.
+ *
+ * 2013 (c) Aeroflex Gaisler AB
+ *
+ * This driver supports GRUSBDC USB Device Controller cores available in the
+ * GRLIB VHDL IP core library.
+ *
+ * Full documentation of the GRUSBDC core can be found here:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ *
+ * 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.
+ *
+ * Contributors:
+ * - Andreas Larsson <andreas@gaisler.com>
+ * - Marko Isomaki
+ */
+
+/*
+ * A GRUSBDC core can have up to 16 IN endpoints and 16 OUT endpoints each
+ * individually configurable to any of the four USB transfer types. This driver
+ * only supports cores in DMA mode.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include <asm/byteorder.h>
+
+#include "gr_udc.h"
+
+#define	DRIVER_NAME	"gr_udc"
+#define	DRIVER_DESC	"Aeroflex Gaisler GRUSBDC USB Peripheral Controller"
+
+static const char driver_name[] = DRIVER_NAME;
+static const char driver_desc[] = DRIVER_DESC;
+
+#define gr_read32(x) (ioread32be((x)))
+#define gr_write32(x, v) (iowrite32be((v), (x)))
+
+/* USB speed and corresponding string calculated from status register value */
+#define GR_SPEED(status) \
+	((status & GR_STATUS_SP) ? USB_SPEED_FULL : USB_SPEED_HIGH)
+#define GR_SPEED_STR(status) usb_speed_string(GR_SPEED(status))
+
+/* Size of hardware buffer calculated from epctrl register value */
+#define GR_BUFFER_SIZE(epctrl)					      \
+	((((epctrl) & GR_EPCTRL_BUFSZ_MASK) >> GR_EPCTRL_BUFSZ_POS) * \
+	 GR_EPCTRL_BUFSZ_SCALER)
+
+/* ---------------------------------------------------------------------- */
+/* Debug printout functionality */
+
+static const char * const gr_modestring[] = {"control", "iso", "bulk", "int"};
+
+static const char *gr_ep0state_string(enum gr_ep0state state)
+{
+	static const char *const names[] = {
+		[GR_EP0_DISCONNECT] = "disconnect",
+		[GR_EP0_SETUP] = "setup",
+		[GR_EP0_IDATA] = "idata",
+		[GR_EP0_ODATA] = "odata",
+		[GR_EP0_ISTATUS] = "istatus",
+		[GR_EP0_OSTATUS] = "ostatus",
+		[GR_EP0_STALL] = "stall",
+		[GR_EP0_SUSPEND] = "suspend",
+	};
+
+	if (state < 0 || state >= ARRAY_SIZE(names))
+		return "UNKNOWN";
+
+	return names[state];
+}
+
+#ifdef VERBOSE_DEBUG
+
+static void gr_dbgprint_request(const char *str, struct gr_ep *ep,
+				struct gr_request *req)
+{
+	int buflen = ep->is_in ? req->req.length : req->req.actual;
+	int rowlen = 32;
+	int plen = min(rowlen, buflen);
+
+	dev_dbg(ep->dev->dev, "%s: 0x%p, %d bytes data%s:\n", str, req, buflen,
+		(buflen > plen ? " (truncated)" : ""));
+	print_hex_dump_debug("   ", DUMP_PREFIX_NONE,
+			     rowlen, 4, req->req.buf, plen, false);
+}
+
+static void gr_dbgprint_devreq(struct gr_udc *dev, u8 type, u8 request,
+			       u16 value, u16 index, u16 length)
+{
+	dev_vdbg(dev->dev, "REQ: %02x.%02x v%04x i%04x l%04x\n",
+		 type, request, value, index, length);
+}
+#else /* !VERBOSE_DEBUG */
+
+static void gr_dbgprint_request(const char *str, struct gr_ep *ep,
+				struct gr_request *req) {}
+
+static void gr_dbgprint_devreq(struct gr_udc *dev, u8 type, u8 request,
+			       u16 value, u16 index, u16 length) {}
+
+#endif /* VERBOSE_DEBUG */
+
+/* ---------------------------------------------------------------------- */
+/* Debugfs functionality */
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+
+static void gr_seq_ep_show(struct seq_file *seq, struct gr_ep *ep)
+{
+	u32 epctrl = gr_read32(&ep->regs->epctrl);
+	u32 epstat = gr_read32(&ep->regs->epstat);
+	int mode = (epctrl & GR_EPCTRL_TT_MASK) >> GR_EPCTRL_TT_POS;
+	struct gr_request *req;
+
+	seq_printf(seq, "%s:\n", ep->ep.name);
+	seq_printf(seq, "  mode = %s\n", gr_modestring[mode]);
+	seq_printf(seq, "  halted: %d\n", !!(epctrl & GR_EPCTRL_EH));
+	seq_printf(seq, "  disabled: %d\n", !!(epctrl & GR_EPCTRL_ED));
+	seq_printf(seq, "  valid: %d\n", !!(epctrl & GR_EPCTRL_EV));
+	seq_printf(seq, "  dma_start = %d\n", ep->dma_start);
+	seq_printf(seq, "  stopped = %d\n", ep->stopped);
+	seq_printf(seq, "  wedged = %d\n", ep->wedged);
+	seq_printf(seq, "  callback = %d\n", ep->callback);
+	seq_printf(seq, "  maxpacket = %d\n", ep->ep.maxpacket);
+	seq_printf(seq, "  bytes_per_buffer = %d\n", ep->bytes_per_buffer);
+	if (mode == 1 || mode == 3)
+		seq_printf(seq, "  nt = %d\n",
+			   (epctrl & GR_EPCTRL_NT_MASK) >> GR_EPCTRL_NT_POS);
+
+	seq_printf(seq, "  Buffer 0: %s %s%d\n",
+		   epstat & GR_EPSTAT_B0 ? "valid" : "invalid",
+		   epstat & GR_EPSTAT_BS ? " " : "selected ",
+		   (epstat & GR_EPSTAT_B0CNT_MASK) >> GR_EPSTAT_B0CNT_POS);
+	seq_printf(seq, "  Buffer 1: %s %s%d\n",
+		   epstat & GR_EPSTAT_B1 ? "valid" : "invalid",
+		   epstat & GR_EPSTAT_BS ? "selected " : " ",
+		   (epstat & GR_EPSTAT_B1CNT_MASK) >> GR_EPSTAT_B1CNT_POS);
+
+	if (list_empty(&ep->queue)) {
+		seq_puts(seq, "  Queue: empty\n\n");
+		return;
+	}
+
+	seq_puts(seq, "  Queue:\n");
+	list_for_each_entry(req, &ep->queue, queue) {
+		struct gr_dma_desc *desc;
+		struct gr_dma_desc *next;
+
+		seq_printf(seq, "    0x%p: 0x%p %d %d\n", req,
+			   &req->req.buf, req->req.actual, req->req.length);
+
+		next = req->first_desc;
+		do {
+			desc = next;
+			next = desc->next_desc;
+			seq_printf(seq, "    %c 0x%p (0x%08x): 0x%05x 0x%08x\n",
+				   desc == req->curr_desc ? 'c' : ' ',
+				   desc, desc->paddr, desc->ctrl, desc->data);
+		} while (desc != req->last_desc);
+	}
+	seq_puts(seq, "\n");
+}
+
+
+static int gr_seq_show(struct seq_file *seq, void *v)
+{
+	struct gr_udc *dev = seq->private;
+	u32 control = gr_read32(&dev->regs->control);
+	u32 status = gr_read32(&dev->regs->status);
+	struct gr_ep *ep;
+
+	seq_printf(seq, "usb state = %s\n",
+		   usb_state_string(dev->gadget.state));
+	seq_printf(seq, "address = %d\n",
+		   (control & GR_CONTROL_UA_MASK) >> GR_CONTROL_UA_POS);
+	seq_printf(seq, "speed = %s\n", GR_SPEED_STR(status));
+	seq_printf(seq, "ep0state = %s\n", gr_ep0state_string(dev->ep0state));
+	seq_printf(seq, "irq_enabled = %d\n", dev->irq_enabled);
+	seq_printf(seq, "remote_wakeup = %d\n", dev->remote_wakeup);
+	seq_printf(seq, "test_mode = %d\n", dev->test_mode);
+	seq_puts(seq, "\n");
+
+	list_for_each_entry(ep, &dev->ep_list, ep_list)
+		gr_seq_ep_show(seq, ep);
+
+	return 0;
+}
+
+static int gr_dfs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, gr_seq_show, inode->i_private);
+}
+
+static const struct file_operations gr_dfs_fops = {
+	.owner		= THIS_MODULE,
+	.open		= gr_dfs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void gr_dfs_create(struct gr_udc *dev)
+{
+	const char *name = "gr_udc_state";
+
+	dev->dfs_root = debugfs_create_dir(dev_name(dev->dev), NULL);
+	if (IS_ERR(dev->dfs_root)) {
+		dev_err(dev->dev, "Failed to create debugfs directory\n");
+		return;
+	}
+	dev->dfs_state = debugfs_create_file(name, 0444, dev->dfs_root,
+					     dev, &gr_dfs_fops);
+	if (IS_ERR(dev->dfs_state))
+		dev_err(dev->dev, "Failed to create debugfs file %s\n", name);
+}
+
+static void gr_dfs_delete(struct gr_udc *dev)
+{
+	/* Handles NULL and ERR pointers internally */
+	debugfs_remove(dev->dfs_state);
+	debugfs_remove(dev->dfs_root);
+}
+
+#else /* !CONFIG_USB_GADGET_DEBUG_FS */
+
+static void gr_dfs_create(struct gr_udc *dev) {}
+static void gr_dfs_delete(struct gr_udc *dev) {}
+
+#endif /* CONFIG_USB_GADGET_DEBUG_FS */
+
+/* ---------------------------------------------------------------------- */
+/* DMA and request handling */
+
+/* Allocates a new struct gr_dma_desc, sets paddr and zeroes the rest */
+static struct gr_dma_desc *gr_alloc_dma_desc(struct gr_ep *ep, gfp_t gfp_flags)
+{
+	dma_addr_t paddr;
+	struct gr_dma_desc *dma_desc;
+
+	dma_desc = dma_pool_alloc(ep->dev->desc_pool, gfp_flags, &paddr);
+	if (!dma_desc) {
+		dev_err(ep->dev->dev, "Could not allocate from DMA pool\n");
+		return NULL;
+	}
+
+	memset(dma_desc, 0, sizeof(*dma_desc));
+	dma_desc->paddr = paddr;
+
+	return dma_desc;
+}
+
+static inline void gr_free_dma_desc(struct gr_udc *dev,
+				    struct gr_dma_desc *desc)
+{
+	dma_pool_free(dev->desc_pool, desc, (dma_addr_t)desc->paddr);
+}
+
+/* Frees the chain of struct gr_dma_desc for the given request */
+static void gr_free_dma_desc_chain(struct gr_udc *dev, struct gr_request *req)
+{
+	struct gr_dma_desc *desc;
+	struct gr_dma_desc *next;
+
+	next = req->first_desc;
+	if (!next)
+		return;
+
+	do {
+		desc = next;
+		next = desc->next_desc;
+		gr_free_dma_desc(dev, desc);
+	} while (desc != req->last_desc);
+
+	req->first_desc = NULL;
+	req->curr_desc = NULL;
+	req->last_desc = NULL;
+}
+
+static void gr_ep0_setup(struct gr_udc *dev, struct gr_request *req);
+
+/*
+ * Frees allocated resources and calls the appropriate completion function/setup
+ * package handler for a finished request.
+ *
+ * Must be called with dev->lock held and irqs disabled.
+ */
+static void gr_finish_request(struct gr_ep *ep, struct gr_request *req,
+			      int status)
+	__releases(&dev->lock)
+	__acquires(&dev->lock)
+{
+	struct gr_udc *dev;
+
+	list_del_init(&req->queue);
+
+	if (likely(req->req.status == -EINPROGRESS))
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	dev = ep->dev;
+	usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
+	gr_free_dma_desc_chain(dev, req);
+
+	if (ep->is_in) /* For OUT, actual gets updated bit by bit */
+		req->req.actual = req->req.length;
+
+	if (!status) {
+		if (ep->is_in)
+			gr_dbgprint_request("SENT", ep, req);
+		else
+			gr_dbgprint_request("RECV", ep, req);
+	}
+
+	/* Prevent changes to ep->queue during callback */
+	ep->callback = 1;
+	if (req == dev->ep0reqo && !status) {
+		if (req->setup)
+			gr_ep0_setup(dev, req);
+		else
+			dev_err(dev->dev,
+				"Unexpected non setup packet on ep0in\n");
+	} else if (req->req.complete) {
+		spin_unlock(&dev->lock);
+
+		req->req.complete(&ep->ep, &req->req);
+
+		spin_lock(&dev->lock);
+	}
+	ep->callback = 0;
+}
+
+static struct usb_request *gr_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+	struct gr_request *req;
+
+	req = kzalloc(sizeof(*req), gfp_flags);
+	if (!req)
+		return NULL;
+
+	INIT_LIST_HEAD(&req->queue);
+
+	return &req->req;
+}
+
+/*
+ * Starts DMA for endpoint ep if there are requests in the queue.
+ *
+ * Must be called with dev->lock held and with !ep->stopped.
+ */
+static void gr_start_dma(struct gr_ep *ep)
+{
+	struct gr_request *req;
+	u32 dmactrl;
+
+	if (list_empty(&ep->queue)) {
+		ep->dma_start = 0;
+		return;
+	}
+
+	req = list_first_entry(&ep->queue, struct gr_request, queue);
+
+	/* A descriptor should already have been allocated */
+	BUG_ON(!req->curr_desc);
+
+	wmb(); /* Make sure all is settled before handing it over to DMA */
+
+	/* Set the descriptor pointer in the hardware */
+	gr_write32(&ep->regs->dmaaddr, req->curr_desc->paddr);
+
+	/* Announce available descriptors */
+	dmactrl = gr_read32(&ep->regs->dmactrl);
+	gr_write32(&ep->regs->dmactrl, dmactrl | GR_DMACTRL_DA);
+
+	ep->dma_start = 1;
+}
+
+/*
+ * Finishes the first request in the ep's queue and, if available, starts the
+ * next request in queue.
+ *
+ * Must be called with dev->lock held, irqs disabled and with !ep->stopped.
+ */
+static void gr_dma_advance(struct gr_ep *ep, int status)
+{
+	struct gr_request *req;
+
+	req = list_first_entry(&ep->queue, struct gr_request, queue);
+	gr_finish_request(ep, req, status);
+	gr_start_dma(ep); /* Regardless of ep->dma_start */
+}
+
+/*
+ * Abort DMA for an endpoint. Sets the abort DMA bit which causes an ongoing DMA
+ * transfer to be canceled and clears GR_DMACTRL_DA.
+ *
+ * Must be called with dev->lock held.
+ */
+static void gr_abort_dma(struct gr_ep *ep)
+{
+	u32 dmactrl;
+
+	dmactrl = gr_read32(&ep->regs->dmactrl);
+	gr_write32(&ep->regs->dmactrl, dmactrl | GR_DMACTRL_AD);
+}
+
+/*
+ * Allocates and sets up a struct gr_dma_desc and putting it on the descriptor
+ * chain.
+ *
+ * Size is not used for OUT endpoints. Hardware can not be instructed to handle
+ * smaller buffer than MAXPL in the OUT direction.
+ */
+static int gr_add_dma_desc(struct gr_ep *ep, struct gr_request *req,
+			   dma_addr_t data, unsigned size, gfp_t gfp_flags)
+{
+	struct gr_dma_desc *desc;
+
+	desc = gr_alloc_dma_desc(ep, gfp_flags);
+	if (!desc)
+		return -ENOMEM;
+
+	desc->data = data;
+	if (ep->is_in)
+		desc->ctrl =
+			(GR_DESC_IN_CTRL_LEN_MASK & size) | GR_DESC_IN_CTRL_EN;
+	else
+		desc->ctrl = GR_DESC_OUT_CTRL_IE;
+
+	if (!req->first_desc) {
+		req->first_desc = desc;
+		req->curr_desc = desc;
+	} else {
+		req->last_desc->next_desc = desc;
+		req->last_desc->next = desc->paddr;
+		req->last_desc->ctrl |= GR_DESC_OUT_CTRL_NX;
+	}
+	req->last_desc = desc;
+
+	return 0;
+}
+
+/*
+ * Sets up a chain of struct gr_dma_descriptors pointing to buffers that
+ * together covers req->req.length bytes of the buffer at DMA address
+ * req->req.dma for the OUT direction.
+ *
+ * The first descriptor in the chain is enabled, the rest disabled. The
+ * interrupt handler will later enable them one by one when needed so we can
+ * find out when the transfer is finished. For OUT endpoints, all descriptors
+ * therefore generate interrutps.
+ */
+static int gr_setup_out_desc_list(struct gr_ep *ep, struct gr_request *req,
+				  gfp_t gfp_flags)
+{
+	u16 bytes_left; /* Bytes left to provide descriptors for */
+	u16 bytes_used; /* Bytes accommodated for */
+	int ret = 0;
+
+	req->first_desc = NULL; /* Signals that no allocation is done yet */
+	bytes_left = req->req.length;
+	bytes_used = 0;
+	while (bytes_left > 0) {
+		dma_addr_t start = req->req.dma + bytes_used;
+		u16 size = min(bytes_left, ep->bytes_per_buffer);
+
+		/* Should not happen however - gr_queue stops such lengths */
+		if (size < ep->bytes_per_buffer)
+			dev_warn(ep->dev->dev,
+				 "Buffer overrun risk: %u < %u bytes/buffer\n",
+				 size, ep->bytes_per_buffer);
+
+		ret = gr_add_dma_desc(ep, req, start, size, gfp_flags);
+		if (ret)
+			goto alloc_err;
+
+		bytes_left -= size;
+		bytes_used += size;
+	}
+
+	req->first_desc->ctrl |= GR_DESC_OUT_CTRL_EN;
+
+	return 0;
+
+alloc_err:
+	gr_free_dma_desc_chain(ep->dev, req);
+
+	return ret;
+}
+
+/*
+ * Sets up a chain of struct gr_dma_descriptors pointing to buffers that
+ * together covers req->req.length bytes of the buffer at DMA address
+ * req->req.dma for the IN direction.
+ *
+ * When more data is provided than the maximum payload size, the hardware splits
+ * this up into several payloads automatically. Moreover, ep->bytes_per_buffer
+ * is always set to a multiple of the maximum payload (restricted to the valid
+ * number of maximum payloads during high bandwidth isochronous or interrupt
+ * transfers)
+ *
+ * All descriptors are enabled from the beginning and we only generate an
+ * interrupt for the last one indicating that the entire request has been pushed
+ * to hardware.
+ */
+static int gr_setup_in_desc_list(struct gr_ep *ep, struct gr_request *req,
+				 gfp_t gfp_flags)
+{
+	u16 bytes_left; /* Bytes left in req to provide descriptors for */
+	u16 bytes_used; /* Bytes in req accommodated for */
+	int ret = 0;
+
+	req->first_desc = NULL; /* Signals that no allocation is done yet */
+	bytes_left = req->req.length;
+	bytes_used = 0;
+	do { /* Allow for zero length packets */
+		dma_addr_t start = req->req.dma + bytes_used;
+		u16 size = min(bytes_left, ep->bytes_per_buffer);
+
+		ret = gr_add_dma_desc(ep, req, start, size, gfp_flags);
+		if (ret)
+			goto alloc_err;
+
+		bytes_left -= size;
+		bytes_used += size;
+	} while (bytes_left > 0);
+
+	/*
+	 * Send an extra zero length packet to indicate that no more data is
+	 * available when req->req.zero is set and the data length is even
+	 * multiples of ep->ep.maxpacket.
+	 */
+	if (req->req.zero && (req->req.length % ep->ep.maxpacket == 0)) {
+		ret = gr_add_dma_desc(ep, req, 0, 0, gfp_flags);
+		if (ret)
+			goto alloc_err;
+	}
+
+	/*
+	 * For IN packets we only want to know when the last packet has been
+	 * transmitted (not just put into internal buffers).
+	 */
+	req->last_desc->ctrl |= GR_DESC_IN_CTRL_PI;
+
+	return 0;
+
+alloc_err:
+	gr_free_dma_desc_chain(ep->dev, req);
+
+	return ret;
+}
+
+/* Must be called with dev->lock held */
+static int gr_queue(struct gr_ep *ep, struct gr_request *req, gfp_t gfp_flags)
+{
+	struct gr_udc *dev = ep->dev;
+	int ret;
+
+	if (unlikely(!ep->ep.desc && ep->num != 0)) {
+		dev_err(dev->dev, "No ep descriptor for %s\n", ep->ep.name);
+		return -EINVAL;
+	}
+
+	if (unlikely(!req->req.buf || !list_empty(&req->queue))) {
+		dev_err(dev->dev,
+			"Invalid request for %s: buf=%p list_empty=%d\n",
+			ep->ep.name, req->req.buf, list_empty(&req->queue));
+		return -EINVAL;
+	}
+
+	/*
+	 * The DMA controller can not handle smaller OUT buffers than
+	 * maxpacket. It could lead to buffer overruns if unexpectedly long
+	 * packet are received.
+	 */
+	if (!ep->is_in && (req->req.length % ep->ep.maxpacket) != 0) {
+		dev_err(dev->dev,
+			"OUT request length %d is not multiple of maxpacket\n",
+			req->req.length);
+		return -EMSGSIZE;
+	}
+
+	if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+		dev_err(dev->dev, "-ESHUTDOWN");
+		return -ESHUTDOWN;
+	}
+
+	/* Can't touch registers when suspended */
+	if (dev->ep0state == GR_EP0_SUSPEND) {
+		dev_err(dev->dev, "-EBUSY");
+		return -EBUSY;
+	}
+
+	/* Set up DMA mapping in case the caller didn't */
+	ret = usb_gadget_map_request(&dev->gadget, &req->req, ep->is_in);
+	if (ret) {
+		dev_err(dev->dev, "usb_gadget_map_request");
+		return ret;
+	}
+
+	if (ep->is_in)
+		ret = gr_setup_in_desc_list(ep, req, gfp_flags);
+	else
+		ret = gr_setup_out_desc_list(ep, req, gfp_flags);
+	if (ret)
+		return ret;
+
+	req->req.status = -EINPROGRESS;
+	req->req.actual = 0;
+	list_add_tail(&req->queue, &ep->queue);
+
+	/* Start DMA if not started, otherwise interrupt handler handles it */
+	if (!ep->dma_start && likely(!ep->stopped))
+		gr_start_dma(ep);
+
+	return 0;
+}
+
+/*
+ * Queue a request from within the driver.
+ *
+ * Must be called with dev->lock held.
+ */
+static inline int gr_queue_int(struct gr_ep *ep, struct gr_request *req,
+			       gfp_t gfp_flags)
+{
+	if (ep->is_in)
+		gr_dbgprint_request("RESP", ep, req);
+
+	return gr_queue(ep, req, gfp_flags);
+}
+
+/* ---------------------------------------------------------------------- */
+/* General helper functions */
+
+/*
+ * Dequeue ALL requests.
+ *
+ * Must be called with dev->lock held and irqs disabled.
+ */
+static void gr_ep_nuke(struct gr_ep *ep)
+{
+	struct gr_request *req;
+	struct gr_udc *dev;
+
+	dev = ep->dev;
+
+	ep->stopped = 1;
+	ep->dma_start = 0;
+	gr_abort_dma(ep);
+
+	while (!list_empty(&ep->queue)) {
+		req = list_first_entry(&ep->queue, struct gr_request, queue);
+		gr_finish_request(ep, req, -ESHUTDOWN);
+	}
+}
+
+/*
+ * Reset the hardware state of this endpoint.
+ *
+ * Must be called with dev->lock held.
+ */
+static void gr_ep_reset(struct gr_ep *ep)
+{
+	gr_write32(&ep->regs->epctrl, 0);
+	gr_write32(&ep->regs->dmactrl, 0);
+
+	ep->ep.maxpacket = MAX_CTRL_PL_SIZE;
+	ep->ep.desc = NULL;
+	ep->stopped = 1;
+	ep->dma_start = 0;
+}
+
+/*
+ * Generate STALL on ep0in/out.
+ *
+ * Must be called with dev->lock held.
+ */
+static void gr_control_stall(struct gr_udc *dev)
+{
+	u32 epctrl;
+
+	epctrl = gr_read32(&dev->epo[0].regs->epctrl);
+	gr_write32(&dev->epo[0].regs->epctrl, epctrl | GR_EPCTRL_CS);
+	epctrl = gr_read32(&dev->epi[0].regs->epctrl);
+	gr_write32(&dev->epi[0].regs->epctrl, epctrl | GR_EPCTRL_CS);
+
+	dev->ep0state = GR_EP0_STALL;
+}
+
+/*
+ * Halts, halts and wedges, or clears halt for an endpoint.
+ *
+ * Must be called with dev->lock held.
+ */
+static int gr_ep_halt_wedge(struct gr_ep *ep, int halt, int wedge, int fromhost)
+{
+	u32 epctrl;
+	int retval = 0;
+
+	if (ep->num && !ep->ep.desc)
+		return -EINVAL;
+
+	if (ep->num && ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC)
+		return -EOPNOTSUPP;
+
+	/* Never actually halt ep0, and therefore never clear halt for ep0 */
+	if (!ep->num) {
+		if (halt && !fromhost) {
+			/* ep0 halt from gadget - generate protocol stall */
+			gr_control_stall(ep->dev);
+			dev_dbg(ep->dev->dev, "EP: stall ep0\n");
+			return 0;
+		}
+		return -EINVAL;
+	}
+
+	dev_dbg(ep->dev->dev, "EP: %s halt %s\n",
+		(halt ? (wedge ? "wedge" : "set") : "clear"), ep->ep.name);
+
+	epctrl = gr_read32(&ep->regs->epctrl);
+	if (halt) {
+		/* Set HALT */
+		gr_write32(&ep->regs->epctrl, epctrl | GR_EPCTRL_EH);
+		ep->stopped = 1;
+		if (wedge)
+			ep->wedged = 1;
+	} else {
+		gr_write32(&ep->regs->epctrl, epctrl & ~GR_EPCTRL_EH);
+		ep->stopped = 0;
+		ep->wedged = 0;
+
+		/* Things might have been queued up in the meantime */
+		if (!ep->dma_start)
+			gr_start_dma(ep);
+	}
+
+	return retval;
+}
+
+/* Must be called with dev->lock held */
+static inline void gr_set_ep0state(struct gr_udc *dev, enum gr_ep0state value)
+{
+	if (dev->ep0state != value)
+		dev_vdbg(dev->dev, "STATE:  ep0state=%s\n",
+			 gr_ep0state_string(value));
+	dev->ep0state = value;
+}
+
+/*
+ * Should only be called when endpoints can not generate interrupts.
+ *
+ * Must be called with dev->lock held.
+ */
+static void gr_disable_interrupts_and_pullup(struct gr_udc *dev)
+{
+	gr_write32(&dev->regs->control, 0);
+	wmb(); /* Make sure that we do not deny one of our interrupts */
+	dev->irq_enabled = 0;
+}
+
+/*
+ * Stop all device activity and disable data line pullup.
+ *
+ * Must be called with dev->lock held and irqs disabled.
+ */
+static void gr_stop_activity(struct gr_udc *dev)
+{
+	struct gr_ep *ep;
+
+	list_for_each_entry(ep, &dev->ep_list, ep_list)
+		gr_ep_nuke(ep);
+
+	gr_disable_interrupts_and_pullup(dev);
+
+	gr_set_ep0state(dev, GR_EP0_DISCONNECT);
+	usb_gadget_set_state(&dev->gadget, USB_STATE_NOTATTACHED);
+}
+
+/* ---------------------------------------------------------------------- */
+/* ep0 setup packet handling */
+
+static void gr_ep0_testmode_complete(struct usb_ep *_ep,
+				     struct usb_request *_req)
+{
+	struct gr_ep *ep;
+	struct gr_udc *dev;
+	u32 control;
+
+	ep = container_of(_ep, struct gr_ep, ep);
+	dev = ep->dev;
+
+	spin_lock(&dev->lock);
+
+	control = gr_read32(&dev->regs->control);
+	control |= GR_CONTROL_TM | (dev->test_mode << GR_CONTROL_TS_POS);
+	gr_write32(&dev->regs->control, control);
+
+	spin_unlock(&dev->lock);
+}
+
+static void gr_ep0_dummy_complete(struct usb_ep *_ep, struct usb_request *_req)
+{
+	/* Nothing needs to be done here */
+}
+
+/*
+ * Queue a response on ep0in.
+ *
+ * Must be called with dev->lock held.
+ */
+static int gr_ep0_respond(struct gr_udc *dev, u8 *buf, int length,
+			  void (*complete)(struct usb_ep *ep,
+					   struct usb_request *req))
+{
+	u8 *reqbuf = dev->ep0reqi->req.buf;
+	int status;
+	int i;
+
+	for (i = 0; i < length; i++)
+		reqbuf[i] = buf[i];
+	dev->ep0reqi->req.length = length;
+	dev->ep0reqi->req.complete = complete;
+
+	status = gr_queue_int(&dev->epi[0], dev->ep0reqi, GFP_ATOMIC);
+	if (status < 0)
+		dev_err(dev->dev,
+			"Could not queue ep0in setup response: %d\n", status);
+
+	return status;
+}
+
+/*
+ * Queue a 2 byte response on ep0in.
+ *
+ * Must be called with dev->lock held.
+ */
+static inline int gr_ep0_respond_u16(struct gr_udc *dev, u16 response)
+{
+	__le16 le_response = cpu_to_le16(response);
+
+	return gr_ep0_respond(dev, (u8 *)&le_response, 2,
+			      gr_ep0_dummy_complete);
+}
+
+/*
+ * Queue a ZLP response on ep0in.
+ *
+ * Must be called with dev->lock held.
+ */
+static inline int gr_ep0_respond_empty(struct gr_udc *dev)
+{
+	return gr_ep0_respond(dev, NULL, 0, gr_ep0_dummy_complete);
+}
+
+/*
+ * This is run when a SET_ADDRESS request is received. First writes
+ * the new address to the control register which is updated internally
+ * when the next IN packet is ACKED.
+ *
+ * Must be called with dev->lock held.
+ */
+static void gr_set_address(struct gr_udc *dev, u8 address)
+{
+	u32 control;
+
+	control = gr_read32(&dev->regs->control) & ~GR_CONTROL_UA_MASK;
+	control |= (address << GR_CONTROL_UA_POS) & GR_CONTROL_UA_MASK;
+	control |= GR_CONTROL_SU;
+	gr_write32(&dev->regs->control, control);
+}
+
+/*
+ * Returns negative for STALL, 0 for successful handling and positive for
+ * delegation.
+ *
+ * Must be called with dev->lock held.
+ */
+static int gr_device_request(struct gr_udc *dev, u8 type, u8 request,
+			     u16 value, u16 index)
+{
+	u16 response;
+	u8 test;
+
+	switch (request) {
+	case USB_REQ_SET_ADDRESS:
+		dev_dbg(dev->dev, "STATUS: address %d\n", value & 0xff);
+		gr_set_address(dev, value & 0xff);
+		if (value)
+			usb_gadget_set_state(&dev->gadget, USB_STATE_ADDRESS);
+		else
+			usb_gadget_set_state(&dev->gadget, USB_STATE_DEFAULT);
+		return gr_ep0_respond_empty(dev);
+
+	case USB_REQ_GET_STATUS:
+		/* Self powered | remote wakeup */
+		response = 0x0001 | (dev->remote_wakeup ? 0x0002 : 0);
+		return gr_ep0_respond_u16(dev, response);
+
+	case USB_REQ_SET_FEATURE:
+		switch (value) {
+		case USB_DEVICE_REMOTE_WAKEUP:
+			/* Allow remote wakeup */
+			dev->remote_wakeup = 1;
+			return gr_ep0_respond_empty(dev);
+
+		case USB_DEVICE_TEST_MODE:
+			/* The hardware does not support TEST_FORCE_EN */
+			test = index >> 8;
+			if (test >= TEST_J && test <= TEST_PACKET) {
+				dev->test_mode = test;
+				return gr_ep0_respond(dev, NULL, 0,
+						      gr_ep0_testmode_complete);
+			}
+		}
+		break;
+
+	case USB_REQ_CLEAR_FEATURE:
+		switch (value) {
+		case USB_DEVICE_REMOTE_WAKEUP:
+			/* Disallow remote wakeup */
+			dev->remote_wakeup = 0;
+			return gr_ep0_respond_empty(dev);
+		}
+		break;
+	}
+
+	return 1; /* Delegate the rest */
+}
+
+/*
+ * Returns negative for STALL, 0 for successful handling and positive for
+ * delegation.
+ *
+ * Must be called with dev->lock held.
+ */
+static int gr_interface_request(struct gr_udc *dev, u8 type, u8 request,
+				u16 value, u16 index)
+{
+	if (dev->gadget.state != USB_STATE_CONFIGURED)
+		return -1;
+
+	/*
+	 * Should return STALL for invalid interfaces, but udc driver does not
+	 * know anything about that. However, many gadget drivers do not handle
+	 * GET_STATUS so we need to take care of that.
+	 */
+
+	switch (request) {
+	case USB_REQ_GET_STATUS:
+		return gr_ep0_respond_u16(dev, 0x0000);
+
+	case USB_REQ_SET_FEATURE:
+	case USB_REQ_CLEAR_FEATURE:
+		/*
+		 * No possible valid standard requests. Still let gadget drivers
+		 * have a go at it.
+		 */
+		break;
+	}
+
+	return 1; /* Delegate the rest */
+}
+
+/*
+ * Returns negative for STALL, 0 for successful handling and positive for
+ * delegation.
+ *
+ * Must be called with dev->lock held.
+ */
+static int gr_endpoint_request(struct gr_udc *dev, u8 type, u8 request,
+			       u16 value, u16 index)
+{
+	struct gr_ep *ep;
+	int status;
+	int halted;
+	u8 epnum = index & USB_ENDPOINT_NUMBER_MASK;
+	u8 is_in = index & USB_ENDPOINT_DIR_MASK;
+
+	if ((is_in && epnum >= dev->nepi) || (!is_in && epnum >= dev->nepo))
+		return -1;
+
+	if (dev->gadget.state != USB_STATE_CONFIGURED && epnum != 0)
+		return -1;
+
+	ep = (is_in ? &dev->epi[epnum] : &dev->epo[epnum]);
+
+	switch (request) {
+	case USB_REQ_GET_STATUS:
+		halted = gr_read32(&ep->regs->epctrl) & GR_EPCTRL_EH;
+		return gr_ep0_respond_u16(dev, halted ? 0x0001 : 0);
+
+	case USB_REQ_SET_FEATURE:
+		switch (value) {
+		case USB_ENDPOINT_HALT:
+			status = gr_ep_halt_wedge(ep, 1, 0, 1);
+			if (status >= 0)
+				status = gr_ep0_respond_empty(dev);
+			return status;
+		}
+		break;
+
+	case USB_REQ_CLEAR_FEATURE:
+		switch (value) {
+		case USB_ENDPOINT_HALT:
+			if (ep->wedged)
+				return -1;
+			status = gr_ep_halt_wedge(ep, 0, 0, 1);
+			if (status >= 0)
+				status = gr_ep0_respond_empty(dev);
+			return status;
+		}
+		break;
+	}
+
+	return 1; /* Delegate the rest */
+}
+
+/* Must be called with dev->lock held */
+static void gr_ep0out_requeue(struct gr_udc *dev)
+{
+	int ret = gr_queue_int(&dev->epo[0], dev->ep0reqo, GFP_ATOMIC);
+
+	if (ret)
+		dev_err(dev->dev, "Could not queue ep0out setup request: %d\n",
+			ret);
+}
+
+/*
+ * The main function dealing with setup requests on ep0.
+ *
+ * Must be called with dev->lock held and irqs disabled
+ */
+static void gr_ep0_setup(struct gr_udc *dev, struct gr_request *req)
+	__releases(&dev->lock)
+	__acquires(&dev->lock)
+{
+	union {
+		struct usb_ctrlrequest ctrl;
+		u8 raw[8];
+		u32 word[2];
+	} u;
+	u8 type;
+	u8 request;
+	u16 value;
+	u16 index;
+	u16 length;
+	int i;
+	int status;
+
+	/* Restore from ep0 halt */
+	if (dev->ep0state == GR_EP0_STALL) {
+		gr_set_ep0state(dev, GR_EP0_SETUP);
+		if (!req->req.actual)
+			goto out;
+	}
+
+	if (dev->ep0state == GR_EP0_ISTATUS) {
+		gr_set_ep0state(dev, GR_EP0_SETUP);
+		if (req->req.actual > 0)
+			dev_dbg(dev->dev,
+				"Unexpected setup packet at state %s\n",
+				gr_ep0state_string(GR_EP0_ISTATUS));
+		else
+			goto out; /* Got expected ZLP */
+	} else if (dev->ep0state != GR_EP0_SETUP) {
+		dev_info(dev->dev,
+			 "Unexpected ep0out request at state %s - stalling\n",
+			 gr_ep0state_string(dev->ep0state));
+		gr_control_stall(dev);
+		gr_set_ep0state(dev, GR_EP0_SETUP);
+		goto out;
+	} else if (!req->req.actual) {
+		dev_dbg(dev->dev, "Unexpected ZLP at state %s\n",
+			gr_ep0state_string(dev->ep0state));
+		goto out;
+	}
+
+	/* Handle SETUP packet */
+	for (i = 0; i < req->req.actual; i++)
+		u.raw[i] = ((u8 *)req->req.buf)[i];
+
+	type = u.ctrl.bRequestType;
+	request = u.ctrl.bRequest;
+	value = le16_to_cpu(u.ctrl.wValue);
+	index = le16_to_cpu(u.ctrl.wIndex);
+	length = le16_to_cpu(u.ctrl.wLength);
+
+	gr_dbgprint_devreq(dev, type, request, value, index, length);
+
+	/* Check for data stage */
+	if (length) {
+		if (type & USB_DIR_IN)
+			gr_set_ep0state(dev, GR_EP0_IDATA);
+		else
+			gr_set_ep0state(dev, GR_EP0_ODATA);
+	}
+
+	status = 1; /* Positive status flags delegation */
+	if ((type & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+		switch (type & USB_RECIP_MASK) {
+		case USB_RECIP_DEVICE:
+			status = gr_device_request(dev, type, request,
+						   value, index);
+			break;
+		case USB_RECIP_ENDPOINT:
+			status =  gr_endpoint_request(dev, type, request,
+						      value, index);
+			break;
+		case USB_RECIP_INTERFACE:
+			status = gr_interface_request(dev, type, request,
+						      value, index);
+			break;
+		}
+	}
+
+	if (status > 0) {
+		spin_unlock(&dev->lock);
+
+		dev_vdbg(dev->dev, "DELEGATE\n");
+		status = dev->driver->setup(&dev->gadget, &u.ctrl);
+
+		spin_lock(&dev->lock);
+	}
+
+	/* Generate STALL on both ep0out and ep0in if requested */
+	if (unlikely(status < 0)) {
+		dev_vdbg(dev->dev, "STALL\n");
+		gr_control_stall(dev);
+	}
+
+	if ((type & USB_TYPE_MASK) == USB_TYPE_STANDARD &&
+	    request == USB_REQ_SET_CONFIGURATION) {
+		if (!value) {
+			dev_dbg(dev->dev, "STATUS: deconfigured\n");
+			usb_gadget_set_state(&dev->gadget, USB_STATE_ADDRESS);
+		} else if (status >= 0) {
+			/* Not configured unless gadget OK:s it */
+			dev_dbg(dev->dev, "STATUS: configured: %d\n", value);
+			usb_gadget_set_state(&dev->gadget,
+					     USB_STATE_CONFIGURED);
+		}
+	}
+
+	/* Get ready for next stage */
+	if (dev->ep0state == GR_EP0_ODATA)
+		gr_set_ep0state(dev, GR_EP0_OSTATUS);
+	else if (dev->ep0state == GR_EP0_IDATA)
+		gr_set_ep0state(dev, GR_EP0_ISTATUS);
+	else
+		gr_set_ep0state(dev, GR_EP0_SETUP);
+
+out:
+	gr_ep0out_requeue(dev);
+}
+
+/* ---------------------------------------------------------------------- */
+/* VBUS and USB reset handling */
+
+/* Must be called with dev->lock held and irqs disabled  */
+static void gr_vbus_connected(struct gr_udc *dev, u32 status)
+{
+	u32 control;
+
+	dev->gadget.speed = GR_SPEED(status);
+	usb_gadget_set_state(&dev->gadget, USB_STATE_POWERED);
+
+	/* Turn on full interrupts and pullup */
+	control = (GR_CONTROL_SI | GR_CONTROL_UI | GR_CONTROL_VI |
+		   GR_CONTROL_SP | GR_CONTROL_EP);
+	gr_write32(&dev->regs->control, control);
+}
+
+/* Must be called with dev->lock held */
+static void gr_enable_vbus_detect(struct gr_udc *dev)
+{
+	u32 status;
+
+	dev->irq_enabled = 1;
+	wmb(); /* Make sure we do not ignore an interrupt */
+	gr_write32(&dev->regs->control, GR_CONTROL_VI);
+
+	/* Take care of the case we are already plugged in at this point */
+	status = gr_read32(&dev->regs->status);
+	if (status & GR_STATUS_VB)
+		gr_vbus_connected(dev, status);
+}
+
+/* Must be called with dev->lock held and irqs disabled */
+static void gr_vbus_disconnected(struct gr_udc *dev)
+{
+	gr_stop_activity(dev);
+
+	/* Report disconnect */
+	if (dev->driver && dev->driver->disconnect) {
+		spin_unlock(&dev->lock);
+
+		dev->driver->disconnect(&dev->gadget);
+
+		spin_lock(&dev->lock);
+	}
+
+	gr_enable_vbus_detect(dev);
+}
+
+/* Must be called with dev->lock held and irqs disabled */
+static void gr_udc_usbreset(struct gr_udc *dev, u32 status)
+{
+	gr_set_address(dev, 0);
+	gr_set_ep0state(dev, GR_EP0_SETUP);
+	usb_gadget_set_state(&dev->gadget, USB_STATE_DEFAULT);
+	dev->gadget.speed = GR_SPEED(status);
+
+	gr_ep_nuke(&dev->epo[0]);
+	gr_ep_nuke(&dev->epi[0]);
+	dev->epo[0].stopped = 0;
+	dev->epi[0].stopped = 0;
+	gr_ep0out_requeue(dev);
+}
+
+/* ---------------------------------------------------------------------- */
+/* Irq handling */
+
+/*
+ * Handles interrupts from in endpoints. Returns whether something was handled.
+ *
+ * Must be called with dev->lock held, irqs disabled and with !ep->stopped.
+ */
+static int gr_handle_in_ep(struct gr_ep *ep)
+{
+	struct gr_request *req;
+
+	req = list_first_entry(&ep->queue, struct gr_request, queue);
+	if (!req->last_desc)
+		return 0;
+
+	if (ACCESS_ONCE(req->last_desc->ctrl) & GR_DESC_IN_CTRL_EN)
+		return 0; /* Not put in hardware buffers yet */
+
+	if (gr_read32(&ep->regs->epstat) & (GR_EPSTAT_B1 | GR_EPSTAT_B0))
+		return 0; /* Not transmitted yet, still in hardware buffers */
+
+	/* Write complete */
+	gr_dma_advance(ep, 0);
+
+	return 1;
+}
+
+/*
+ * Handles interrupts from out endpoints. Returns whether something was handled.
+ *
+ * Must be called with dev->lock held, irqs disabled and with !ep->stopped.
+ */
+static int gr_handle_out_ep(struct gr_ep *ep)
+{
+	u32 ep_dmactrl;
+	u32 ctrl;
+	u16 len;
+	struct gr_request *req;
+	struct gr_udc *dev = ep->dev;
+
+	req = list_first_entry(&ep->queue, struct gr_request, queue);
+	if (!req->curr_desc)
+		return 0;
+
+	ctrl = ACCESS_ONCE(req->curr_desc->ctrl);
+	if (ctrl & GR_DESC_OUT_CTRL_EN)
+		return 0; /* Not received yet */
+
+	/* Read complete */
+	len = ctrl & GR_DESC_OUT_CTRL_LEN_MASK;
+	req->req.actual += len;
+	if (ctrl & GR_DESC_OUT_CTRL_SE)
+		req->setup = 1;
+
+	if (len < ep->ep.maxpacket || req->req.actual == req->req.length) {
+		/* Short packet or the expected size - we are done */
+
+		if ((ep == &dev->epo[0]) && (dev->ep0state == GR_EP0_OSTATUS)) {
+			/*
+			 * Send a status stage ZLP to ack the DATA stage in the
+			 * OUT direction. This needs to be done before
+			 * gr_dma_advance as that can lead to a call to
+			 * ep0_setup that can change dev->ep0state.
+			 */
+			gr_ep0_respond_empty(dev);
+			gr_set_ep0state(dev, GR_EP0_SETUP);
+		}
+
+		gr_dma_advance(ep, 0);
+	} else {
+		/* Not done yet. Enable the next descriptor to receive more. */
+		req->curr_desc = req->curr_desc->next_desc;
+		req->curr_desc->ctrl |= GR_DESC_OUT_CTRL_EN;
+
+		ep_dmactrl = gr_read32(&ep->regs->dmactrl);
+		gr_write32(&ep->regs->dmactrl, ep_dmactrl | GR_DMACTRL_DA);
+	}
+
+	return 1;
+}
+
+/*
+ * Handle state changes. Returns whether something was handled.
+ *
+ * Must be called with dev->lock held and irqs disabled.
+ */
+static int gr_handle_state_changes(struct gr_udc *dev)
+{
+	u32 status = gr_read32(&dev->regs->status);
+	int handled = 0;
+	int powstate = !(dev->gadget.state == USB_STATE_NOTATTACHED ||
+			 dev->gadget.state == USB_STATE_ATTACHED);
+
+	/* VBUS valid detected */
+	if (!powstate && (status & GR_STATUS_VB)) {
+		dev_dbg(dev->dev, "STATUS: vbus valid detected\n");
+		gr_vbus_connected(dev, status);
+		handled = 1;
+	}
+
+	/* Disconnect */
+	if (powstate && !(status & GR_STATUS_VB)) {
+		dev_dbg(dev->dev, "STATUS: vbus invalid detected\n");
+		gr_vbus_disconnected(dev);
+		handled = 1;
+	}
+
+	/* USB reset detected */
+	if (status & GR_STATUS_UR) {
+		dev_dbg(dev->dev, "STATUS: USB reset - speed is %s\n",
+			GR_SPEED_STR(status));
+		gr_write32(&dev->regs->status, GR_STATUS_UR);
+		gr_udc_usbreset(dev, status);
+		handled = 1;
+	}
+
+	/* Speed change */
+	if (dev->gadget.speed != GR_SPEED(status)) {
+		dev_dbg(dev->dev, "STATUS: USB Speed change to %s\n",
+			GR_SPEED_STR(status));
+		dev->gadget.speed = GR_SPEED(status);
+		handled = 1;
+	}
+
+	/* Going into suspend */
+	if ((dev->ep0state != GR_EP0_SUSPEND) && !(status & GR_STATUS_SU)) {
+		dev_dbg(dev->dev, "STATUS: USB suspend\n");
+		gr_set_ep0state(dev, GR_EP0_SUSPEND);
+		dev->suspended_from = dev->gadget.state;
+		usb_gadget_set_state(&dev->gadget, USB_STATE_SUSPENDED);
+
+		if ((dev->gadget.speed != USB_SPEED_UNKNOWN) &&
+		    dev->driver && dev->driver->suspend) {
+			spin_unlock(&dev->lock);
+
+			dev->driver->suspend(&dev->gadget);
+
+			spin_lock(&dev->lock);
+		}
+		handled = 1;
+	}
+
+	/* Coming out of suspend */
+	if ((dev->ep0state == GR_EP0_SUSPEND) && (status & GR_STATUS_SU)) {
+		dev_dbg(dev->dev, "STATUS: USB resume\n");
+		if (dev->suspended_from == USB_STATE_POWERED)
+			gr_set_ep0state(dev, GR_EP0_DISCONNECT);
+		else
+			gr_set_ep0state(dev, GR_EP0_SETUP);
+		usb_gadget_set_state(&dev->gadget, dev->suspended_from);
+
+		if ((dev->gadget.speed != USB_SPEED_UNKNOWN) &&
+		    dev->driver && dev->driver->resume) {
+			spin_unlock(&dev->lock);
+
+			dev->driver->resume(&dev->gadget);
+
+			spin_lock(&dev->lock);
+		}
+		handled = 1;
+	}
+
+	return handled;
+}
+
+/* Non-interrupt context irq handler */
+static irqreturn_t gr_irq_handler(int irq, void *_dev)
+{
+	struct gr_udc *dev = _dev;
+	struct gr_ep *ep;
+	int handled = 0;
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	if (!dev->irq_enabled)
+		goto out;
+
+	/*
+	 * Check IN ep interrupts. We check these before the OUT eps because
+	 * some gadgets reuse the request that might already be currently
+	 * outstanding and needs to be completed (mainly setup requests).
+	 */
+	for (i = 0; i < dev->nepi; i++) {
+		ep = &dev->epi[i];
+		if (!ep->stopped && !ep->callback && !list_empty(&ep->queue))
+			handled = gr_handle_in_ep(ep) || handled;
+	}
+
+	/* Check OUT ep interrupts */
+	for (i = 0; i < dev->nepo; i++) {
+		ep = &dev->epo[i];
+		if (!ep->stopped && !ep->callback && !list_empty(&ep->queue))
+			handled = gr_handle_out_ep(ep) || handled;
+	}
+
+	/* Check status interrupts */
+	handled = gr_handle_state_changes(dev) || handled;
+
+	/*
+	 * Check AMBA DMA errors. Only check if we didn't find anything else to
+	 * handle because this shouldn't happen if we did everything right.
+	 */
+	if (!handled) {
+		list_for_each_entry(ep, &dev->ep_list, ep_list) {
+			if (gr_read32(&ep->regs->dmactrl) & GR_DMACTRL_AE) {
+				dev_err(dev->dev,
+					"AMBA Error occurred for %s\n",
+					ep->ep.name);
+				handled = 1;
+			}
+		}
+	}
+
+out:
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+/* Interrupt context irq handler */
+static irqreturn_t gr_irq(int irq, void *_dev)
+{
+	struct gr_udc *dev = _dev;
+
+	if (!dev->irq_enabled)
+		return IRQ_NONE;
+
+	return IRQ_WAKE_THREAD;
+}
+
+/* ---------------------------------------------------------------------- */
+/* USB ep ops */
+
+/* Enable endpoint. Not for ep0in and ep0out that are handled separately. */
+static int gr_ep_enable(struct usb_ep *_ep,
+			const struct usb_endpoint_descriptor *desc)
+{
+	struct gr_udc *dev;
+	struct gr_ep *ep;
+	u8 mode;
+	u8 nt;
+	u16 max;
+	u16 buffer_size = 0;
+	u32 epctrl;
+
+	ep = container_of(_ep, struct gr_ep, ep);
+	if (!_ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT)
+		return -EINVAL;
+
+	dev = ep->dev;
+
+	/* 'ep0' IN and OUT are reserved */
+	if (ep == &dev->epo[0] || ep == &dev->epi[0])
+		return -EINVAL;
+
+	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	/* Make sure we are clear for enabling */
+	epctrl = gr_read32(&ep->regs->epctrl);
+	if (epctrl & GR_EPCTRL_EV)
+		return -EBUSY;
+
+	/* Check that directions match */
+	if (!ep->is_in != !usb_endpoint_dir_in(desc))
+		return -EINVAL;
+
+	/* Check ep num */
+	if ((!ep->is_in && ep->num >= dev->nepo) ||
+	    (ep->is_in && ep->num >= dev->nepi))
+		return -EINVAL;
+
+	if (usb_endpoint_xfer_control(desc)) {
+		mode = 0;
+	} else if (usb_endpoint_xfer_isoc(desc)) {
+		mode = 1;
+	} else if (usb_endpoint_xfer_bulk(desc)) {
+		mode = 2;
+	} else if (usb_endpoint_xfer_int(desc)) {
+		mode = 3;
+	} else {
+		dev_err(dev->dev, "Unknown transfer type for %s\n",
+			ep->ep.name);
+		return -EINVAL;
+	}
+
+	/*
+	 * Bits 10-0 set the max payload. 12-11 set the number of
+	 * additional transactions.
+	 */
+	max = 0x7ff & usb_endpoint_maxp(desc);
+	nt = 0x3 & (usb_endpoint_maxp(desc) >> 11);
+	buffer_size = GR_BUFFER_SIZE(epctrl);
+	if (nt && (mode == 0 || mode == 2)) {
+		dev_err(dev->dev,
+			"%s mode: multiple trans./microframe not valid\n",
+			(mode == 2 ? "Bulk" : "Control"));
+		return -EINVAL;
+	} else if (nt == 0x11) {
+		dev_err(dev->dev, "Invalid value for trans./microframe\n");
+		return -EINVAL;
+	} else if ((nt + 1) * max > buffer_size) {
+		dev_err(dev->dev, "Hw buffer size %d < max payload %d * %d\n",
+			buffer_size, (nt + 1), max);
+		return -EINVAL;
+	} else if (max == 0) {
+		dev_err(dev->dev, "Max payload cannot be set to 0\n");
+		return -EINVAL;
+	}
+
+	spin_lock(&ep->dev->lock);
+
+	if (!ep->stopped) {
+		spin_unlock(&ep->dev->lock);
+		return -EBUSY;
+	}
+
+	ep->stopped = 0;
+	ep->wedged = 0;
+	ep->ep.desc = desc;
+	ep->ep.maxpacket = max;
+	ep->dma_start = 0;
+
+
+	if (nt) {
+		/*
+		 * Maximum possible size of all payloads in one microframe
+		 * regardless of direction when using high-bandwidth mode.
+		 */
+		ep->bytes_per_buffer = (nt + 1) * max;
+	} else if (ep->is_in) {
+		/*
+		 * The biggest multiple of maximum packet size that fits into
+		 * the buffer. The hardware will split up into many packets in
+		 * the IN direction.
+		 */
+		ep->bytes_per_buffer = (buffer_size / max) * max;
+	} else {
+		/*
+		 * Only single packets will be placed the buffers in the OUT
+		 * direction.
+		 */
+		ep->bytes_per_buffer = max;
+	}
+
+	epctrl = (max << GR_EPCTRL_MAXPL_POS)
+		| (nt << GR_EPCTRL_NT_POS)
+		| (mode << GR_EPCTRL_TT_POS)
+		| GR_EPCTRL_EV;
+	if (ep->is_in)
+		epctrl |= GR_EPCTRL_PI;
+	gr_write32(&ep->regs->epctrl, epctrl);
+
+	gr_write32(&ep->regs->dmactrl, GR_DMACTRL_IE | GR_DMACTRL_AI);
+
+	spin_unlock(&ep->dev->lock);
+
+	dev_dbg(ep->dev->dev, "EP: %s enabled - %s with %d bytes/buffer\n",
+		ep->ep.name, gr_modestring[mode], ep->bytes_per_buffer);
+	return 0;
+}
+
+/* Disable endpoint. Not for ep0in and ep0out that are handled separately. */
+static int gr_ep_disable(struct usb_ep *_ep)
+{
+	struct gr_ep *ep;
+	struct gr_udc *dev;
+	unsigned long flags;
+
+	ep = container_of(_ep, struct gr_ep, ep);
+	if (!_ep || !ep->ep.desc)
+		return -ENODEV;
+
+	dev = ep->dev;
+
+	/* 'ep0' IN and OUT are reserved */
+	if (ep == &dev->epo[0] || ep == &dev->epi[0])
+		return -EINVAL;
+
+	if (dev->ep0state == GR_EP0_SUSPEND)
+		return -EBUSY;
+
+	dev_dbg(ep->dev->dev, "EP: disable %s\n", ep->ep.name);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	gr_ep_nuke(ep);
+	gr_ep_reset(ep);
+	ep->ep.desc = NULL;
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+/*
+ * Frees a request, but not any DMA buffers associated with it
+ * (gr_finish_request should already have taken care of that).
+ */
+static void gr_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct gr_request *req;
+
+	if (!_ep || !_req)
+		return;
+	req = container_of(_req, struct gr_request, req);
+
+	/* Leads to memory leak */
+	WARN(!list_empty(&req->queue),
+	     "request not dequeued properly before freeing\n");
+
+	kfree(req);
+}
+
+/* Queue a request from the gadget */
+static int gr_queue_ext(struct usb_ep *_ep, struct usb_request *_req,
+			gfp_t gfp_flags)
+{
+	struct gr_ep *ep;
+	struct gr_request *req;
+	struct gr_udc *dev;
+	int ret;
+
+	if (unlikely(!_ep || !_req))
+		return -EINVAL;
+
+	ep = container_of(_ep, struct gr_ep, ep);
+	req = container_of(_req, struct gr_request, req);
+	dev = ep->dev;
+
+	spin_lock(&ep->dev->lock);
+
+	/*
+	 * The ep0 pointer in the gadget struct is used both for ep0in and
+	 * ep0out. In a data stage in the out direction ep0out needs to be used
+	 * instead of the default ep0in. Completion functions might use
+	 * driver_data, so that needs to be copied as well.
+	 */
+	if ((ep == &dev->epi[0]) && (dev->ep0state == GR_EP0_ODATA)) {
+		ep = &dev->epo[0];
+		ep->ep.driver_data = dev->epi[0].ep.driver_data;
+	}
+
+	if (ep->is_in)
+		gr_dbgprint_request("EXTERN", ep, req);
+
+	ret = gr_queue(ep, req, gfp_flags);
+
+	spin_unlock(&ep->dev->lock);
+
+	return ret;
+}
+
+/* Dequeue JUST ONE request */
+static int gr_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct gr_request *req;
+	struct gr_ep *ep;
+	struct gr_udc *dev;
+	int ret = 0;
+	unsigned long flags;
+
+	ep = container_of(_ep, struct gr_ep, ep);
+	if (!_ep || !_req || (!ep->ep.desc && ep->num != 0))
+		return -EINVAL;
+	dev = ep->dev;
+	if (!dev->driver)
+		return -ESHUTDOWN;
+
+	/* We can't touch (DMA) registers when suspended */
+	if (dev->ep0state == GR_EP0_SUSPEND)
+		return -EBUSY;
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* Make sure it's actually queued on this endpoint */
+	list_for_each_entry(req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+	if (&req->req != _req) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (list_first_entry(&ep->queue, struct gr_request, queue) == req) {
+		/* This request is currently being processed */
+		gr_abort_dma(ep);
+		if (ep->stopped)
+			gr_finish_request(ep, req, -ECONNRESET);
+		else
+			gr_dma_advance(ep, -ECONNRESET);
+	} else if (!list_empty(&req->queue)) {
+		/* Not being processed - gr_finish_request dequeues it */
+		gr_finish_request(ep, req, -ECONNRESET);
+	} else {
+		ret = -EOPNOTSUPP;
+	}
+
+out:
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return ret;
+}
+
+/* Helper for gr_set_halt and gr_set_wedge */
+static int gr_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge)
+{
+	int ret;
+	struct gr_ep *ep;
+
+	if (!_ep)
+		return -ENODEV;
+	ep = container_of(_ep, struct gr_ep, ep);
+
+	spin_lock(&ep->dev->lock);
+
+	/* Halting an IN endpoint should fail if queue is not empty */
+	if (halt && ep->is_in && !list_empty(&ep->queue)) {
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	ret = gr_ep_halt_wedge(ep, halt, wedge, 0);
+
+out:
+	spin_unlock(&ep->dev->lock);
+
+	return ret;
+}
+
+/* Halt endpoint */
+static int gr_set_halt(struct usb_ep *_ep, int halt)
+{
+	return gr_set_halt_wedge(_ep, halt, 0);
+}
+
+/* Halt and wedge endpoint */
+static int gr_set_wedge(struct usb_ep *_ep)
+{
+	return gr_set_halt_wedge(_ep, 1, 1);
+}
+
+/*
+ * Return the total number of bytes currently stored in the internal buffers of
+ * the endpoint.
+ */
+static int gr_fifo_status(struct usb_ep *_ep)
+{
+	struct gr_ep *ep;
+	u32 epstat;
+	u32 bytes = 0;
+
+	if (!_ep)
+		return -ENODEV;
+	ep = container_of(_ep, struct gr_ep, ep);
+
+	epstat = gr_read32(&ep->regs->epstat);
+
+	if (epstat & GR_EPSTAT_B0)
+		bytes += (epstat & GR_EPSTAT_B0CNT_MASK) >> GR_EPSTAT_B0CNT_POS;
+	if (epstat & GR_EPSTAT_B1)
+		bytes += (epstat & GR_EPSTAT_B1CNT_MASK) >> GR_EPSTAT_B1CNT_POS;
+
+	return bytes;
+}
+
+
+/* Empty data from internal buffers of an endpoint. */
+static void gr_fifo_flush(struct usb_ep *_ep)
+{
+	struct gr_ep *ep;
+	u32 epctrl;
+
+	if (!_ep)
+		return;
+	ep = container_of(_ep, struct gr_ep, ep);
+	dev_vdbg(ep->dev->dev, "EP: flush fifo %s\n", ep->ep.name);
+
+	spin_lock(&ep->dev->lock);
+
+	epctrl = gr_read32(&ep->regs->epctrl);
+	epctrl |= GR_EPCTRL_CB;
+	gr_write32(&ep->regs->epctrl, epctrl);
+
+	spin_unlock(&ep->dev->lock);
+}
+
+static struct usb_ep_ops gr_ep_ops = {
+	.enable		= gr_ep_enable,
+	.disable	= gr_ep_disable,
+
+	.alloc_request	= gr_alloc_request,
+	.free_request	= gr_free_request,
+
+	.queue		= gr_queue_ext,
+	.dequeue	= gr_dequeue,
+
+	.set_halt	= gr_set_halt,
+	.set_wedge	= gr_set_wedge,
+	.fifo_status	= gr_fifo_status,
+	.fifo_flush	= gr_fifo_flush,
+};
+
+/* ---------------------------------------------------------------------- */
+/* USB Gadget ops */
+
+static int gr_get_frame(struct usb_gadget *_gadget)
+{
+	struct gr_udc *dev;
+
+	if (!_gadget)
+		return -ENODEV;
+	dev = container_of(_gadget, struct gr_udc, gadget);
+	return gr_read32(&dev->regs->status) & GR_STATUS_FN_MASK;
+}
+
+static int gr_wakeup(struct usb_gadget *_gadget)
+{
+	struct gr_udc *dev;
+
+	if (!_gadget)
+		return -ENODEV;
+	dev = container_of(_gadget, struct gr_udc, gadget);
+
+	/* Remote wakeup feature not enabled by host*/
+	if (!dev->remote_wakeup)
+		return -EINVAL;
+
+	spin_lock(&dev->lock);
+
+	gr_write32(&dev->regs->control,
+		   gr_read32(&dev->regs->control) | GR_CONTROL_RW);
+
+	spin_unlock(&dev->lock);
+
+	return 0;
+}
+
+static int gr_pullup(struct usb_gadget *_gadget, int is_on)
+{
+	struct gr_udc *dev;
+	u32 control;
+
+	if (!_gadget)
+		return -ENODEV;
+	dev = container_of(_gadget, struct gr_udc, gadget);
+
+	spin_lock(&dev->lock);
+
+	control = gr_read32(&dev->regs->control);
+	if (is_on)
+		control |= GR_CONTROL_EP;
+	else
+		control &= ~GR_CONTROL_EP;
+	gr_write32(&dev->regs->control, control);
+
+	spin_unlock(&dev->lock);
+
+	return 0;
+}
+
+static int gr_udc_start(struct usb_gadget *gadget,
+			struct usb_gadget_driver *driver)
+{
+	struct gr_udc *dev = to_gr_udc(gadget);
+
+	spin_lock(&dev->lock);
+
+	/* Hook up the driver */
+	driver->driver.bus = NULL;
+	dev->driver = driver;
+
+	/* Get ready for host detection */
+	gr_enable_vbus_detect(dev);
+
+	spin_unlock(&dev->lock);
+
+	dev_info(dev->dev, "Started with gadget driver '%s'\n",
+		 driver->driver.name);
+
+	return 0;
+}
+
+static int gr_udc_stop(struct usb_gadget *gadget,
+		       struct usb_gadget_driver *driver)
+{
+	struct gr_udc *dev = to_gr_udc(gadget);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	dev->driver = NULL;
+	gr_stop_activity(dev);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	dev_info(dev->dev, "Stopped\n");
+
+	return 0;
+}
+
+static const struct usb_gadget_ops gr_ops = {
+	.get_frame	= gr_get_frame,
+	.wakeup         = gr_wakeup,
+	.pullup         = gr_pullup,
+	.udc_start	= gr_udc_start,
+	.udc_stop	= gr_udc_stop,
+	/* Other operations not supported */
+};
+
+/* ---------------------------------------------------------------------- */
+/* Module probe, removal and of-matching */
+
+static const char * const onames[] = {
+	"ep0out", "ep1out", "ep2out", "ep3out", "ep4out", "ep5out",
+	"ep6out", "ep7out", "ep8out", "ep9out", "ep10out", "ep11out",
+	"ep12out", "ep13out", "ep14out", "ep15out"
+};
+
+static const char * const inames[] = {
+	"ep0in", "ep1in", "ep2in", "ep3in", "ep4in", "ep5in",
+	"ep6in", "ep7in", "ep8in", "ep9in", "ep10in", "ep11in",
+	"ep12in", "ep13in", "ep14in", "ep15in"
+};
+
+/* Must be called with dev->lock held */
+static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)
+{
+	struct gr_ep *ep;
+	struct gr_request *req;
+	struct usb_request *_req;
+	void *buf;
+
+	if (is_in) {
+		ep = &dev->epi[num];
+		ep->ep.name = inames[num];
+		ep->regs = &dev->regs->epi[num];
+	} else {
+		ep = &dev->epo[num];
+		ep->ep.name = onames[num];
+		ep->regs = &dev->regs->epo[num];
+	}
+
+	gr_ep_reset(ep);
+	ep->num = num;
+	ep->is_in = is_in;
+	ep->dev = dev;
+	ep->ep.ops = &gr_ep_ops;
+	INIT_LIST_HEAD(&ep->queue);
+
+	if (num == 0) {
+		_req = gr_alloc_request(&ep->ep, GFP_KERNEL);
+		buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_KERNEL);
+		if (!_req || !buf) {
+			/* possible _req freed by gr_probe via gr_remove */
+			return -ENOMEM;
+		}
+
+		req = container_of(_req, struct gr_request, req);
+		req->req.buf = buf;
+		req->req.length = MAX_CTRL_PL_SIZE;
+
+		if (is_in)
+			dev->ep0reqi = req; /* Complete gets set as used */
+		else
+			dev->ep0reqo = req; /* Completion treated separately */
+
+		usb_ep_set_maxpacket_limit(&ep->ep, MAX_CTRL_PL_SIZE);
+		ep->bytes_per_buffer = MAX_CTRL_PL_SIZE;
+	} else {
+		usb_ep_set_maxpacket_limit(&ep->ep, (u16)maxplimit);
+		list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+	}
+	list_add_tail(&ep->ep_list, &dev->ep_list);
+
+	return 0;
+}
+
+/* Must be called with dev->lock held */
+static int gr_udc_init(struct gr_udc *dev)
+{
+	struct device_node *np = dev->dev->of_node;
+	u32 epctrl_val;
+	u32 dmactrl_val;
+	int i;
+	int ret = 0;
+	u32 *bufsizes;
+	u32 bufsize;
+	int len;
+
+	gr_set_address(dev, 0);
+
+	INIT_LIST_HEAD(&dev->gadget.ep_list);
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+	dev->gadget.ep0 = &dev->epi[0].ep;
+
+	INIT_LIST_HEAD(&dev->ep_list);
+	gr_set_ep0state(dev, GR_EP0_DISCONNECT);
+
+	bufsizes = (u32 *)of_get_property(np, "epobufsizes", &len);
+	len /= sizeof(u32);
+	for (i = 0; i < dev->nepo; i++) {
+		bufsize = (bufsizes && i < len) ? bufsizes[i] : 1024;
+		ret = gr_ep_init(dev, i, 0, bufsize);
+		if (ret)
+			return ret;
+	}
+
+	bufsizes = (u32 *)of_get_property(np, "epibufsizes", &len);
+	len /= sizeof(u32);
+	for (i = 0; i < dev->nepi; i++) {
+		bufsize = (bufsizes && i < len) ? bufsizes[i] : 1024;
+		ret = gr_ep_init(dev, i, 1, bufsize);
+		if (ret)
+			return ret;
+	}
+
+	/* Must be disabled by default */
+	dev->remote_wakeup = 0;
+
+	/* Enable ep0out and ep0in */
+	epctrl_val = (MAX_CTRL_PL_SIZE << GR_EPCTRL_MAXPL_POS) | GR_EPCTRL_EV;
+	dmactrl_val = GR_DMACTRL_IE | GR_DMACTRL_AI;
+	gr_write32(&dev->epo[0].regs->epctrl, epctrl_val);
+	gr_write32(&dev->epi[0].regs->epctrl, epctrl_val | GR_EPCTRL_PI);
+	gr_write32(&dev->epo[0].regs->dmactrl, dmactrl_val);
+	gr_write32(&dev->epi[0].regs->dmactrl, dmactrl_val);
+
+	return 0;
+}
+
+static int gr_remove(struct platform_device *ofdev)
+{
+	struct gr_udc *dev = dev_get_drvdata(&ofdev->dev);
+
+	if (dev->added)
+		usb_del_gadget_udc(&dev->gadget); /* Shuts everything down */
+	if (dev->driver)
+		return -EBUSY;
+
+	gr_dfs_delete(dev);
+	if (dev->desc_pool)
+		dma_pool_destroy(dev->desc_pool);
+	dev_set_drvdata(&ofdev->dev, NULL);
+
+	gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req);
+	gr_free_request(&dev->epo[0].ep, &dev->ep0reqo->req);
+
+	return 0;
+}
+static int gr_request_irq(struct gr_udc *dev, int irq)
+{
+	return devm_request_threaded_irq(dev->dev, irq, gr_irq, gr_irq_handler,
+					 IRQF_SHARED, driver_name, dev);
+}
+
+static int gr_probe(struct platform_device *ofdev)
+{
+	struct gr_udc *dev;
+	struct resource *res;
+	struct gr_regs __iomem *regs;
+	int retval;
+	u32 status;
+
+	dev = devm_kzalloc(&ofdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+	dev->dev = &ofdev->dev;
+
+	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(dev->dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	dev->irq = irq_of_parse_and_map(dev->dev->of_node, 0);
+	if (!dev->irq) {
+		dev_err(dev->dev, "No irq found\n");
+		return -ENODEV;
+	}
+
+	/* Some core configurations has separate irqs for IN and OUT events */
+	dev->irqi = irq_of_parse_and_map(dev->dev->of_node, 1);
+	if (dev->irqi) {
+		dev->irqo = irq_of_parse_and_map(dev->dev->of_node, 2);
+		if (!dev->irqo) {
+			dev_err(dev->dev, "Found irqi but not irqo\n");
+			return -ENODEV;
+		}
+	}
+
+	dev->gadget.name = driver_name;
+	dev->gadget.max_speed = USB_SPEED_HIGH;
+	dev->gadget.ops = &gr_ops;
+	dev->gadget.quirk_ep_out_aligned_size = true;
+
+	spin_lock_init(&dev->lock);
+	dev->regs = regs;
+
+	dev_set_drvdata(&ofdev->dev, dev);
+
+	/* Determine number of endpoints and data interface mode */
+	status = gr_read32(&dev->regs->status);
+	dev->nepi = ((status & GR_STATUS_NEPI_MASK) >> GR_STATUS_NEPI_POS) + 1;
+	dev->nepo = ((status & GR_STATUS_NEPO_MASK) >> GR_STATUS_NEPO_POS) + 1;
+
+	if (!(status & GR_STATUS_DM)) {
+		dev_err(dev->dev, "Slave mode cores are not supported\n");
+		return -ENODEV;
+	}
+
+	/* --- Effects of the following calls might need explicit cleanup --- */
+
+	/* Create DMA pool for descriptors */
+	dev->desc_pool = dma_pool_create("desc_pool", dev->dev,
+					 sizeof(struct gr_dma_desc), 4, 0);
+	if (!dev->desc_pool) {
+		dev_err(dev->dev, "Could not allocate DMA pool");
+		return -ENOMEM;
+	}
+
+	spin_lock(&dev->lock);
+
+	/* Inside lock so that no gadget can use this udc until probe is done */
+	retval = usb_add_gadget_udc(dev->dev, &dev->gadget);
+	if (retval) {
+		dev_err(dev->dev, "Could not add gadget udc");
+		goto out;
+	}
+	dev->added = 1;
+
+	retval = gr_udc_init(dev);
+	if (retval)
+		goto out;
+
+	gr_dfs_create(dev);
+
+	/* Clear all interrupt enables that might be left on since last boot */
+	gr_disable_interrupts_and_pullup(dev);
+
+	retval = gr_request_irq(dev, dev->irq);
+	if (retval) {
+		dev_err(dev->dev, "Failed to request irq %d\n", dev->irq);
+		goto out;
+	}
+
+	if (dev->irqi) {
+		retval = gr_request_irq(dev, dev->irqi);
+		if (retval) {
+			dev_err(dev->dev, "Failed to request irqi %d\n",
+				dev->irqi);
+			goto out;
+		}
+		retval = gr_request_irq(dev, dev->irqo);
+		if (retval) {
+			dev_err(dev->dev, "Failed to request irqo %d\n",
+				dev->irqo);
+			goto out;
+		}
+	}
+
+	if (dev->irqi)
+		dev_info(dev->dev, "regs: %p, irqs %d, %d, %d\n", dev->regs,
+			 dev->irq, dev->irqi, dev->irqo);
+	else
+		dev_info(dev->dev, "regs: %p, irq %d\n", dev->regs, dev->irq);
+
+out:
+	spin_unlock(&dev->lock);
+
+	if (retval)
+		gr_remove(ofdev);
+
+	return retval;
+}
+
+static struct of_device_id gr_match[] = {
+	{.name = "GAISLER_USBDC"},
+	{.name = "01_021"},
+	{},
+};
+MODULE_DEVICE_TABLE(of, gr_match);
+
+static struct platform_driver gr_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = gr_match,
+	},
+	.probe = gr_probe,
+	.remove = gr_remove,
+};
+module_platform_driver(gr_driver);
+
+MODULE_AUTHOR("Aeroflex Gaisler AB.");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/gr_udc.h b/drivers/usb/gadget/gr_udc.h
new file mode 100644
index 0000000..8388897
--- /dev/null
+++ b/drivers/usb/gadget/gr_udc.h
@@ -0,0 +1,220 @@
+/*
+ * USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC.
+ *
+ * 2013 (c) Aeroflex Gaisler AB
+ *
+ * This driver supports GRUSBDC USB Device Controller cores available in the
+ * GRLIB VHDL IP core library.
+ *
+ * Full documentation of the GRUSBDC core can be found here:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ *
+ * 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.
+ *
+ * Contributors:
+ * - Andreas Larsson <andreas@gaisler.com>
+ * - Marko Isomaki
+ */
+
+/* Control registers on the AMBA bus */
+
+#define GR_MAXEP	16	/* Max # endpoints for *each* direction */
+
+struct gr_epregs {
+	u32 epctrl;
+	union {
+		struct { /* Slave mode*/
+			u32 slvctrl;
+			u32 slvdata;
+		};
+		struct { /* DMA mode*/
+			u32 dmactrl;
+			u32 dmaaddr;
+		};
+	};
+	u32 epstat;
+};
+
+struct gr_regs {
+	struct gr_epregs	epo[GR_MAXEP];	/* 0x000 - 0x0fc */
+	struct gr_epregs	epi[GR_MAXEP];	/* 0x100 - 0x1fc */
+	u32			control;	/* 0x200 */
+	u32			status;		/* 0x204 */
+};
+
+#define GR_EPCTRL_BUFSZ_SCALER	8
+#define GR_EPCTRL_BUFSZ_MASK	0xffe00000
+#define GR_EPCTRL_BUFSZ_POS	21
+#define GR_EPCTRL_PI		BIT(20)
+#define GR_EPCTRL_CB		BIT(19)
+#define GR_EPCTRL_CS		BIT(18)
+#define GR_EPCTRL_MAXPL_MASK	0x0003ff80
+#define GR_EPCTRL_MAXPL_POS	7
+#define GR_EPCTRL_NT_MASK	0x00000060
+#define GR_EPCTRL_NT_POS	5
+#define GR_EPCTRL_TT_MASK	0x00000018
+#define GR_EPCTRL_TT_POS	3
+#define GR_EPCTRL_EH		BIT(2)
+#define GR_EPCTRL_ED		BIT(1)
+#define GR_EPCTRL_EV		BIT(0)
+
+#define GR_DMACTRL_AE		BIT(10)
+#define GR_DMACTRL_AD		BIT(3)
+#define GR_DMACTRL_AI		BIT(2)
+#define GR_DMACTRL_IE		BIT(1)
+#define GR_DMACTRL_DA		BIT(0)
+
+#define GR_EPSTAT_PT		BIT(29)
+#define GR_EPSTAT_PR		BIT(29)
+#define GR_EPSTAT_B1CNT_MASK	0x1fff0000
+#define GR_EPSTAT_B1CNT_POS	16
+#define GR_EPSTAT_B0CNT_MASK	0x0000fff8
+#define GR_EPSTAT_B0CNT_POS	3
+#define GR_EPSTAT_B1		BIT(2)
+#define GR_EPSTAT_B0		BIT(1)
+#define GR_EPSTAT_BS		BIT(0)
+
+#define GR_CONTROL_SI		BIT(31)
+#define GR_CONTROL_UI		BIT(30)
+#define GR_CONTROL_VI		BIT(29)
+#define GR_CONTROL_SP		BIT(28)
+#define GR_CONTROL_FI		BIT(27)
+#define GR_CONTROL_EP		BIT(14)
+#define GR_CONTROL_DH		BIT(13)
+#define GR_CONTROL_RW		BIT(12)
+#define GR_CONTROL_TS_MASK	0x00000e00
+#define GR_CONTROL_TS_POS	9
+#define GR_CONTROL_TM		BIT(8)
+#define GR_CONTROL_UA_MASK	0x000000fe
+#define GR_CONTROL_UA_POS	1
+#define GR_CONTROL_SU		BIT(0)
+
+#define GR_STATUS_NEPI_MASK	0xf0000000
+#define GR_STATUS_NEPI_POS	28
+#define GR_STATUS_NEPO_MASK	0x0f000000
+#define GR_STATUS_NEPO_POS	24
+#define GR_STATUS_DM		BIT(23)
+#define GR_STATUS_SU		BIT(17)
+#define GR_STATUS_UR		BIT(16)
+#define GR_STATUS_VB		BIT(15)
+#define GR_STATUS_SP		BIT(14)
+#define GR_STATUS_AF_MASK	0x00003800
+#define GR_STATUS_AF_POS	11
+#define GR_STATUS_FN_MASK	0x000007ff
+#define GR_STATUS_FN_POS	0
+
+
+#define MAX_CTRL_PL_SIZE 64 /* As per USB standard for full and high speed */
+
+/*-------------------------------------------------------------------------*/
+
+/* Driver data structures and utilities */
+
+struct gr_dma_desc {
+	u32 ctrl;
+	u32 data;
+	u32 next;
+
+	/* These must be last because hw uses the previous three */
+	u32 paddr;
+	struct gr_dma_desc *next_desc;
+};
+
+#define GR_DESC_OUT_CTRL_SE		BIT(17)
+#define GR_DESC_OUT_CTRL_IE		BIT(15)
+#define GR_DESC_OUT_CTRL_NX		BIT(14)
+#define GR_DESC_OUT_CTRL_EN		BIT(13)
+#define GR_DESC_OUT_CTRL_LEN_MASK	0x00001fff
+
+#define GR_DESC_IN_CTRL_MO		BIT(18)
+#define GR_DESC_IN_CTRL_PI		BIT(17)
+#define GR_DESC_IN_CTRL_ML		BIT(16)
+#define GR_DESC_IN_CTRL_IE		BIT(15)
+#define GR_DESC_IN_CTRL_NX		BIT(14)
+#define GR_DESC_IN_CTRL_EN		BIT(13)
+#define GR_DESC_IN_CTRL_LEN_MASK	0x00001fff
+
+#define GR_DESC_DMAADDR_MASK		0xfffffffc
+
+struct gr_ep {
+	struct usb_ep ep;
+	struct gr_udc *dev;
+	u16 bytes_per_buffer;
+	unsigned int dma_start;
+	struct gr_epregs __iomem *regs;
+
+	unsigned num:8;
+	unsigned is_in:1;
+	unsigned stopped:1;
+	unsigned wedged:1;
+	unsigned callback:1;
+
+	/* analogous to a host-side qh */
+	struct list_head queue;
+
+	struct list_head ep_list;
+};
+
+struct gr_request {
+	struct usb_request req;
+	struct list_head queue;
+
+	/* Chain of dma descriptors */
+	struct gr_dma_desc *first_desc; /* First in the chain */
+	struct gr_dma_desc *curr_desc; /* Current descriptor */
+	struct gr_dma_desc *last_desc; /* Last in the chain */
+
+	u8 setup; /* Setup packet */
+};
+
+enum gr_ep0state {
+	GR_EP0_DISCONNECT = 0,	/* No host */
+	GR_EP0_SETUP,		/* Between STATUS ack and SETUP report */
+	GR_EP0_IDATA,		/* IN data stage */
+	GR_EP0_ODATA,		/* OUT data stage */
+	GR_EP0_ISTATUS,		/* Status stage after IN data stage */
+	GR_EP0_OSTATUS,		/* Status stage after OUT data stage */
+	GR_EP0_STALL,		/* Data or status stages */
+	GR_EP0_SUSPEND,		/* USB suspend */
+};
+
+struct gr_udc {
+	struct usb_gadget gadget;
+	struct gr_ep epi[GR_MAXEP];
+	struct gr_ep epo[GR_MAXEP];
+	struct usb_gadget_driver *driver;
+	struct dma_pool *desc_pool;
+	struct device *dev;
+
+	enum gr_ep0state ep0state;
+	struct gr_request *ep0reqo;
+	struct gr_request *ep0reqi;
+
+	struct gr_regs __iomem *regs;
+	int irq;
+	int irqi;
+	int irqo;
+
+	unsigned added:1;
+	unsigned irq_enabled:1;
+	unsigned remote_wakeup:1;
+
+	u8 test_mode;
+
+	enum usb_device_state suspended_from;
+
+	unsigned int nepi;
+	unsigned int nepo;
+
+	struct list_head ep_list;
+
+	spinlock_t lock; /* General lock, a.k.a. "dev->lock" in comments */
+
+	struct dentry *dfs_root;
+	struct dentry *dfs_state;
+};
+
+#define to_gr_udc(gadget)	(container_of((gadget), struct gr_udc, gadget))
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c
index 6a2a65a..049ebab 100644
--- a/drivers/usb/gadget/lpc32xx_udc.c
+++ b/drivers/usb/gadget/lpc32xx_udc.c
@@ -1449,7 +1449,7 @@
 
 		if (i != 0)
 			list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
-		ep->ep.maxpacket = ep->maxpacket;
+		usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
 		INIT_LIST_HEAD(&ep->queue);
 		ep->req_pending = 0;
 	}
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index d5f050d..8cae01d 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -1647,9 +1647,9 @@
 		INIT_LIST_HEAD(&ep->queue);
 		ep->ep.name = m66592_ep_name[i];
 		ep->ep.ops = &m66592_ep_ops;
-		ep->ep.maxpacket = 512;
+		usb_ep_set_maxpacket_limit(&ep->ep, 512);
 	}
-	m66592->ep[0].ep.maxpacket = 64;
+	usb_ep_set_maxpacket_limit(&m66592->ep[0].ep, 64);
 	m66592->ep[0].pipenum = 0;
 	m66592->ep[0].fifoaddr = M66592_CFIFO;
 	m66592->ep[0].fifosel = M66592_CFIFOSEL;
diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c
index 234711e..9fe31d7 100644
--- a/drivers/usb/gadget/mv_u3d_core.c
+++ b/drivers/usb/gadget/mv_u3d_core.c
@@ -1336,7 +1336,7 @@
 	ep->ep.name = ep->name;
 	ep->ep.ops = &mv_u3d_ep_ops;
 	ep->wedge = 0;
-	ep->ep.maxpacket = MV_U3D_EP0_MAX_PKT_SIZE;
+	usb_ep_set_maxpacket_limit(&ep->ep, MV_U3D_EP0_MAX_PKT_SIZE);
 	ep->ep_num = 0;
 	ep->ep.desc = &mv_u3d_ep0_desc;
 	INIT_LIST_HEAD(&ep->queue);
@@ -1361,7 +1361,7 @@
 		ep->ep.name = ep->name;
 
 		ep->ep.ops = &mv_u3d_ep_ops;
-		ep->ep.maxpacket = (unsigned short) ~0;
+		usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
 		ep->ep_num = i / 2;
 
 		INIT_LIST_HEAD(&ep->queue);
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index 104cdbe..d43ce95 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -1261,7 +1261,7 @@
 	ep->ep.ops = &mv_ep_ops;
 	ep->wedge = 0;
 	ep->stopped = 0;
-	ep->ep.maxpacket = EP0_MAX_PKT_SIZE;
+	usb_ep_set_maxpacket_limit(&ep->ep, EP0_MAX_PKT_SIZE);
 	ep->ep_num = 0;
 	ep->ep.desc = &mv_ep0_desc;
 	INIT_LIST_HEAD(&ep->queue);
@@ -1284,7 +1284,7 @@
 
 		ep->ep.ops = &mv_ep_ops;
 		ep->stopped = 0;
-		ep->ep.maxpacket = (unsigned short) ~0;
+		usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
 		ep->ep_num = i / 2;
 
 		INIT_LIST_HEAD(&ep->queue);
diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
index bf2bb39..ca15405 100644
--- a/drivers/usb/gadget/net2272.c
+++ b/drivers/usb/gadget/net2272.c
@@ -266,7 +266,7 @@
 	ep->desc = NULL;
 	INIT_LIST_HEAD(&ep->queue);
 
-	ep->ep.maxpacket = ~0;
+	usb_ep_set_maxpacket_limit(&ep->ep, ~0);
 	ep->ep.ops = &net2272_ep_ops;
 
 	/* disable irqs, endpoint */
@@ -1409,7 +1409,7 @@
 			ep->fifo_size = 64;
 		net2272_ep_reset(ep);
 	}
-	dev->ep[0].ep.maxpacket = 64;
+	usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64);
 
 	dev->gadget.ep0 = &dev->ep[0].ep;
 	dev->ep[0].stopped = 0;
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index fc85217..43e5e2f 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -293,7 +293,7 @@
 	ep->desc = NULL;
 	INIT_LIST_HEAD (&ep->queue);
 
-	ep->ep.maxpacket = ~0;
+	usb_ep_set_maxpacket_limit(&ep->ep, ~0);
 	ep->ep.ops = &net2280_ep_ops;
 
 	/* disable the dma, irqs, endpoint... */
@@ -1805,9 +1805,9 @@
 		ep->regs = &dev->epregs [tmp];
 		ep_reset (dev->regs, ep);
 	}
-	dev->ep [0].ep.maxpacket = 64;
-	dev->ep [5].ep.maxpacket = 64;
-	dev->ep [6].ep.maxpacket = 64;
+	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;
diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c
index 0a8099a..3ab3861 100644
--- a/drivers/usb/gadget/nokia.c
+++ b/drivers/usb/gadget/nokia.c
@@ -126,9 +126,9 @@
 	struct usb_function *f_ecm;
 	struct usb_function *f_obex2 = NULL;
 	int status = 0;
-	int obex1_stat = 0;
-	int obex2_stat = 0;
-	int phonet_stat = 0;
+	int obex1_stat = -1;
+	int obex2_stat = -1;
+	int phonet_stat = -1;
 
 	if (!IS_ERR(fi_phonet)) {
 		f_phonet = usb_get_function(fi_phonet);
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 83957cc..34bd713 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -2586,7 +2586,8 @@
 
 	ep->ep.name = ep->name;
 	ep->ep.ops = &omap_ep_ops;
-	ep->ep.maxpacket = ep->maxpacket = maxp;
+	ep->maxpacket = maxp;
+	usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
 	list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
 
 	return buf;
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 78a3d92..eb8c3be 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -2896,12 +2896,12 @@
 			ep->offset_addr = (UDC_EPINT_OUT_SHIFT + ep->num) *
 					  UDC_EP_REG_SHIFT;
 		/* need to set ep->ep.maxpacket and set Default Configuration?*/
-		ep->ep.maxpacket = UDC_BULK_MAX_PKT_SIZE;
+		usb_ep_set_maxpacket_limit(&ep->ep, UDC_BULK_MAX_PKT_SIZE);
 		list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
 		INIT_LIST_HEAD(&ep->queue);
 	}
-	dev->ep[UDC_EP0IN_IDX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE;
-	dev->ep[UDC_EP0OUT_IDX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE;
+	usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IDX].ep, UDC_EP0IN_MAX_PKT_SIZE);
+	usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IDX].ep, UDC_EP0OUT_MAX_PKT_SIZE);
 
 	/* remove ep0 in and out from the list.  They have own pointer */
 	list_del_init(&dev->ep[UDC_EP0IN_IDX].ep.ep_list);
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index 409a3c4..33b09a7 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -1194,6 +1194,7 @@
 		ep->stopped = 0;
 		INIT_LIST_HEAD (&ep->queue);
 		ep->pio_irqs = 0;
+		usb_ep_set_maxpacket_limit(&ep->ep, ep->ep.maxpacket);
 	}
 
 	/* the rest was statically initialized, and is read-only */
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 3c97da7..cdf4d67 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -1737,9 +1737,12 @@
 	}
 
 	/* USB endpoints init */
-	for (i = 1; i < NR_USB_ENDPOINTS; i++)
+	for (i = 1; i < NR_USB_ENDPOINTS; i++) {
 		list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list,
 				&dev->gadget.ep_list);
+		usb_ep_set_maxpacket_limit(&dev->udc_usb_ep[i].usb_ep,
+					   dev->udc_usb_ep[i].usb_ep.maxpacket);
+	}
 }
 
 /**
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index 68be48d..aff0a67 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -1833,7 +1833,7 @@
 	r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
 
 	if (r8a66597->pdata->on_chip) {
-		clk_disable(r8a66597->clk);
+		clk_disable_unprepare(r8a66597->clk);
 		clk_put(r8a66597->clk);
 	}
 
@@ -1931,7 +1931,7 @@
 			ret = PTR_ERR(r8a66597->clk);
 			goto clean_up;
 		}
-		clk_enable(r8a66597->clk);
+		clk_prepare_enable(r8a66597->clk);
 	}
 
 	if (r8a66597->pdata->sudmac) {
@@ -1964,9 +1964,9 @@
 		INIT_LIST_HEAD(&ep->queue);
 		ep->ep.name = r8a66597_ep_name[i];
 		ep->ep.ops = &r8a66597_ep_ops;
-		ep->ep.maxpacket = 512;
+		usb_ep_set_maxpacket_limit(&ep->ep, 512);
 	}
-	r8a66597->ep[0].ep.maxpacket = 64;
+	usb_ep_set_maxpacket_limit(&r8a66597->ep[0].ep, 64);
 	r8a66597->ep[0].pipenum = 0;
 	r8a66597->ep[0].fifoaddr = CFIFO;
 	r8a66597->ep[0].fifosel = CFIFOSEL;
@@ -1996,7 +1996,7 @@
 	free_irq(irq, r8a66597);
 clean_up2:
 	if (r8a66597->pdata->on_chip) {
-		clk_disable(r8a66597->clk);
+		clk_disable_unprepare(r8a66597->clk);
 		clk_put(r8a66597->clk);
 	}
 clean_up:
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index a3ad732..1ffbdb4 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -1142,7 +1142,7 @@
 #endif /* CONFIG_USB_GADGET_DEBUG_FILES */
 
 
-static int rndis_init(void)
+int rndis_init(void)
 {
 	u8 i;
 
@@ -1174,9 +1174,8 @@
 
 	return 0;
 }
-module_init(rndis_init);
 
-static void rndis_exit(void)
+void rndis_exit(void)
 {
 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
 	u8 i;
@@ -1188,6 +1187,4 @@
 	}
 #endif
 }
-module_exit(rndis_exit);
 
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index e20bc10..c0ff1cb 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -30,14 +30,14 @@
 #include <linux/clk.h>
 #include <linux/regulator/consumer.h>
 #include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/usb/phy.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/phy.h>
 #include <linux/platform_data/s3c-hsotg.h>
 
-#include <mach/map.h>
-
 #include "s3c-hsotg.h"
 
 static const char * const s3c_hsotg_supply_names[] = {
@@ -140,11 +140,13 @@
  * @dev: The parent device supplied to the probe function
  * @driver: USB gadget driver
  * @phy: The otg phy transceiver structure for phy control.
+ * @uphy: The otg phy transceiver structure for old USB phy control.
  * @plat: The platform specific configuration data. This can be removed once
  * all SoCs support usb transceiver.
  * @regs: The memory area mapped for accessing registers.
  * @irq: The IRQ number we are using
  * @supplies: Definition of USB power supplies
+ * @phyif: PHY interface width
  * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
  * @num_of_eps: Number of available EPs (excluding EP0)
  * @debug_root: root directrory for debugfs.
@@ -161,7 +163,8 @@
 struct s3c_hsotg {
 	struct device		 *dev;
 	struct usb_gadget_driver *driver;
-	struct usb_phy		*phy;
+	struct phy		 *phy;
+	struct usb_phy		 *uphy;
 	struct s3c_hsotg_plat	 *plat;
 
 	spinlock_t              lock;
@@ -172,6 +175,7 @@
 
 	struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)];
 
+	u32			phyif;
 	unsigned int		dedicated_fifos:1;
 	unsigned char           num_of_eps;
 
@@ -2086,13 +2090,13 @@
 	case DSTS_EnumSpd_FS48:
 		hsotg->gadget.speed = USB_SPEED_FULL;
 		ep0_mps = EP0_MPS_LIMIT;
-		ep_mps = 64;
+		ep_mps = 1023;
 		break;
 
 	case DSTS_EnumSpd_HS:
 		hsotg->gadget.speed = USB_SPEED_HIGH;
 		ep0_mps = EP0_MPS_LIMIT;
-		ep_mps = 512;
+		ep_mps = 1024;
 		break;
 
 	case DSTS_EnumSpd_LS:
@@ -2156,6 +2160,9 @@
 		s3c_hsotg_complete_request(hsotg, ep, req,
 					   result);
 	}
+	if(hsotg->dedicated_fifos)
+		if ((readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4 < 3072)
+			s3c_hsotg_txfifo_flush(hsotg, ep->index);
 }
 
 #define call_gadget(_hs, _entry) \
@@ -2283,7 +2290,7 @@
 	 */
 
 	/* set the PLL on, remove the HNP/SRP and set the PHY */
-	writel(GUSBCFG_PHYIf16 | GUSBCFG_TOutCal(7) |
+	writel(hsotg->phyif | GUSBCFG_TOutCal(7) |
 	       (0x5 << 10), hsotg->regs + GUSBCFG);
 
 	s3c_hsotg_init_fifo(hsotg);
@@ -2908,8 +2915,11 @@
 
 	dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev);
 
-	if (hsotg->phy)
-		usb_phy_init(hsotg->phy);
+	if (hsotg->phy) {
+		phy_init(hsotg->phy);
+		phy_power_on(hsotg->phy);
+	} else if (hsotg->uphy)
+		usb_phy_init(hsotg->uphy);
 	else if (hsotg->plat->phy_init)
 		hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
 }
@@ -2925,8 +2935,11 @@
 {
 	struct platform_device *pdev = to_platform_device(hsotg->dev);
 
-	if (hsotg->phy)
-		usb_phy_shutdown(hsotg->phy);
+	if (hsotg->phy) {
+		phy_power_off(hsotg->phy);
+		phy_exit(hsotg->phy);
+	} else if (hsotg->uphy)
+		usb_phy_shutdown(hsotg->uphy);
 	else if (hsotg->plat->phy_exit)
 		hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
 }
@@ -3152,7 +3165,7 @@
 
 	hs_ep->parent = hsotg;
 	hs_ep->ep.name = hs_ep->name;
-	hs_ep->ep.maxpacket = epnum ? 1024 : EP0_MPS_LIMIT;
+	usb_ep_set_maxpacket_limit(&hs_ep->ep, epnum ? 1024 : EP0_MPS_LIMIT);
 	hs_ep->ep.ops = &s3c_hsotg_ep_ops;
 
 	/*
@@ -3533,7 +3546,8 @@
 static int s3c_hsotg_probe(struct platform_device *pdev)
 {
 	struct s3c_hsotg_plat *plat = dev_get_platdata(&pdev->dev);
-	struct usb_phy *phy;
+	struct phy *phy;
+	struct usb_phy *uphy;
 	struct device *dev = &pdev->dev;
 	struct s3c_hsotg_ep *eps;
 	struct s3c_hsotg *hsotg;
@@ -3548,19 +3562,26 @@
 		return -ENOMEM;
 	}
 
-	phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+	/*
+	 * Attempt to find a generic PHY, then look for an old style
+	 * USB PHY, finally fall back to pdata
+	 */
+	phy = devm_phy_get(&pdev->dev, "usb2-phy");
 	if (IS_ERR(phy)) {
-		/* Fallback for pdata */
-		plat = dev_get_platdata(&pdev->dev);
-		if (!plat) {
-			dev_err(&pdev->dev, "no platform data or transceiver defined\n");
-			return -EPROBE_DEFER;
-		} else {
+		uphy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+		if (IS_ERR(uphy)) {
+			/* Fallback for pdata */
+			plat = dev_get_platdata(&pdev->dev);
+			if (!plat) {
+				dev_err(&pdev->dev,
+				"no platform data or transceiver defined\n");
+				return -EPROBE_DEFER;
+			}
 			hsotg->plat = plat;
-		}
-	} else {
+		} else
+			hsotg->uphy = uphy;
+	} else
 		hsotg->phy = phy;
-	}
 
 	hsotg->dev = dev;
 
@@ -3627,6 +3648,19 @@
 		goto err_supplies;
 	}
 
+	/* Set default UTMI width */
+	hsotg->phyif = GUSBCFG_PHYIf16;
+
+	/*
+	 * If using the generic PHY framework, check if the PHY bus
+	 * width is 8-bit and set the phyif appropriately.
+	 */
+	if (hsotg->phy && (phy_get_bus_width(phy) == 8))
+		hsotg->phyif = GUSBCFG_PHYIf8;
+
+	if (hsotg->phy)
+		phy_init(hsotg->phy);
+
 	/* usb phy enable */
 	s3c_hsotg_phy_enable(hsotg);
 
@@ -3720,6 +3754,8 @@
 	}
 
 	s3c_hsotg_phy_disable(hsotg);
+	if (hsotg->phy)
+		phy_exit(hsotg->phy);
 	clk_disable_unprepare(hsotg->clk);
 
 	return 0;
@@ -3733,6 +3769,7 @@
 #ifdef CONFIG_OF
 static const struct of_device_id s3c_hsotg_of_ids[] = {
 	{ .compatible = "samsung,s3c6400-hsotg", },
+	{ .compatible = "snps,dwc2", },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, s3c_hsotg_of_ids);
diff --git a/drivers/usb/gadget/s3c-hsotg.h b/drivers/usb/gadget/s3c-hsotg.h
index d650b12..85f549f 100644
--- a/drivers/usb/gadget/s3c-hsotg.h
+++ b/drivers/usb/gadget/s3c-hsotg.h
@@ -55,6 +55,7 @@
 #define GUSBCFG_HNPCap				(1 << 9)
 #define GUSBCFG_SRPCap				(1 << 8)
 #define GUSBCFG_PHYIf16			(1 << 3)
+#define GUSBCFG_PHYIf8				(0 << 3)
 #define GUSBCFG_TOutCal_MASK			(0x7 << 0)
 #define GUSBCFG_TOutCal_SHIFT			(0)
 #define GUSBCFG_TOutCal_LIMIT			(0x7)
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index 1a1a414..ea4bbfe 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -999,7 +999,7 @@
 
 	hsep->dev = hsudc;
 	hsep->ep.name = hsep->name;
-	hsep->ep.maxpacket = epnum ? 512 : 64;
+	usb_ep_set_maxpacket_limit(&hsep->ep, epnum ? 512 : 64);
 	hsep->ep.ops = &s3c_hsudc_ep_ops;
 	hsep->fifo = hsudc->regs + S3C_BR(epnum);
 	hsep->ep.desc = NULL;
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index c72d810..f04b2c3 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1629,6 +1629,7 @@
 		ep->ep.desc = NULL;
 		ep->halted = 0;
 		INIT_LIST_HEAD(&ep->queue);
+		usb_ep_set_maxpacket_limit(&ep->ep, &ep->ep.maxpacket);
 	}
 }
 
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 2aae0d6..b7d4f82 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -753,7 +753,7 @@
  * gadget driver using this framework.  The link layer addresses are
  * set up using module parameters.
  *
- * Returns negative errno, or zero on success
+ * Returns an eth_dev pointer on success, or an ERR_PTR on failure.
  */
 struct eth_dev *gether_setup_name(struct usb_gadget *g,
 		const char *dev_addr, const char *host_addr,
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index fb23d1f..0f0290a 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -106,7 +106,7 @@
  * gadget driver using this framework.  The link layer addresses are
  * set up using module parameters.
  *
- * Returns negative errno, or zero on success
+ * Returns a eth_dev pointer on success, or an ERR_PTR on failure
  */
 static inline struct eth_dev *gether_setup(struct usb_gadget *g,
 		const char *dev_addr, const char *host_addr,
@@ -267,45 +267,4 @@
 	return true;
 }
 
-/* each configuration may bind one instance of an ethernet link */
-int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-		struct eth_dev *dev);
-int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-		struct eth_dev *dev);
-
-#ifdef USB_ETH_RNDIS
-
-int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-		u32 vendorID, const char *manufacturer, struct eth_dev *dev);
-
-#else
-
-static inline int
-rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-		u32 vendorID, const char *manufacturer, struct eth_dev *dev)
-{
-	return 0;
-}
-
-#endif
-
-/**
- * rndis_bind_config - add RNDIS network link to a configuration
- * @c: the configuration to support the network link
- * @ethaddr: a buffer in which the ethernet address of the host side
- *	side of the link was recorded
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- *
- * Caller must have called @gether_setup().  Caller is also responsible
- * for calling @gether_cleanup() before module unload.
- */
-static inline int rndis_bind_config(struct usb_configuration *c,
-		u8 ethaddr[ETH_ALEN], struct eth_dev *dev)
-{
-	return rndis_bind_config_vendor(c, ethaddr, 0, NULL, dev);
-}
-
-
 #endif /* __U_ETHER_H */
diff --git a/drivers/usb/gadget/u_f.c b/drivers/usb/gadget/u_f.c
new file mode 100644
index 0000000..63b6642
--- /dev/null
+++ b/drivers/usb/gadget/u_f.c
@@ -0,0 +1,32 @@
+/*
+ * u_f.c -- USB function utilities for Gadget stack
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/usb/gadget.h>
+#include "u_f.h"
+
+struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len)
+{
+	struct usb_request      *req;
+
+	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+	if (req) {
+		req->length = len ?: default_len;
+		req->buf = kmalloc(req->length, GFP_ATOMIC);
+		if (!req->buf) {
+			usb_ep_free_request(ep, req);
+			req = NULL;
+		}
+	}
+	return req;
+}
+EXPORT_SYMBOL(alloc_ep_req);
diff --git a/drivers/usb/gadget/u_f.h b/drivers/usb/gadget/u_f.h
new file mode 100644
index 0000000..71034c0
--- /dev/null
+++ b/drivers/usb/gadget/u_f.h
@@ -0,0 +1,26 @@
+/*
+ * u_f.h
+ *
+ * Utility definitions for USB functions
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __U_F_H__
+#define __U_F_H__
+
+struct usb_ep;
+struct usb_request;
+
+struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len);
+
+#endif /* __U_F_H__ */
+
+
diff --git a/drivers/usb/gadget/u_fs.h b/drivers/usb/gadget/u_fs.h
new file mode 100644
index 0000000..bc2d371
--- /dev/null
+++ b/drivers/usb/gadget/u_fs.h
@@ -0,0 +1,267 @@
+/*
+ * u_fs.h
+ *
+ * Utility definitions for the FunctionFS
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef U_FFS_H
+#define U_FFS_H
+
+#include <linux/usb/composite.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+
+#ifdef VERBOSE_DEBUG
+#ifndef pr_vdebug
+#  define pr_vdebug pr_debug
+#endif /* pr_vdebug */
+#  define ffs_dump_mem(prefix, ptr, len) \
+	print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len)
+#else
+#ifndef pr_vdebug
+#  define pr_vdebug(...)                 do { } while (0)
+#endif /* pr_vdebug */
+#  define ffs_dump_mem(prefix, ptr, len) do { } while (0)
+#endif /* VERBOSE_DEBUG */
+
+#define ENTER()    pr_vdebug("%s()\n", __func__)
+
+struct f_fs_opts;
+
+struct ffs_dev {
+	const char *name;
+	bool name_allocated;
+	bool mounted;
+	bool desc_ready;
+	bool single;
+	struct ffs_data *ffs_data;
+	struct f_fs_opts *opts;
+	struct list_head entry;
+
+	int (*ffs_ready_callback)(struct ffs_data *ffs);
+	void (*ffs_closed_callback)(struct ffs_data *ffs);
+	void *(*ffs_acquire_dev_callback)(struct ffs_dev *dev);
+	void (*ffs_release_dev_callback)(struct ffs_dev *dev);
+};
+
+extern struct mutex ffs_lock;
+
+static inline void ffs_dev_lock(void)
+{
+	mutex_lock(&ffs_lock);
+}
+
+static inline void ffs_dev_unlock(void)
+{
+	mutex_unlock(&ffs_lock);
+}
+
+struct ffs_dev *ffs_alloc_dev(void);
+int ffs_name_dev(struct ffs_dev *dev, const char *name);
+int ffs_single_dev(struct ffs_dev *dev);
+void ffs_free_dev(struct ffs_dev *dev);
+
+struct ffs_epfile;
+struct ffs_function;
+
+enum ffs_state {
+	/*
+	 * Waiting for descriptors and strings.
+	 *
+	 * In this state no open(2), read(2) or write(2) on epfiles
+	 * may succeed (which should not be the problem as there
+	 * should be no such files opened in the first place).
+	 */
+	FFS_READ_DESCRIPTORS,
+	FFS_READ_STRINGS,
+
+	/*
+	 * We've got descriptors and strings.  We are or have called
+	 * functionfs_ready_callback().  functionfs_bind() may have
+	 * been called but we don't know.
+	 *
+	 * This is the only state in which operations on epfiles may
+	 * succeed.
+	 */
+	FFS_ACTIVE,
+
+	/*
+	 * All endpoints have been closed.  This state is also set if
+	 * we encounter an unrecoverable error.  The only
+	 * unrecoverable error is situation when after reading strings
+	 * from user space we fail to initialise epfiles or
+	 * functionfs_ready_callback() returns with error (<0).
+	 *
+	 * In this state no open(2), read(2) or write(2) (both on ep0
+	 * as well as epfile) may succeed (at this point epfiles are
+	 * unlinked and all closed so this is not a problem; ep0 is
+	 * also closed but ep0 file exists and so open(2) on ep0 must
+	 * fail).
+	 */
+	FFS_CLOSING
+};
+
+enum ffs_setup_state {
+	/* There is no setup request pending. */
+	FFS_NO_SETUP,
+	/*
+	 * User has read events and there was a setup request event
+	 * there.  The next read/write on ep0 will handle the
+	 * request.
+	 */
+	FFS_SETUP_PENDING,
+	/*
+	 * There was event pending but before user space handled it
+	 * some other event was introduced which canceled existing
+	 * setup.  If this state is set read/write on ep0 return
+	 * -EIDRM.  This state is only set when adding event.
+	 */
+	FFS_SETUP_CANCELED
+};
+
+struct ffs_data {
+	struct usb_gadget		*gadget;
+
+	/*
+	 * Protect access read/write operations, only one read/write
+	 * at a time.  As a consequence protects ep0req and company.
+	 * While setup request is being processed (queued) this is
+	 * held.
+	 */
+	struct mutex			mutex;
+
+	/*
+	 * Protect access to endpoint related structures (basically
+	 * usb_ep_queue(), usb_ep_dequeue(), etc. calls) except for
+	 * endpoint zero.
+	 */
+	spinlock_t			eps_lock;
+
+	/*
+	 * XXX REVISIT do we need our own request? Since we are not
+	 * handling setup requests immediately user space may be so
+	 * slow that another setup will be sent to the gadget but this
+	 * time not to us but another function and then there could be
+	 * a race.  Is that the case? Or maybe we can use cdev->req
+	 * after all, maybe we just need some spinlock for that?
+	 */
+	struct usb_request		*ep0req;		/* P: mutex */
+	struct completion		ep0req_completion;	/* P: mutex */
+	int				ep0req_status;		/* P: mutex */
+
+	/* reference counter */
+	atomic_t			ref;
+	/* how many files are opened (EP0 and others) */
+	atomic_t			opened;
+
+	/* EP0 state */
+	enum ffs_state			state;
+
+	/*
+	 * Possible transitions:
+	 * + FFS_NO_SETUP       -> FFS_SETUP_PENDING  -- P: ev.waitq.lock
+	 *               happens only in ep0 read which is P: mutex
+	 * + FFS_SETUP_PENDING  -> FFS_NO_SETUP       -- P: ev.waitq.lock
+	 *               happens only in ep0 i/o  which is P: mutex
+	 * + FFS_SETUP_PENDING  -> FFS_SETUP_CANCELED -- P: ev.waitq.lock
+	 * + FFS_SETUP_CANCELED -> FFS_NO_SETUP       -- cmpxchg
+	 */
+	enum ffs_setup_state		setup_state;
+
+#define FFS_SETUP_STATE(ffs)					\
+	((enum ffs_setup_state)cmpxchg(&(ffs)->setup_state,	\
+				       FFS_SETUP_CANCELED, FFS_NO_SETUP))
+
+	/* Events & such. */
+	struct {
+		u8				types[4];
+		unsigned short			count;
+		/* XXX REVISIT need to update it in some places, or do we? */
+		unsigned short			can_stall;
+		struct usb_ctrlrequest		setup;
+
+		wait_queue_head_t		waitq;
+	} ev; /* the whole structure, P: ev.waitq.lock */
+
+	/* Flags */
+	unsigned long			flags;
+#define FFS_FL_CALL_CLOSED_CALLBACK 0
+#define FFS_FL_BOUND                1
+
+	/* Active function */
+	struct ffs_function		*func;
+
+	/*
+	 * Device name, write once when file system is mounted.
+	 * Intended for user to read if she wants.
+	 */
+	const char			*dev_name;
+	/* Private data for our user (ie. gadget).  Managed by user. */
+	void				*private_data;
+
+	/* filled by __ffs_data_got_descs() */
+	/*
+	 * Real descriptors are 16 bytes after raw_descs (so you need
+	 * to skip 16 bytes (ie. ffs->raw_descs + 16) to get to the
+	 * first full speed descriptor).  raw_descs_length and
+	 * raw_fs_descs_length do not have those 16 bytes added.
+	 */
+	const void			*raw_descs;
+	unsigned			raw_descs_length;
+	unsigned			raw_fs_descs_length;
+	unsigned			fs_descs_count;
+	unsigned			hs_descs_count;
+
+	unsigned short			strings_count;
+	unsigned short			interfaces_count;
+	unsigned short			eps_count;
+	unsigned short			_pad1;
+
+	/* filled by __ffs_data_got_strings() */
+	/* ids in stringtabs are set in functionfs_bind() */
+	const void			*raw_strings;
+	struct usb_gadget_strings	**stringtabs;
+
+	/*
+	 * File system's super block, write once when file system is
+	 * mounted.
+	 */
+	struct super_block		*sb;
+
+	/* File permissions, written once when fs is mounted */
+	struct ffs_file_perms {
+		umode_t				mode;
+		kuid_t				uid;
+		kgid_t				gid;
+	}				file_perms;
+
+	/*
+	 * The endpoint files, filled by ffs_epfiles_create(),
+	 * destroyed by ffs_epfiles_destroy().
+	 */
+	struct ffs_epfile		*epfiles;
+};
+
+
+struct f_fs_opts {
+	struct usb_function_instance	func_inst;
+	struct ffs_dev			*dev;
+	unsigned			refcnt;
+	bool				no_configfs;
+};
+
+static inline struct f_fs_opts *to_f_fs_opts(struct usb_function_instance *fi)
+{
+	return container_of(fi, struct f_fs_opts, func_inst);
+}
+
+#endif /* U_FFS_H */
diff --git a/drivers/usb/gadget/u_rndis.h b/drivers/usb/gadget/u_rndis.h
index c62ba82..7291b15 100644
--- a/drivers/usb/gadget/u_rndis.h
+++ b/drivers/usb/gadget/u_rndis.h
@@ -36,6 +36,8 @@
 	int				refcnt;
 };
 
+int rndis_init(void);
+void rndis_exit(void);
 void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net);
 
 #endif /* U_RNDIS_H */
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index f49b0b6..9f170c5 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -64,10 +64,10 @@
 module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
 
 static struct usb_zero_options gzero_options = {
-	.isoc_interval = 4,
-	.isoc_maxpacket = 1024,
-	.bulk_buflen = 4096,
-	.qlen = 32,
+	.isoc_interval = GZERO_ISOC_INTERVAL,
+	.isoc_maxpacket = GZERO_ISOC_MAXPACKET,
+	.bulk_buflen = GZERO_BULK_BUFLEN,
+	.qlen = GZERO_QLEN,
 };
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 57dfc0c..688dc8b 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -6,7 +6,7 @@
 # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
 config USB_MUSB_HDRC
 	tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
-	depends on USB_GADGET
+	depends on (USB || USB_GADGET)
 	help
 	  Say Y here if your system has a dual role high speed USB
 	  controller based on the Mentor Graphics silicon IP.  Then
@@ -35,21 +35,21 @@
 
 config USB_MUSB_HOST
 	bool "Host only mode"
-	depends on USB
+	depends on USB=y || USB=USB_MUSB_HDRC
 	help
 	  Select this when you want to use MUSB in host mode only,
 	  thereby the gadget feature will be regressed.
 
 config USB_MUSB_GADGET
 	bool "Gadget only mode"
-	depends on USB_GADGET
+	depends on USB_GADGET=y || USB_GADGET=USB_MUSB_HDRC
 	help
 	  Select this when you want to use MUSB in gadget mode only,
 	  thereby the host feature will be regressed.
 
 config USB_MUSB_DUAL_ROLE
 	bool "Dual Role mode"
-	depends on (USB && USB_GADGET)
+	depends on ((USB=y || USB=USB_MUSB_HDRC) && (USB_GADGET=y || USB_GADGET=USB_MUSB_HDRC))
 	help
 	  This is the default mode of working of MUSB controller where
 	  both host and gadget features are enabled.
@@ -93,6 +93,12 @@
 config USB_MUSB_UX500
 	tristate "Ux500 platforms"
 
+config USB_MUSB_JZ4740
+	tristate "JZ4740"
+	depends on MACH_JZ4740 || COMPILE_TEST
+	depends on USB_MUSB_GADGET
+	depends on USB_OTG_BLACKLIST_HUB
+
 endchoice
 
 config USB_MUSB_AM335X_CHILD
@@ -100,7 +106,7 @@
 
 choice
 	prompt 'MUSB DMA mode'
-	default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM
+	default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM || USB_MUSB_JZ4740
 	default USB_UX500_DMA if USB_MUSB_UX500
 	default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
 	default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index c5ea5c6..ba49501 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -19,6 +19,7 @@
 obj-$(CONFIG_USB_MUSB_DA8XX)			+= da8xx.o
 obj-$(CONFIG_USB_MUSB_BLACKFIN)			+= blackfin.o
 obj-$(CONFIG_USB_MUSB_UX500)			+= ux500.o
+obj-$(CONFIG_USB_MUSB_JZ4740)			+= jz4740.o
 
 
 obj-$(CONFIG_USB_MUSB_AM335X_CHILD)		+= musb_am335x.o
diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c
new file mode 100644
index 0000000..5f30537
--- /dev/null
+++ b/drivers/usb/musb/jz4740.c
@@ -0,0 +1,201 @@
+/*
+ * Ingenic JZ4740 "glue layer"
+ *
+ * Copyright (C) 2013, Apelete Seketeli <apelete@seketeli.net>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "musb_core.h"
+
+struct jz4740_glue {
+	struct device           *dev;
+	struct platform_device  *musb;
+	struct clk		*clk;
+};
+
+static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
+{
+	unsigned long   flags;
+	irqreturn_t     retval = IRQ_NONE;
+	struct musb     *musb = __hci;
+
+	spin_lock_irqsave(&musb->lock, flags);
+
+	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+
+	/*
+	 * The controller is gadget only, the state of the host mode IRQ bits is
+	 * undefined. Mask them to make sure that the musb driver core will
+	 * never see them set
+	 */
+	musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
+	    MUSB_INTR_RESET | MUSB_INTR_SOF;
+
+	if (musb->int_usb || musb->int_tx || musb->int_rx)
+		retval = musb_interrupt(musb);
+
+	spin_unlock_irqrestore(&musb->lock, flags);
+
+	return retval;
+}
+
+static struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, },
+};
+
+static struct musb_hdrc_config jz4740_musb_config = {
+	/* Silicon does not implement USB OTG. */
+	.multipoint = 0,
+	/* Max EPs scanned, driver will decide which EP can be used. */
+	.num_eps    = 4,
+	/* RAMbits needed to configure EPs from table */
+	.ram_bits   = 9,
+	.fifo_cfg = jz4740_musb_fifo_cfg,
+	.fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg),
+};
+
+static struct musb_hdrc_platform_data jz4740_musb_platform_data = {
+	.mode   = MUSB_PERIPHERAL,
+	.config = &jz4740_musb_config,
+};
+
+static int jz4740_musb_init(struct musb *musb)
+{
+	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+	if (!musb->xceiv) {
+		pr_err("HS UDC: no transceiver configured\n");
+		return -ENODEV;
+	}
+
+	/* Silicon does not implement ConfigData register.
+	 * Set dyn_fifo to avoid reading EP config from hardware.
+	 */
+	musb->dyn_fifo = true;
+
+	musb->isr = jz4740_musb_interrupt;
+
+	return 0;
+}
+
+static int jz4740_musb_exit(struct musb *musb)
+{
+	usb_put_phy(musb->xceiv);
+
+	return 0;
+}
+
+static const struct musb_platform_ops jz4740_musb_ops = {
+	.init		= jz4740_musb_init,
+	.exit		= jz4740_musb_exit,
+};
+
+static int jz4740_probe(struct platform_device *pdev)
+{
+	struct musb_hdrc_platform_data	*pdata = &jz4740_musb_platform_data;
+	struct platform_device		*musb;
+	struct jz4740_glue		*glue;
+	struct clk                      *clk;
+	int				ret;
+
+	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
+	if (!glue)
+		return -ENOMEM;
+
+	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		return -ENOMEM;
+	}
+
+	clk = devm_clk_get(&pdev->dev, "udc");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		ret = PTR_ERR(clk);
+		goto err_platform_device_put;
+	}
+
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clock\n");
+		goto err_platform_device_put;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+	glue->clk			= clk;
+
+	pdata->platform_ops		= &jz4740_musb_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+					    pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err_clk_disable;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err_clk_disable;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err_clk_disable;
+	}
+
+	return 0;
+
+err_clk_disable:
+	clk_disable_unprepare(clk);
+err_platform_device_put:
+	platform_device_put(musb);
+	return ret;
+}
+
+static int jz4740_remove(struct platform_device *pdev)
+{
+	struct jz4740_glue	*glue = platform_get_drvdata(pdev);
+
+	platform_device_unregister(glue->musb);
+	clk_disable_unprepare(glue->clk);
+
+	return 0;
+}
+
+static struct platform_driver jz4740_driver = {
+	.probe		= jz4740_probe,
+	.remove		= jz4740_remove,
+	.driver		= {
+		.name	= "musb-jz4740",
+	},
+};
+
+MODULE_DESCRIPTION("JZ4740 MUSB Glue Layer");
+MODULE_AUTHOR("Apelete Seketeli <apelete@seketeli.net>");
+MODULE_LICENSE("GPL v2");
+module_platform_driver(jz4740_driver);
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 4d4499b..5942f00 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -478,8 +478,8 @@
 				musb->port1_status |=
 						(USB_PORT_STAT_C_SUSPEND << 16)
 						| MUSB_PORT_STAT_RESUME;
-				musb->rh_timer = jiffies
-						+ msecs_to_jiffies(20);
+				schedule_delayed_work(
+					&musb->finish_resume_work, 20);
 
 				musb->xceiv->state = OTG_STATE_A_HOST;
 				musb->is_active = 1;
@@ -1813,6 +1813,21 @@
 	musb_host_free(musb);
 }
 
+static void musb_deassert_reset(struct work_struct *work)
+{
+	struct musb *musb;
+	unsigned long flags;
+
+	musb = container_of(work, struct musb, deassert_reset_work.work);
+
+	spin_lock_irqsave(&musb->lock, flags);
+
+	if (musb->port1_status & USB_PORT_STAT_RESET)
+		musb_port_reset(musb, false);
+
+	spin_unlock_irqrestore(&musb->lock, flags);
+}
+
 /*
  * Perform generic per-controller initialization.
  *
@@ -1897,6 +1912,8 @@
 
 	/* Init IRQ workqueue before request_irq */
 	INIT_WORK(&musb->irq_work, musb_irq_work);
+	INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset);
+	INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume);
 
 	/* setup musb parts of the core (especially endpoints) */
 	status = musb_core_init(plat->config->multipoint
@@ -1940,17 +1957,26 @@
 	switch (musb->port_mode) {
 	case MUSB_PORT_MODE_HOST:
 		status = musb_host_setup(musb, plat->power);
+		if (status < 0)
+			goto fail3;
+		status = musb_platform_set_mode(musb, MUSB_HOST);
 		break;
 	case MUSB_PORT_MODE_GADGET:
 		status = musb_gadget_setup(musb);
+		if (status < 0)
+			goto fail3;
+		status = musb_platform_set_mode(musb, MUSB_PERIPHERAL);
 		break;
 	case MUSB_PORT_MODE_DUAL_ROLE:
 		status = musb_host_setup(musb, plat->power);
 		if (status < 0)
 			goto fail3;
 		status = musb_gadget_setup(musb);
-		if (status)
+		if (status) {
 			musb_host_cleanup(musb);
+			goto fail3;
+		}
+		status = musb_platform_set_mode(musb, MUSB_OTG);
 		break;
 	default:
 		dev_err(dev, "unsupported port mode %d\n", musb->port_mode);
@@ -1981,6 +2007,8 @@
 
 fail3:
 	cancel_work_sync(&musb->irq_work);
+	cancel_delayed_work_sync(&musb->finish_resume_work);
+	cancel_delayed_work_sync(&musb->deassert_reset_work);
 	if (musb->dma_controller)
 		dma_controller_destroy(musb->dma_controller);
 fail2_5:
@@ -2044,6 +2072,8 @@
 		dma_controller_destroy(musb->dma_controller);
 
 	cancel_work_sync(&musb->irq_work);
+	cancel_delayed_work_sync(&musb->finish_resume_work);
+	cancel_delayed_work_sync(&musb->deassert_reset_work);
 	musb_free(musb);
 	device_init_wakeup(dev, 0);
 	return 0;
@@ -2216,16 +2246,28 @@
 		 */
 	}
 
+	musb_save_context(musb);
+
 	spin_unlock_irqrestore(&musb->lock, flags);
 	return 0;
 }
 
 static int musb_resume_noirq(struct device *dev)
 {
-	/* for static cmos like DaVinci, register values were preserved
+	struct musb	*musb = dev_to_musb(dev);
+
+	/*
+	 * For static cmos like DaVinci, register values were preserved
 	 * unless for some reason the whole soc powered down or the USB
 	 * module got reset through the PSC (vs just being disabled).
+	 *
+	 * For the DSPS glue layer though, a full register restore has to
+	 * be done. As it shouldn't harm other platforms, we do it
+	 * unconditionally.
 	 */
+
+	musb_restore_context(musb);
+
 	return 0;
 }
 
@@ -2283,19 +2325,4 @@
 	.shutdown	= musb_shutdown,
 };
 
-/*-------------------------------------------------------------------------*/
-
-static int __init musb_init(void)
-{
-	if (usb_disabled())
-		return 0;
-
-	return platform_driver_register(&musb_driver);
-}
-module_init(musb_init);
-
-static void __exit musb_cleanup(void)
-{
-	platform_driver_unregister(&musb_driver);
-}
-module_exit(musb_cleanup);
+module_platform_driver(musb_driver);
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 29f7cd7..7083e82 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -47,6 +47,7 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/musb.h>
 #include <linux/phy/phy.h>
+#include <linux/workqueue.h>
 
 struct musb;
 struct musb_hw_ep;
@@ -295,6 +296,8 @@
 
 	irqreturn_t		(*isr)(int, void *);
 	struct work_struct	irq_work;
+	struct delayed_work	deassert_reset_work;
+	struct delayed_work	finish_resume_work;
 	u16			hwvers;
 
 	u16			intrrxe;
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 1901f6f..593d3c9 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -83,6 +83,8 @@
 	u16	coreintr_status;
 	u16	phy_utmi;
 	u16	mode;
+	u16	tx_mode;
+	u16	rx_mode;
 
 	/* bit positions for control */
 	unsigned	reset:5;
@@ -106,10 +108,24 @@
 
 	/* bit positions for mode */
 	unsigned	iddig:5;
+	unsigned	iddig_mux:5;
 	/* miscellaneous stuff */
 	u8		poll_seconds;
 };
 
+/*
+ * register shadow for suspend
+ */
+struct dsps_context {
+	u32 control;
+	u32 epintr;
+	u32 coreintr;
+	u32 phy_utmi;
+	u32 mode;
+	u32 tx_mode;
+	u32 rx_mode;
+};
+
 /**
  * DSPS glue structure.
  */
@@ -119,6 +135,8 @@
 	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 */
+
+	struct dsps_context context;
 };
 
 static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
@@ -341,8 +359,9 @@
 	if (musb->int_tx || musb->int_rx || musb->int_usb)
 		ret |= musb_interrupt(musb);
 
-	/* Poll for ID change */
-	if (musb->xceiv->state == OTG_STATE_B_IDLE)
+	/* Poll for ID change in OTG port mode */
+	if (musb->xceiv->state == OTG_STATE_B_IDLE &&
+			musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
 		mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
 out:
 	spin_unlock_irqrestore(&musb->lock, flags);
@@ -406,6 +425,54 @@
 	return 0;
 }
 
+static int dsps_musb_set_mode(struct musb *musb, u8 mode)
+{
+	struct device *dev = musb->controller;
+	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
+	const struct dsps_musb_wrapper *wrp = glue->wrp;
+	void __iomem *ctrl_base = musb->ctrl_base;
+	void __iomem *base = musb->mregs;
+	u32 reg;
+
+	reg = dsps_readl(base, wrp->mode);
+
+	switch (mode) {
+	case MUSB_HOST:
+		reg &= ~(1 << wrp->iddig);
+
+		/*
+		 * if we're setting mode to host-only or device-only, we're
+		 * going to ignore whatever the PHY sends us and just force
+		 * ID pin status by SW
+		 */
+		reg |= (1 << wrp->iddig_mux);
+
+		dsps_writel(base, wrp->mode, reg);
+		dsps_writel(ctrl_base, wrp->phy_utmi, 0x02);
+		break;
+	case MUSB_PERIPHERAL:
+		reg |= (1 << wrp->iddig);
+
+		/*
+		 * if we're setting mode to host-only or device-only, we're
+		 * going to ignore whatever the PHY sends us and just force
+		 * ID pin status by SW
+		 */
+		reg |= (1 << wrp->iddig_mux);
+
+		dsps_writel(base, wrp->mode, reg);
+		break;
+	case MUSB_OTG:
+		dsps_writel(base, wrp->phy_utmi, 0x02);
+		break;
+	default:
+		dev_err(glue->dev, "unsupported mode %d\n", mode);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static struct musb_platform_ops dsps_ops = {
 	.init		= dsps_musb_init,
 	.exit		= dsps_musb_exit,
@@ -414,6 +481,7 @@
 	.disable	= dsps_musb_disable,
 
 	.try_idle	= dsps_musb_try_idle,
+	.set_mode	= dsps_musb_set_mode,
 };
 
 static u64 musb_dmamask = DMA_BIT_MASK(32);
@@ -507,6 +575,7 @@
 
 	config->num_eps = get_int_prop(dn, "mentor,num-eps");
 	config->ram_bits = get_int_prop(dn, "mentor,ram-bits");
+	config->host_port_deassert_reset_at_resume = 1;
 	pdata.mode = get_musb_port_mode(dev);
 	/* DT keeps this entry in mA, musb expects it as per USB spec */
 	pdata.power = get_int_prop(dn, "mentor,power") / 2;
@@ -605,9 +674,12 @@
 	.coreintr_status	= 0x34,
 	.phy_utmi		= 0xe0,
 	.mode			= 0xe8,
+	.tx_mode		= 0x70,
+	.rx_mode		= 0x74,
 	.reset			= 0,
 	.otg_disable		= 21,
 	.iddig			= 8,
+	.iddig_mux		= 7,
 	.usb_shift		= 0,
 	.usb_mask		= 0x1ff,
 	.usb_bitmap		= (0x1ff << 0),
@@ -628,11 +700,52 @@
 };
 MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
 
+#ifdef CONFIG_PM
+static int dsps_suspend(struct device *dev)
+{
+	struct dsps_glue *glue = dev_get_drvdata(dev);
+	const struct dsps_musb_wrapper *wrp = glue->wrp;
+	struct musb *musb = platform_get_drvdata(glue->musb);
+	void __iomem *mbase = musb->ctrl_base;
+
+	glue->context.control = dsps_readl(mbase, wrp->control);
+	glue->context.epintr = dsps_readl(mbase, wrp->epintr_set);
+	glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set);
+	glue->context.phy_utmi = dsps_readl(mbase, wrp->phy_utmi);
+	glue->context.mode = dsps_readl(mbase, wrp->mode);
+	glue->context.tx_mode = dsps_readl(mbase, wrp->tx_mode);
+	glue->context.rx_mode = dsps_readl(mbase, wrp->rx_mode);
+
+	return 0;
+}
+
+static int dsps_resume(struct device *dev)
+{
+	struct dsps_glue *glue = dev_get_drvdata(dev);
+	const struct dsps_musb_wrapper *wrp = glue->wrp;
+	struct musb *musb = platform_get_drvdata(glue->musb);
+	void __iomem *mbase = musb->ctrl_base;
+
+	dsps_writel(mbase, wrp->control, glue->context.control);
+	dsps_writel(mbase, wrp->epintr_set, glue->context.epintr);
+	dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr);
+	dsps_writel(mbase, wrp->phy_utmi, glue->context.phy_utmi);
+	dsps_writel(mbase, wrp->mode, glue->context.mode);
+	dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode);
+	dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
+
 static struct platform_driver dsps_usbss_driver = {
 	.probe		= dsps_probe,
 	.remove         = dsps_remove,
 	.driver         = {
 		.name   = "musb-dsps",
+		.pm	= &dsps_pm_ops,
 		.of_match_table	= musb_dsps_of_match,
 	},
 };
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 32fb057..d4aa779 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1727,14 +1727,14 @@
 	ep->end_point.name = ep->name;
 	INIT_LIST_HEAD(&ep->end_point.ep_list);
 	if (!epnum) {
-		ep->end_point.maxpacket = 64;
+		usb_ep_set_maxpacket_limit(&ep->end_point, 64);
 		ep->end_point.ops = &musb_g_ep0_ops;
 		musb->g.ep0 = &ep->end_point;
 	} else {
 		if (is_in)
-			ep->end_point.maxpacket = hw_ep->max_packet_sz_tx;
+			usb_ep_set_maxpacket_limit(&ep->end_point, hw_ep->max_packet_sz_tx);
 		else
-			ep->end_point.maxpacket = hw_ep->max_packet_sz_rx;
+			usb_ep_set_maxpacket_limit(&ep->end_point, hw_ep->max_packet_sz_rx);
 		ep->end_point.ops = &musb_ep_ops;
 		list_add_tail(&ep->end_point.ep_list, &musb->g.ep_list);
 	}
@@ -2119,7 +2119,15 @@
 	/* Normal reset, as B-Device;
 	 * or else after HNP, as A-Device
 	 */
-	if (devctl & MUSB_DEVCTL_BDEVICE) {
+	if (!musb->g.is_otg) {
+		/* USB device controllers that are not OTG compatible
+		 * may not have DEVCTL register in silicon.
+		 * In that case, do not rely on devctl for setting
+		 * peripheral mode.
+		 */
+		musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+		musb->g.is_a_peripheral = 0;
+	} else if (devctl & MUSB_DEVCTL_BDEVICE) {
 		musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
 		musb->g.is_a_peripheral = 0;
 	} else {
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index e208375..01e7caf 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -2433,6 +2433,8 @@
 	struct musb	*musb = hcd_to_musb(hcd);
 	u8		devctl;
 
+	musb_port_suspend(musb, true);
+
 	if (!is_host_active(musb))
 		return 0;
 
@@ -2462,7 +2464,12 @@
 
 static int musb_bus_resume(struct usb_hcd *hcd)
 {
-	/* resuming child port does the work */
+	struct musb *musb = hcd_to_musb(hcd);
+
+	if (musb->config &&
+	    musb->config->host_port_deassert_reset_at_resume)
+		musb_port_reset(musb, false);
+
 	return 0;
 }
 
diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h
index 960d735..7bbf01b 100644
--- a/drivers/usb/musb/musb_host.h
+++ b/drivers/usb/musb/musb_host.h
@@ -92,6 +92,9 @@
 extern void musb_root_disconnect(struct musb *musb);
 extern void musb_host_resume_root_hub(struct musb *musb);
 extern void musb_host_poke_root_hub(struct musb *musb);
+extern void musb_port_suspend(struct musb *musb, bool do_suspend);
+extern void musb_port_reset(struct musb *musb, bool do_reset);
+extern void musb_host_finish_resume(struct work_struct *work);
 #else
 static inline struct musb *hcd_to_musb(struct usb_hcd *hcd)
 {
@@ -121,6 +124,9 @@
 static inline void musb_host_resume_root_hub(struct musb *musb)	{}
 static inline void musb_host_poll_rh_status(struct musb *musb)	{}
 static inline void musb_host_poke_root_hub(struct musb *musb)	{}
+static inline void musb_port_suspend(struct musb *musb, bool do_suspend) {}
+static inline void musb_port_reset(struct musb *musb, bool do_reset) {}
+static inline void musb_host_finish_resume(struct work_struct *work) {}
 #endif
 
 struct usb_hcd;
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index 9af6bba..966cf95 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -44,7 +44,38 @@
 
 #include "musb_core.h"
 
-static void musb_port_suspend(struct musb *musb, bool do_suspend)
+void musb_host_finish_resume(struct work_struct *work)
+{
+	struct musb *musb;
+	unsigned long flags;
+	u8 power;
+
+	musb = container_of(work, struct musb, finish_resume_work.work);
+
+	spin_lock_irqsave(&musb->lock, flags);
+
+	power = musb_readb(musb->mregs, MUSB_POWER);
+	power &= ~MUSB_POWER_RESUME;
+	dev_dbg(musb->controller, "root port resume stopped, power %02x\n",
+		power);
+	musb_writeb(musb->mregs, MUSB_POWER, power);
+
+	/*
+	 * ISSUE:  DaVinci (RTL 1.300) disconnects after
+	 * resume of high speed peripherals (but not full
+	 * speed ones).
+	 */
+	musb->is_active = 1;
+	musb->port1_status &= ~(USB_PORT_STAT_SUSPEND | MUSB_PORT_STAT_RESUME);
+	musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
+	usb_hcd_poll_rh_status(musb->hcd);
+	/* NOTE: it might really be A_WAIT_BCON ... */
+	musb->xceiv->state = OTG_STATE_A_HOST;
+
+	spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+void musb_port_suspend(struct musb *musb, bool do_suspend)
 {
 	struct usb_otg	*otg = musb->xceiv->otg;
 	u8		power;
@@ -105,11 +136,11 @@
 
 		/* later, GetPortStatus will stop RESUME signaling */
 		musb->port1_status |= MUSB_PORT_STAT_RESUME;
-		musb->rh_timer = jiffies + msecs_to_jiffies(20);
+		schedule_delayed_work(&musb->finish_resume_work, 20);
 	}
 }
 
-static void musb_port_reset(struct musb *musb, bool do_reset)
+void musb_port_reset(struct musb *musb, bool do_reset)
 {
 	u8		power;
 	void __iomem	*mbase = musb->mregs;
@@ -150,7 +181,7 @@
 
 		musb->port1_status |= USB_PORT_STAT_RESET;
 		musb->port1_status &= ~USB_PORT_STAT_ENABLE;
-		musb->rh_timer = jiffies + msecs_to_jiffies(50);
+		schedule_delayed_work(&musb->deassert_reset_work, 50);
 	} else {
 		dev_dbg(musb->controller, "root port reset stopped\n");
 		musb_writeb(mbase, MUSB_POWER,
@@ -325,36 +356,6 @@
 		if (wIndex != 1)
 			goto error;
 
-		/* finish RESET signaling? */
-		if ((musb->port1_status & USB_PORT_STAT_RESET)
-				&& time_after_eq(jiffies, musb->rh_timer))
-			musb_port_reset(musb, false);
-
-		/* finish RESUME signaling? */
-		if ((musb->port1_status & MUSB_PORT_STAT_RESUME)
-				&& time_after_eq(jiffies, musb->rh_timer)) {
-			u8		power;
-
-			power = musb_readb(musb->mregs, MUSB_POWER);
-			power &= ~MUSB_POWER_RESUME;
-			dev_dbg(musb->controller, "root port resume stopped, power %02x\n",
-					power);
-			musb_writeb(musb->mregs, MUSB_POWER, power);
-
-			/* ISSUE:  DaVinci (RTL 1.300) disconnects after
-			 * resume of high speed peripherals (but not full
-			 * speed ones).
-			 */
-
-			musb->is_active = 1;
-			musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
-					| MUSB_PORT_STAT_RESUME);
-			musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
-			usb_hcd_poll_rh_status(musb->hcd);
-			/* NOTE: it might really be A_WAIT_BCON ... */
-			musb->xceiv->state = OTG_STATE_A_HOST;
-		}
-
 		put_unaligned(cpu_to_le32(musb->port1_status
 					& ~MUSB_PORT_STAT_RESUME),
 				(__le32 *) buf);
diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c
index 3700e97..9aad00f 100644
--- a/drivers/usb/musb/ux500_dma.c
+++ b/drivers/usb/musb/ux500_dma.c
@@ -336,7 +336,9 @@
 							    data ?
 							    data->dma_filter :
 							    NULL,
-							    param_array[ch_num]);
+							    param_array ?
+							    param_array[ch_num] :
+							    NULL);
 
 			if (!ux500_channel->dma_chan) {
 				ERR("Dma pipe allocation error dir=%d ch=%d\n",
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 2b41c63..7d1451d 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -6,6 +6,15 @@
 config USB_PHY
 	def_bool n
 
+config USB_OTG_FSM
+	tristate "USB 2.0 OTG FSM implementation"
+	depends on USB
+	select USB_OTG
+	select USB_PHY
+	help
+	  Implements OTG Final State Machine as specified in On-The-Go
+	  and Embedded Host Supplement to the USB Revision 2.0 Specification.
+
 #
 # USB Transceiver Drivers
 #
@@ -19,9 +28,8 @@
 	  in host mode, low speed.
 
 config FSL_USB2_OTG
-	tristate "Freescale USB OTG Transceiver Driver"
-	depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME
-	depends on USB
+	bool "Freescale USB OTG Transceiver Driver"
+	depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM && PM_RUNTIME
 	select USB_OTG
 	select USB_PHY
 	help
@@ -40,7 +48,16 @@
 	  Instruments OMAP processors.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called isp1301_omap.
+	  will be called phy-isp1301-omap.
+
+config KEYSTONE_USB_PHY
+	tristate "Keystone USB PHY Driver"
+	depends on ARCH_KEYSTONE || COMPILE_TEST
+	select NOP_USB_XCEIV
+	help
+	  Enable this to support Keystone USB phy. This driver provides
+	  interface to interact with USB 2.0 and USB 3.0 PHY that is part
+	  of the Keystone SOC.
 
 config MV_U3D_PHY
 	bool "Marvell USB 3.0 PHY controller Driver"
@@ -136,6 +153,31 @@
 	  optionally control of a D+ pullup GPIO as well as a VBUS
 	  current limit regulator.
 
+config OMAP_OTG
+	tristate "OMAP USB OTG controller driver"
+	depends on ARCH_OMAP_OTG && EXTCON
+	help
+	  Enable this to support some transceivers on OMAP1 platforms. OTG
+	  controller is needed to switch between host and peripheral modes.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called phy-omap-otg.
+
+config TAHVO_USB
+	tristate "Tahvo USB transceiver driver"
+	depends on MFD_RETU && EXTCON
+	select USB_PHY
+	help
+	  Enable this to support USB transceiver on Tahvo. This is used
+	  at least on Nokia 770.
+
+config TAHVO_USB_HOST_BY_DEFAULT
+	depends on TAHVO_USB
+	boolean "Device in USB host mode by default"
+	help
+	  Say Y here, if you want the device to enter USB host mode
+	  by default on bootup.
+
 config USB_ISP1301
 	tristate "NXP ISP1301 USB transceiver support"
 	depends on USB || USB_GADGET
@@ -147,7 +189,7 @@
 	  and OTG drivers (to be selected separately).
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called isp1301.
+	  module will be called phy-isp1301.
 
 config USB_MSM_OTG
 	tristate "OTG support for Qualcomm on-chip USB controller"
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index 022c1da..be58ada 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -3,18 +3,20 @@
 #
 obj-$(CONFIG_USB_PHY)			+= phy.o
 obj-$(CONFIG_OF)			+= of.o
+obj-$(CONFIG_USB_OTG_FSM)		+= phy-fsm-usb.o
 
 # transceiver drivers, keep the list sorted
 
 obj-$(CONFIG_AB8500_USB)		+= phy-ab8500-usb.o
-phy-fsl-usb2-objs			:= phy-fsl-usb.o phy-fsm-usb.o
-obj-$(CONFIG_FSL_USB2_OTG)		+= phy-fsl-usb2.o
+obj-$(CONFIG_FSL_USB2_OTG)		+= phy-fsl-usb.o
 obj-$(CONFIG_ISP1301_OMAP)		+= phy-isp1301-omap.o
 obj-$(CONFIG_MV_U3D_PHY)		+= phy-mv-u3d-usb.o
 obj-$(CONFIG_NOP_USB_XCEIV)		+= phy-generic.o
+obj-$(CONFIG_TAHVO_USB)			+= phy-tahvo.o
 obj-$(CONFIG_OMAP_CONTROL_USB)		+= phy-omap-control.o
 obj-$(CONFIG_AM335X_CONTROL_USB)	+= phy-am335x-control.o
 obj-$(CONFIG_AM335X_PHY_USB)		+= phy-am335x.o
+obj-$(CONFIG_OMAP_OTG)			+= phy-omap-otg.o
 obj-$(CONFIG_OMAP_USB3)			+= phy-omap-usb3.o
 obj-$(CONFIG_SAMSUNG_USBPHY)		+= phy-samsung-usb.o
 obj-$(CONFIG_SAMSUNG_USB2PHY)		+= phy-samsung-usb2.o
@@ -30,3 +32,4 @@
 obj-$(CONFIG_USB_RCAR_GEN2_PHY)		+= phy-rcar-gen2-usb.o
 obj-$(CONFIG_USB_ULPI)			+= phy-ulpi.o
 obj-$(CONFIG_USB_ULPI_VIEWPORT)		+= phy-ulpi-viewport.o
+obj-$(CONFIG_KEYSTONE_USB_PHY)		+= phy-keystone.o
diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 0874023..11ab2c4 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -1415,8 +1415,6 @@
 
 	platform_set_drvdata(pdev, ab);
 
-	ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier);
-
 	/* all: Disable phy when called from set_host and set_peripheral */
 	INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work);
 
diff --git a/drivers/usb/phy/phy-am335x-control.c b/drivers/usb/phy/phy-am335x-control.c
index 634f49a..d75196a 100644
--- a/drivers/usb/phy/phy-am335x-control.c
+++ b/drivers/usb/phy/phy-am335x-control.c
@@ -3,11 +3,7 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/io.h>
-
-struct phy_control {
-	void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on);
-	void (*phy_wkup)(struct phy_control *phy_ctrl, u32 id, bool on);
-};
+#include "am35x-phy-control.h"
 
 struct am335x_control_usb {
 	struct device *dev;
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
index 0e3c60c..12fc346 100644
--- a/drivers/usb/phy/phy-am335x.c
+++ b/drivers/usb/phy/phy-am335x.c
@@ -63,6 +63,19 @@
 	am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown;
 
 	platform_set_drvdata(pdev, am_phy);
+	device_init_wakeup(dev, true);
+
+	/*
+	 * If we leave PHY wakeup enabled then AM33XX wakes up
+	 * immediately from DS0. To avoid this we mark dev->power.can_wakeup
+	 * to false. The same is checked in suspend routine to decide
+	 * on whether to enable PHY wakeup or not.
+	 * PHY wakeup works fine in standby mode, there by allowing us to
+	 * handle remote wakeup, wakeup on disconnect and connect.
+	 */
+
+	device_set_wakeup_enable(dev, false);
+	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false);
 
 	return 0;
 }
@@ -75,38 +88,48 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM_RUNTIME
-
-static int am335x_phy_runtime_suspend(struct device *dev)
+#ifdef CONFIG_PM_SLEEP
+static int am335x_phy_suspend(struct device *dev)
 {
 	struct platform_device	*pdev = to_platform_device(dev);
 	struct am335x_phy *am_phy = platform_get_drvdata(pdev);
 
+	/*
+	 * Enable phy wakeup only if dev->power.can_wakeup is true.
+	 * Make sure to enable wakeup to support remote wakeup	in
+	 * standby mode ( same is not supported in OFF(DS0) mode).
+	 * Enable it by doing
+	 * echo enabled > /sys/bus/platform/devices/<usb-phy-id>/power/wakeup
+	 */
+
 	if (device_may_wakeup(dev))
 		phy_ctrl_wkup(am_phy->phy_ctrl, am_phy->id, true);
+
 	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false);
+
 	return 0;
 }
 
-static int am335x_phy_runtime_resume(struct device *dev)
+static int am335x_phy_resume(struct device *dev)
 {
 	struct platform_device	*pdev = to_platform_device(dev);
 	struct am335x_phy	*am_phy = platform_get_drvdata(pdev);
 
 	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, true);
+
 	if (device_may_wakeup(dev))
 		phy_ctrl_wkup(am_phy->phy_ctrl, am_phy->id, false);
+
 	return 0;
 }
 
 static const struct dev_pm_ops am335x_pm_ops = {
-	SET_RUNTIME_PM_OPS(am335x_phy_runtime_suspend,
-			am335x_phy_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(am335x_phy_suspend, am335x_phy_resume)
 };
 
-#define DEV_PM_OPS	(&am335x_pm_ops)
+#define DEV_PM_OPS     (&am335x_pm_ops)
 #else
-#define DEV_PM_OPS	NULL
+#define DEV_PM_OPS     NULL
 #endif
 
 static const struct of_device_id am335x_phy_ids[] = {
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index 7f3c73b..62d5af2 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -848,7 +848,7 @@
 		pr_info("Couldn't init OTG timers\n");
 		goto err;
 	}
-	spin_lock_init(&fsl_otg_tc->fsm.lock);
+	mutex_init(&fsl_otg_tc->fsm.lock);
 
 	/* Set OTG state machine operations */
 	fsl_otg_tc->fsm.ops = &fsl_otg_ops;
@@ -1017,10 +1017,9 @@
 	struct otg_fsm *fsm = &fsl_otg_dev->fsm;
 	char *next = buf;
 	unsigned size = PAGE_SIZE;
-	unsigned long flags;
 	int t;
 
-	spin_lock_irqsave(&fsm->lock, flags);
+	mutex_lock(&fsm->lock);
 
 	/* basic driver infomation */
 	t = scnprintf(next, size,
@@ -1088,7 +1087,7 @@
 	size -= t;
 	next += t;
 
-	spin_unlock_irqrestore(&fsm->lock, flags);
+	mutex_unlock(&fsm->lock);
 
 	return PAGE_SIZE - size;
 }
diff --git a/drivers/usb/phy/phy-fsl-usb.h b/drivers/usb/phy/phy-fsl-usb.h
index 7365170..5986c96 100644
--- a/drivers/usb/phy/phy-fsl-usb.h
+++ b/drivers/usb/phy/phy-fsl-usb.h
@@ -15,7 +15,7 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "phy-fsm-usb.h"
+#include <linux/usb/otg-fsm.h>
 #include <linux/usb/otg.h>
 #include <linux/ioctl.h>
 
diff --git a/drivers/usb/phy/phy-fsm-usb.c b/drivers/usb/phy/phy-fsm-usb.c
index 329c2d2..7aa314e 100644
--- a/drivers/usb/phy/phy-fsm-usb.c
+++ b/drivers/usb/phy/phy-fsm-usb.c
@@ -23,13 +23,12 @@
 
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/usb.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
-
-#include "phy-fsm-usb.h"
+#include <linux/usb/otg-fsm.h>
 
 /* Change USB protocol when there is a protocol change */
 static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
@@ -65,7 +64,7 @@
 static int state_changed;
 
 /* Called when leaving a state.  Do state clean up jobs here */
-void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
+static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
 {
 	switch (old_state) {
 	case OTG_STATE_B_IDLE:
@@ -122,7 +121,7 @@
 }
 
 /* Called when entering a state */
-int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
+static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
 {
 	state_changed = 1;
 	if (fsm->otg->phy->state == new_state)
@@ -245,9 +244,8 @@
 int otg_statemachine(struct otg_fsm *fsm)
 {
 	enum usb_otg_state state;
-	unsigned long flags;
 
-	spin_lock_irqsave(&fsm->lock, flags);
+	mutex_lock(&fsm->lock);
 
 	state = fsm->otg->phy->state;
 	state_changed = 0;
@@ -359,7 +357,7 @@
 	default:
 		break;
 	}
-	spin_unlock_irqrestore(&fsm->lock, flags);
+	mutex_unlock(&fsm->lock);
 
 	VDBG("quit statemachine, changed = %d\n", state_changed);
 	return state_changed;
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index aa6d37b..bb39498 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -241,7 +241,6 @@
 	nop->phy.otg->set_host		= nop_set_host;
 	nop->phy.otg->set_peripheral	= nop_set_peripheral;
 
-	ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index 02799a5..69462e0 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -314,8 +314,6 @@
 		goto err_irq;
 	}
 
-	ATOMIC_INIT_NOTIFIER_HEAD(&gpio_vbus->phy.notifier);
-
 	INIT_DELAYED_WORK(&gpio_vbus->work, gpio_vbus_work);
 
 	gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw");
diff --git a/drivers/usb/phy/phy-isp1301-omap.c b/drivers/usb/phy/phy-isp1301-omap.c
index d3a5160..6e146d7 100644
--- a/drivers/usb/phy/phy-isp1301-omap.c
+++ b/drivers/usb/phy/phy-isp1301-omap.c
@@ -1277,7 +1277,7 @@
 {
 	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
 
-	if (!otg || isp != the_transceiver)
+	if (isp != the_transceiver)
 		return -ENODEV;
 
 	if (!host) {
@@ -1333,7 +1333,7 @@
 {
 	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
 
-	if (!otg || isp != the_transceiver)
+	if (isp != the_transceiver)
 		return -ENODEV;
 
 	if (!gadget) {
@@ -1414,8 +1414,7 @@
 	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
 	u32		otg_ctrl;
 
-	if (!otg || isp != the_transceiver
-			|| isp->phy.state != OTG_STATE_B_IDLE)
+	if (isp != the_transceiver || isp->phy.state != OTG_STATE_B_IDLE)
 		return -ENODEV;
 
 	otg_ctrl = omap_readl(OTG_CTRL);
@@ -1442,7 +1441,7 @@
 	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
 	u32 l;
 
-	if (!otg || isp != the_transceiver)
+	if (isp != the_transceiver)
 		return -ENODEV;
 	if (otg->default_a && (otg->host == NULL || !otg->host->b_hnp_enable))
 		return -ENOTCONN;
diff --git a/drivers/usb/phy/phy-keystone.c b/drivers/usb/phy/phy-keystone.c
new file mode 100644
index 0000000..d762003
--- /dev/null
+++ b/drivers/usb/phy/phy-keystone.c
@@ -0,0 +1,136 @@
+/*
+ * phy-keystone - USB PHY, talking to dwc3 controller in Keystone.
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ * 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.
+ *
+ * Author: WingMan Kwok <w-kwok2@ti.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include "phy-generic.h"
+
+/* USB PHY control register offsets */
+#define USB_PHY_CTL_UTMI		0x0000
+#define USB_PHY_CTL_PIPE		0x0004
+#define USB_PHY_CTL_PARAM_1		0x0008
+#define USB_PHY_CTL_PARAM_2		0x000c
+#define USB_PHY_CTL_CLOCK		0x0010
+#define USB_PHY_CTL_PLL			0x0014
+
+#define PHY_REF_SSP_EN			BIT(29)
+
+struct keystone_usbphy {
+	struct usb_phy_gen_xceiv	usb_phy_gen;
+	void __iomem			*phy_ctrl;
+};
+
+static inline u32 keystone_usbphy_readl(void __iomem *base, u32 offset)
+{
+	return readl(base + offset);
+}
+
+static inline void keystone_usbphy_writel(void __iomem *base,
+					  u32 offset, u32 value)
+{
+	writel(value, base + offset);
+}
+
+static int keystone_usbphy_init(struct usb_phy *phy)
+{
+	struct keystone_usbphy *k_phy = dev_get_drvdata(phy->dev);
+	u32 val;
+
+	val  = keystone_usbphy_readl(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK);
+	keystone_usbphy_writel(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK,
+				val | PHY_REF_SSP_EN);
+	return 0;
+}
+
+static void keystone_usbphy_shutdown(struct usb_phy *phy)
+{
+	struct keystone_usbphy *k_phy = dev_get_drvdata(phy->dev);
+	u32 val;
+
+	val  = keystone_usbphy_readl(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK);
+	keystone_usbphy_writel(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK,
+				val &= ~PHY_REF_SSP_EN);
+}
+
+static int keystone_usbphy_probe(struct platform_device *pdev)
+{
+	struct device		*dev = &pdev->dev;
+	struct keystone_usbphy	*k_phy;
+	struct resource		*res;
+	int ret;
+
+	k_phy = devm_kzalloc(dev, sizeof(*k_phy), GFP_KERNEL);
+	if (!k_phy)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	k_phy->phy_ctrl = devm_ioremap_resource(dev, res);
+	if (IS_ERR(k_phy->phy_ctrl))
+		return PTR_ERR(k_phy->phy_ctrl);
+
+	ret = usb_phy_gen_create_phy(dev, &k_phy->usb_phy_gen, NULL);
+	if (ret)
+		return ret;
+
+	k_phy->usb_phy_gen.phy.init = keystone_usbphy_init;
+	k_phy->usb_phy_gen.phy.shutdown = keystone_usbphy_shutdown;
+
+	platform_set_drvdata(pdev, k_phy);
+
+	ret = usb_add_phy_dev(&k_phy->usb_phy_gen.phy);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int keystone_usbphy_remove(struct platform_device *pdev)
+{
+	struct keystone_usbphy *k_phy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&k_phy->usb_phy_gen.phy);
+
+	return 0;
+}
+
+static const struct of_device_id keystone_usbphy_ids[] = {
+	{ .compatible = "ti,keystone-usbphy" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, keystone_usbphy_ids);
+
+static struct platform_driver keystone_usbphy_driver = {
+	.probe          = keystone_usbphy_probe,
+	.remove         = keystone_usbphy_remove,
+	.driver         = {
+		.name   = "keystone-usbphy",
+		.owner  = THIS_MODULE,
+		.of_match_table = keystone_usbphy_ids,
+	},
+};
+
+module_platform_driver(keystone_usbphy_driver);
+
+MODULE_ALIAS("platform:keystone-usbphy");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("Keystone USB phy driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index 545844b..b42897b 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -63,9 +63,13 @@
 
 static int mxs_phy_init(struct usb_phy *phy)
 {
+	int ret;
 	struct mxs_phy *mxs_phy = to_mxs_phy(phy);
 
-	clk_prepare_enable(mxs_phy->clk);
+	ret = clk_prepare_enable(mxs_phy->clk);
+	if (ret)
+		return ret;
+
 	return mxs_phy_hw_init(mxs_phy);
 }
 
@@ -81,6 +85,7 @@
 
 static int mxs_phy_suspend(struct usb_phy *x, int suspend)
 {
+	int ret;
 	struct mxs_phy *mxs_phy = to_mxs_phy(x);
 
 	if (suspend) {
@@ -89,7 +94,9 @@
 		       x->io_priv + HW_USBPHY_CTRL_SET);
 		clk_disable_unprepare(mxs_phy->clk);
 	} else {
-		clk_prepare_enable(mxs_phy->clk);
+		ret = clk_prepare_enable(mxs_phy->clk);
+		if (ret)
+			return ret;
 		writel(BM_USBPHY_CTRL_CLKGATE,
 		       x->io_priv + HW_USBPHY_CTRL_CLR);
 		writel(0, x->io_priv + HW_USBPHY_PWD);
@@ -160,8 +167,6 @@
 	mxs_phy->phy.notify_disconnect	= mxs_phy_on_disconnect;
 	mxs_phy->phy.type		= USB_PHY_TYPE_USB2;
 
-	ATOMIC_INIT_NOTIFIER_HEAD(&mxs_phy->phy.notifier);
-
 	mxs_phy->clk = clk;
 
 	platform_set_drvdata(pdev, mxs_phy);
diff --git a/drivers/usb/phy/phy-omap-control.c b/drivers/usb/phy/phy-omap-control.c
index 09c5ace..e725318 100644
--- a/drivers/usb/phy/phy-omap-control.c
+++ b/drivers/usb/phy/phy-omap-control.c
@@ -84,6 +84,20 @@
 		else
 			val |= OMAP_CTRL_USB2_PHY_PD;
 		break;
+
+	case OMAP_CTRL_TYPE_AM437USB2:
+		if (on) {
+			val &= ~(AM437X_CTRL_USB2_PHY_PD |
+					AM437X_CTRL_USB2_OTG_PD);
+			val |= (AM437X_CTRL_USB2_OTGVDET_EN |
+					AM437X_CTRL_USB2_OTGSESSEND_EN);
+		} else {
+			val &= ~(AM437X_CTRL_USB2_OTGVDET_EN |
+					AM437X_CTRL_USB2_OTGSESSEND_EN);
+			val |= (AM437X_CTRL_USB2_PHY_PD |
+					 AM437X_CTRL_USB2_OTG_PD);
+		}
+		break;
 	default:
 		dev_err(dev, "%s: type %d not recognized\n",
 					__func__, control_usb->type);
@@ -197,6 +211,7 @@
 static const enum omap_control_usb_type usb2_data = OMAP_CTRL_TYPE_USB2;
 static const enum omap_control_usb_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
 static const enum omap_control_usb_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2;
+static const enum omap_control_usb_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2;
 
 static const struct of_device_id omap_control_usb_id_table[] = {
 	{
@@ -215,6 +230,10 @@
 		.compatible = "ti,control-phy-dra7usb2",
 		.data = &dra7usb2_data,
 	},
+	{
+		.compatible = "ti,control-phy-am437usb2",
+		.data = &am437usb2_data,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
diff --git a/drivers/usb/phy/phy-omap-otg.c b/drivers/usb/phy/phy-omap-otg.c
new file mode 100644
index 0000000..11598cd
--- /dev/null
+++ b/drivers/usb/phy/phy-omap-otg.c
@@ -0,0 +1,169 @@
+/*
+ * OMAP OTG controller driver
+ *
+ * Based on code from tahvo-usb.c and isp1301_omap.c drivers.
+ *
+ * Copyright (C) 2005-2006 Nokia Corporation
+ * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2004 David Brownell
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * 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/io.h>
+#include <linux/err.h>
+#include <linux/extcon.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/usb-omap1.h>
+
+struct otg_device {
+	void __iomem			*base;
+	bool				id;
+	bool				vbus;
+	struct extcon_specific_cable_nb	vbus_dev;
+	struct extcon_specific_cable_nb	id_dev;
+	struct notifier_block		vbus_nb;
+	struct notifier_block		id_nb;
+};
+
+#define OMAP_OTG_CTRL		0x0c
+#define OMAP_OTG_ASESSVLD	(1 << 20)
+#define OMAP_OTG_BSESSEND	(1 << 19)
+#define OMAP_OTG_BSESSVLD	(1 << 18)
+#define OMAP_OTG_VBUSVLD	(1 << 17)
+#define OMAP_OTG_ID		(1 << 16)
+#define OMAP_OTG_XCEIV_OUTPUTS \
+	(OMAP_OTG_ASESSVLD | OMAP_OTG_BSESSEND | OMAP_OTG_BSESSVLD | \
+	 OMAP_OTG_VBUSVLD  | OMAP_OTG_ID)
+
+static void omap_otg_ctrl(struct otg_device *otg_dev, u32 outputs)
+{
+	u32 l;
+
+	l = readl(otg_dev->base + OMAP_OTG_CTRL);
+	l &= ~OMAP_OTG_XCEIV_OUTPUTS;
+	l |= outputs;
+	writel(l, otg_dev->base + OMAP_OTG_CTRL);
+}
+
+static void omap_otg_set_mode(struct otg_device *otg_dev)
+{
+	if (!otg_dev->id && otg_dev->vbus)
+		/* Set B-session valid. */
+		omap_otg_ctrl(otg_dev, OMAP_OTG_ID | OMAP_OTG_BSESSVLD);
+	else if (otg_dev->vbus)
+		/* Set A-session valid. */
+		omap_otg_ctrl(otg_dev, OMAP_OTG_ASESSVLD);
+	else if (!otg_dev->id)
+		/* Set B-session end to indicate no VBUS. */
+		omap_otg_ctrl(otg_dev, OMAP_OTG_ID | OMAP_OTG_BSESSEND);
+}
+
+static int omap_otg_id_notifier(struct notifier_block *nb,
+				unsigned long event, void *ptr)
+{
+	struct otg_device *otg_dev = container_of(nb, struct otg_device, id_nb);
+
+	otg_dev->id = event;
+	omap_otg_set_mode(otg_dev);
+
+	return NOTIFY_DONE;
+}
+
+static int omap_otg_vbus_notifier(struct notifier_block *nb,
+				  unsigned long event, void *ptr)
+{
+	struct otg_device *otg_dev = container_of(nb, struct otg_device,
+						  vbus_nb);
+
+	otg_dev->vbus = event;
+	omap_otg_set_mode(otg_dev);
+
+	return NOTIFY_DONE;
+}
+
+static int omap_otg_probe(struct platform_device *pdev)
+{
+	const struct omap_usb_config *config = pdev->dev.platform_data;
+	struct otg_device *otg_dev;
+	struct extcon_dev *extcon;
+	int ret;
+	u32 rev;
+
+	if (!config || !config->extcon)
+		return -ENODEV;
+
+	extcon = extcon_get_extcon_dev(config->extcon);
+	if (!extcon)
+		return -EPROBE_DEFER;
+
+	otg_dev = devm_kzalloc(&pdev->dev, sizeof(*otg_dev), GFP_KERNEL);
+	if (!otg_dev)
+		return -ENOMEM;
+
+	otg_dev->base = devm_ioremap_resource(&pdev->dev, &pdev->resource[0]);
+	if (IS_ERR(otg_dev->base))
+		return PTR_ERR(otg_dev->base);
+
+	otg_dev->id_nb.notifier_call = omap_otg_id_notifier;
+	otg_dev->vbus_nb.notifier_call = omap_otg_vbus_notifier;
+
+	ret = extcon_register_interest(&otg_dev->id_dev, config->extcon,
+				       "USB-HOST", &otg_dev->id_nb);
+	if (ret)
+		return ret;
+
+	ret = extcon_register_interest(&otg_dev->vbus_dev, config->extcon,
+				       "USB", &otg_dev->vbus_nb);
+	if (ret) {
+		extcon_unregister_interest(&otg_dev->id_dev);
+		return ret;
+	}
+
+	otg_dev->id = extcon_get_cable_state(extcon, "USB-HOST");
+	otg_dev->vbus = extcon_get_cable_state(extcon, "USB");
+	omap_otg_set_mode(otg_dev);
+
+	rev = readl(otg_dev->base);
+
+	dev_info(&pdev->dev,
+		 "OMAP USB OTG controller rev %d.%d (%s, id=%d, vbus=%d)\n",
+		 (rev >> 4) & 0xf, rev & 0xf, config->extcon, otg_dev->id,
+		 otg_dev->vbus);
+
+	return 0;
+}
+
+static int omap_otg_remove(struct platform_device *pdev)
+{
+	struct otg_device *otg_dev = platform_get_drvdata(pdev);
+
+	extcon_unregister_interest(&otg_dev->id_dev);
+	extcon_unregister_interest(&otg_dev->vbus_dev);
+
+	return 0;
+}
+
+static struct platform_driver omap_otg_driver = {
+	.probe		= omap_otg_probe,
+	.remove		= omap_otg_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "omap_otg",
+	},
+};
+module_platform_driver(omap_otg_driver);
+
+MODULE_DESCRIPTION("OMAP USB OTG controller driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
diff --git a/drivers/usb/phy/phy-rcar-gen2-usb.c b/drivers/usb/phy/phy-rcar-gen2-usb.c
index db3ab34..551e0a6 100644
--- a/drivers/usb/phy/phy-rcar-gen2-usb.c
+++ b/drivers/usb/phy/phy-rcar-gen2-usb.c
@@ -213,7 +213,7 @@
 	priv->phy.shutdown = rcar_gen2_usb_phy_shutdown;
 	priv->phy.set_suspend = rcar_gen2_usb_phy_set_suspend;
 
-	retval = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2);
+	retval = usb_add_phy_dev(&priv->phy);
 	if (retval < 0) {
 		dev_err(dev, "Failed to add USB phy\n");
 		return retval;
diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c
new file mode 100644
index 0000000..cc61ee4
--- /dev/null
+++ b/drivers/usb/phy/phy-tahvo.c
@@ -0,0 +1,457 @@
+/*
+ * Tahvo USB transceiver driver
+ *
+ * Copyright (C) 2005-2006 Nokia Corporation
+ *
+ * Parts copied from isp1301_omap.c.
+ * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2004 David Brownell
+ *
+ * Original driver written by Juha Yrjölä, Tony Lindgren and Timo Teräs.
+ * Modified for Retu/Tahvo MFD by Aaro Koskinen.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * 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/io.h>
+#include <linux/clk.h>
+#include <linux/usb.h>
+#include <linux/extcon.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb/otg.h>
+#include <linux/mfd/retu.h>
+#include <linux/usb/gadget.h>
+#include <linux/platform_device.h>
+
+#define DRIVER_NAME     "tahvo-usb"
+
+#define TAHVO_REG_IDSR	0x02
+#define TAHVO_REG_USBR	0x06
+
+#define USBR_SLAVE_CONTROL	(1 << 8)
+#define USBR_VPPVIO_SW		(1 << 7)
+#define USBR_SPEED		(1 << 6)
+#define USBR_REGOUT		(1 << 5)
+#define USBR_MASTER_SW2		(1 << 4)
+#define USBR_MASTER_SW1		(1 << 3)
+#define USBR_SLAVE_SW		(1 << 2)
+#define USBR_NSUSPEND		(1 << 1)
+#define USBR_SEMODE		(1 << 0)
+
+#define TAHVO_MODE_HOST		0
+#define TAHVO_MODE_PERIPHERAL	1
+
+struct tahvo_usb {
+	struct platform_device	*pt_dev;
+	struct usb_phy		phy;
+	int			vbus_state;
+	struct mutex		serialize;
+	struct clk		*ick;
+	int			irq;
+	int			tahvo_mode;
+	struct extcon_dev	extcon;
+};
+
+static const char *tahvo_cable[] = {
+	"USB-HOST",
+	"USB",
+	NULL,
+};
+
+static ssize_t vbus_state_show(struct device *device,
+			       struct device_attribute *attr, char *buf)
+{
+	struct tahvo_usb *tu = dev_get_drvdata(device);
+	return sprintf(buf, "%s\n", tu->vbus_state ? "on" : "off");
+}
+static DEVICE_ATTR(vbus, 0444, vbus_state_show, NULL);
+
+static void check_vbus_state(struct tahvo_usb *tu)
+{
+	struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
+	int reg, prev_state;
+
+	reg = retu_read(rdev, TAHVO_REG_IDSR);
+	if (reg & TAHVO_STAT_VBUS) {
+		switch (tu->phy.state) {
+		case OTG_STATE_B_IDLE:
+			/* Enable the gadget driver */
+			if (tu->phy.otg->gadget)
+				usb_gadget_vbus_connect(tu->phy.otg->gadget);
+			tu->phy.state = OTG_STATE_B_PERIPHERAL;
+			break;
+		case OTG_STATE_A_IDLE:
+			/*
+			 * Session is now valid assuming the USB hub is driving
+			 * Vbus.
+			 */
+			tu->phy.state = OTG_STATE_A_HOST;
+			break;
+		default:
+			break;
+		}
+		dev_info(&tu->pt_dev->dev, "USB cable connected\n");
+	} else {
+		switch (tu->phy.state) {
+		case OTG_STATE_B_PERIPHERAL:
+			if (tu->phy.otg->gadget)
+				usb_gadget_vbus_disconnect(tu->phy.otg->gadget);
+			tu->phy.state = OTG_STATE_B_IDLE;
+			break;
+		case OTG_STATE_A_HOST:
+			tu->phy.state = OTG_STATE_A_IDLE;
+			break;
+		default:
+			break;
+		}
+		dev_info(&tu->pt_dev->dev, "USB cable disconnected\n");
+	}
+
+	prev_state = tu->vbus_state;
+	tu->vbus_state = reg & TAHVO_STAT_VBUS;
+	if (prev_state != tu->vbus_state) {
+		extcon_set_cable_state(&tu->extcon, "USB", tu->vbus_state);
+		sysfs_notify(&tu->pt_dev->dev.kobj, NULL, "vbus_state");
+	}
+}
+
+static void tahvo_usb_become_host(struct tahvo_usb *tu)
+{
+	struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
+
+	extcon_set_cable_state(&tu->extcon, "USB-HOST", true);
+
+	/* Power up the transceiver in USB host mode */
+	retu_write(rdev, TAHVO_REG_USBR, USBR_REGOUT | USBR_NSUSPEND |
+		   USBR_MASTER_SW2 | USBR_MASTER_SW1);
+	tu->phy.state = OTG_STATE_A_IDLE;
+
+	check_vbus_state(tu);
+}
+
+static void tahvo_usb_stop_host(struct tahvo_usb *tu)
+{
+	tu->phy.state = OTG_STATE_A_IDLE;
+}
+
+static void tahvo_usb_become_peripheral(struct tahvo_usb *tu)
+{
+	struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
+
+	extcon_set_cable_state(&tu->extcon, "USB-HOST", false);
+
+	/* Power up transceiver and set it in USB peripheral mode */
+	retu_write(rdev, TAHVO_REG_USBR, USBR_SLAVE_CONTROL | USBR_REGOUT |
+		   USBR_NSUSPEND | USBR_SLAVE_SW);
+	tu->phy.state = OTG_STATE_B_IDLE;
+
+	check_vbus_state(tu);
+}
+
+static void tahvo_usb_stop_peripheral(struct tahvo_usb *tu)
+{
+	if (tu->phy.otg->gadget)
+		usb_gadget_vbus_disconnect(tu->phy.otg->gadget);
+	tu->phy.state = OTG_STATE_B_IDLE;
+}
+
+static void tahvo_usb_power_off(struct tahvo_usb *tu)
+{
+	struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
+
+	/* Disable gadget controller if any */
+	if (tu->phy.otg->gadget)
+		usb_gadget_vbus_disconnect(tu->phy.otg->gadget);
+
+	/* Power off transceiver */
+	retu_write(rdev, TAHVO_REG_USBR, 0);
+	tu->phy.state = OTG_STATE_UNDEFINED;
+}
+
+static int tahvo_usb_set_suspend(struct usb_phy *dev, int suspend)
+{
+	struct tahvo_usb *tu = container_of(dev, struct tahvo_usb, phy);
+	struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
+	u16 w;
+
+	dev_dbg(&tu->pt_dev->dev, "%s\n", __func__);
+
+	w = retu_read(rdev, TAHVO_REG_USBR);
+	if (suspend)
+		w &= ~USBR_NSUSPEND;
+	else
+		w |= USBR_NSUSPEND;
+	retu_write(rdev, TAHVO_REG_USBR, w);
+
+	return 0;
+}
+
+static int tahvo_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	struct tahvo_usb *tu = container_of(otg->phy, struct tahvo_usb, phy);
+
+	dev_dbg(&tu->pt_dev->dev, "%s %p\n", __func__, host);
+
+	mutex_lock(&tu->serialize);
+
+	if (host == NULL) {
+		if (tu->tahvo_mode == TAHVO_MODE_HOST)
+			tahvo_usb_power_off(tu);
+		otg->host = NULL;
+		mutex_unlock(&tu->serialize);
+		return 0;
+	}
+
+	if (tu->tahvo_mode == TAHVO_MODE_HOST) {
+		otg->host = NULL;
+		tahvo_usb_become_host(tu);
+	}
+
+	otg->host = host;
+
+	mutex_unlock(&tu->serialize);
+
+	return 0;
+}
+
+static int tahvo_usb_set_peripheral(struct usb_otg *otg,
+				    struct usb_gadget *gadget)
+{
+	struct tahvo_usb *tu = container_of(otg->phy, struct tahvo_usb, phy);
+
+	dev_dbg(&tu->pt_dev->dev, "%s %p\n", __func__, gadget);
+
+	mutex_lock(&tu->serialize);
+
+	if (!gadget) {
+		if (tu->tahvo_mode == TAHVO_MODE_PERIPHERAL)
+			tahvo_usb_power_off(tu);
+		tu->phy.otg->gadget = NULL;
+		mutex_unlock(&tu->serialize);
+		return 0;
+	}
+
+	tu->phy.otg->gadget = gadget;
+	if (tu->tahvo_mode == TAHVO_MODE_PERIPHERAL)
+		tahvo_usb_become_peripheral(tu);
+
+	mutex_unlock(&tu->serialize);
+
+	return 0;
+}
+
+static irqreturn_t tahvo_usb_vbus_interrupt(int irq, void *_tu)
+{
+	struct tahvo_usb *tu = _tu;
+
+	mutex_lock(&tu->serialize);
+	check_vbus_state(tu);
+	mutex_unlock(&tu->serialize);
+
+	return IRQ_HANDLED;
+}
+
+static ssize_t otg_mode_show(struct device *device,
+			     struct device_attribute *attr, char *buf)
+{
+	struct tahvo_usb *tu = dev_get_drvdata(device);
+
+	switch (tu->tahvo_mode) {
+	case TAHVO_MODE_HOST:
+		return sprintf(buf, "host\n");
+	case TAHVO_MODE_PERIPHERAL:
+		return sprintf(buf, "peripheral\n");
+	}
+
+	return -EINVAL;
+}
+
+static ssize_t otg_mode_store(struct device *device,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct tahvo_usb *tu = dev_get_drvdata(device);
+	int r;
+
+	mutex_lock(&tu->serialize);
+	if (count >= 4 && strncmp(buf, "host", 4) == 0) {
+		if (tu->tahvo_mode == TAHVO_MODE_PERIPHERAL)
+			tahvo_usb_stop_peripheral(tu);
+		tu->tahvo_mode = TAHVO_MODE_HOST;
+		if (tu->phy.otg->host) {
+			dev_info(device, "HOST mode: host controller present\n");
+			tahvo_usb_become_host(tu);
+		} else {
+			dev_info(device, "HOST mode: no host controller, powering off\n");
+			tahvo_usb_power_off(tu);
+		}
+		r = strlen(buf);
+	} else if (count >= 10 && strncmp(buf, "peripheral", 10) == 0) {
+		if (tu->tahvo_mode == TAHVO_MODE_HOST)
+			tahvo_usb_stop_host(tu);
+		tu->tahvo_mode = TAHVO_MODE_PERIPHERAL;
+		if (tu->phy.otg->gadget) {
+			dev_info(device, "PERIPHERAL mode: gadget driver present\n");
+			tahvo_usb_become_peripheral(tu);
+		} else {
+			dev_info(device, "PERIPHERAL mode: no gadget driver, powering off\n");
+			tahvo_usb_power_off(tu);
+		}
+		r = strlen(buf);
+	} else {
+		r = -EINVAL;
+	}
+	mutex_unlock(&tu->serialize);
+
+	return r;
+}
+static DEVICE_ATTR(otg_mode, 0644, otg_mode_show, otg_mode_store);
+
+static struct attribute *tahvo_attributes[] = {
+	&dev_attr_vbus.attr,
+	&dev_attr_otg_mode.attr,
+	NULL
+};
+
+static struct attribute_group tahvo_attr_group = {
+	.attrs = tahvo_attributes,
+};
+
+static int tahvo_usb_probe(struct platform_device *pdev)
+{
+	struct retu_dev *rdev = dev_get_drvdata(pdev->dev.parent);
+	struct tahvo_usb *tu;
+	int ret;
+
+	tu = devm_kzalloc(&pdev->dev, sizeof(*tu), GFP_KERNEL);
+	if (!tu)
+		return -ENOMEM;
+
+	tu->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*tu->phy.otg),
+				   GFP_KERNEL);
+	if (!tu->phy.otg)
+		return -ENOMEM;
+
+	tu->pt_dev = pdev;
+
+	/* Default mode */
+#ifdef CONFIG_TAHVO_USB_HOST_BY_DEFAULT
+	tu->tahvo_mode = TAHVO_MODE_HOST;
+#else
+	tu->tahvo_mode = TAHVO_MODE_PERIPHERAL;
+#endif
+
+	mutex_init(&tu->serialize);
+
+	tu->ick = devm_clk_get(&pdev->dev, "usb_l4_ick");
+	if (!IS_ERR(tu->ick))
+		clk_enable(tu->ick);
+
+	/*
+	 * Set initial state, so that we generate kevents only on state changes.
+	 */
+	tu->vbus_state = retu_read(rdev, TAHVO_REG_IDSR) & TAHVO_STAT_VBUS;
+
+	tu->extcon.name = DRIVER_NAME;
+	tu->extcon.supported_cable = tahvo_cable;
+	tu->extcon.dev.parent = &pdev->dev;
+
+	ret = extcon_dev_register(&tu->extcon);
+	if (ret) {
+		dev_err(&pdev->dev, "could not register extcon device: %d\n",
+			ret);
+		goto err_disable_clk;
+	}
+
+	/* Set the initial cable state. */
+	extcon_set_cable_state(&tu->extcon, "USB-HOST",
+			       tu->tahvo_mode == TAHVO_MODE_HOST);
+	extcon_set_cable_state(&tu->extcon, "USB", tu->vbus_state);
+
+	/* Create OTG interface */
+	tahvo_usb_power_off(tu);
+	tu->phy.dev = &pdev->dev;
+	tu->phy.state = OTG_STATE_UNDEFINED;
+	tu->phy.label = DRIVER_NAME;
+	tu->phy.set_suspend = tahvo_usb_set_suspend;
+
+	tu->phy.otg->phy = &tu->phy;
+	tu->phy.otg->set_host = tahvo_usb_set_host;
+	tu->phy.otg->set_peripheral = tahvo_usb_set_peripheral;
+
+	ret = usb_add_phy(&tu->phy, USB_PHY_TYPE_USB2);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "cannot register USB transceiver: %d\n",
+			ret);
+		goto err_extcon_unreg;
+	}
+
+	dev_set_drvdata(&pdev->dev, tu);
+
+	tu->irq = platform_get_irq(pdev, 0);
+	ret = request_threaded_irq(tu->irq, NULL, tahvo_usb_vbus_interrupt, 0,
+				   "tahvo-vbus", tu);
+	if (ret) {
+		dev_err(&pdev->dev, "could not register tahvo-vbus irq: %d\n",
+			ret);
+		goto err_remove_phy;
+	}
+
+	/* Attributes */
+	ret = sysfs_create_group(&pdev->dev.kobj, &tahvo_attr_group);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot create sysfs group: %d\n", ret);
+		goto err_free_irq;
+	}
+
+	return 0;
+
+err_free_irq:
+	free_irq(tu->irq, tu);
+err_remove_phy:
+	usb_remove_phy(&tu->phy);
+err_extcon_unreg:
+	extcon_dev_unregister(&tu->extcon);
+err_disable_clk:
+	if (!IS_ERR(tu->ick))
+		clk_disable(tu->ick);
+
+	return ret;
+}
+
+static int tahvo_usb_remove(struct platform_device *pdev)
+{
+	struct tahvo_usb *tu = platform_get_drvdata(pdev);
+
+	sysfs_remove_group(&pdev->dev.kobj, &tahvo_attr_group);
+	free_irq(tu->irq, tu);
+	usb_remove_phy(&tu->phy);
+	extcon_dev_unregister(&tu->extcon);
+	if (!IS_ERR(tu->ick))
+		clk_disable(tu->ick);
+
+	return 0;
+}
+
+static struct platform_driver tahvo_usb_driver = {
+	.probe		= tahvo_usb_probe,
+	.remove		= tahvo_usb_remove,
+	.driver		= {
+		.name	= "tahvo-usb",
+		.owner	= THIS_MODULE,
+	},
+};
+module_platform_driver(tahvo_usb_driver);
+
+MODULE_DESCRIPTION("Tahvo USB transceiver driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Juha Yrjölä, Tony Lindgren, and Timo Teräs");
+MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index bad57ce..214172b 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -328,7 +328,7 @@
 	struct device		*dev = &pdev->dev;
 	struct twl4030_usb_data	*pdata = dev_get_platdata(dev);
 
-	twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL);
+	twl = devm_kzalloc(dev, sizeof(*twl), GFP_KERNEL);
 	if (!twl)
 		return -ENOMEM;
 
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c
index 1b74523..e6f61e4 100644
--- a/drivers/usb/phy/phy.c
+++ b/drivers/usb/phy/phy.c
@@ -329,6 +329,8 @@
 		return -EINVAL;
 	}
 
+	ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier);
+
 	spin_lock_irqsave(&phy_lock, flags);
 
 	list_for_each_entry(phy, &phy_list, head) {
@@ -367,6 +369,8 @@
 		return -EINVAL;
 	}
 
+	ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier);
+
 	spin_lock_irqsave(&phy_lock, flags);
 	list_for_each_entry(phy_bind, &phy_bind_list, list)
 		if (!(strcmp(phy_bind->phy_dev_name, dev_name(x->dev))))
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 45b9401..d49f9c3 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -1124,19 +1124,8 @@
 	mod->irq_brdysts	= 0;
 
 	cfifo->pipe	= NULL;
-	cfifo->tx_chan	= NULL;
-	cfifo->rx_chan	= NULL;
-
 	d0fifo->pipe	= NULL;
-	d0fifo->tx_chan	= NULL;
-	d0fifo->rx_chan	= NULL;
-
 	d1fifo->pipe	= NULL;
-	d1fifo->tx_chan	= NULL;
-	d1fifo->rx_chan	= NULL;
-
-	usbhsf_dma_init(priv, usbhsf_get_d0fifo(priv));
-	usbhsf_dma_init(priv, usbhsf_get_d1fifo(priv));
 }
 
 void usbhs_fifo_quit(struct usbhs_priv *priv)
@@ -1147,9 +1136,6 @@
 	mod->irq_ready		= NULL;
 	mod->irq_bempsts	= 0;
 	mod->irq_brdysts	= 0;
-
-	usbhsf_dma_quit(priv, usbhsf_get_d0fifo(priv));
-	usbhsf_dma_quit(priv, usbhsf_get_d1fifo(priv));
 }
 
 int usbhs_fifo_probe(struct usbhs_priv *priv)
@@ -1171,6 +1157,7 @@
 	fifo->ctr	= D0FIFOCTR;
 	fifo->tx_slave.shdma_slave.slave_id	= usbhs_get_dparam(priv, d0_tx_id);
 	fifo->rx_slave.shdma_slave.slave_id	= usbhs_get_dparam(priv, d0_rx_id);
+	usbhsf_dma_init(priv, fifo);
 
 	/* D1FIFO */
 	fifo = usbhsf_get_d1fifo(priv);
@@ -1180,10 +1167,13 @@
 	fifo->ctr	= D1FIFOCTR;
 	fifo->tx_slave.shdma_slave.slave_id	= usbhs_get_dparam(priv, d1_tx_id);
 	fifo->rx_slave.shdma_slave.slave_id	= usbhs_get_dparam(priv, d1_rx_id);
+	usbhsf_dma_init(priv, fifo);
 
 	return 0;
 }
 
 void usbhs_fifo_remove(struct usbhs_priv *priv)
 {
+	usbhsf_dma_quit(priv, usbhsf_get_d0fifo(priv));
+	usbhsf_dma_quit(priv, usbhsf_get_d1fifo(priv));
 }
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 3385aeb..458f376 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -987,11 +987,11 @@
 		/* init DCP */
 		if (usbhsg_is_dcp(uep)) {
 			gpriv->gadget.ep0 = &uep->ep;
-			uep->ep.maxpacket = 64;
+			usb_ep_set_maxpacket_limit(&uep->ep, 64);
 		}
 		/* init normal pipe */
 		else {
-			uep->ep.maxpacket = 512;
+			usb_ep_set_maxpacket_limit(&uep->ep, 512);
 			list_add_tail(&uep->ep.ep_list, &gpriv->gadget.ep_list);
 		}
 	}
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 6d72269..e273e5a 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -38,6 +38,14 @@
 };
 
 /**
+ * struct phy_attrs - represents phy attributes
+ * @bus_width: Data path width implemented by PHY
+ */
+struct phy_attrs {
+	u32			bus_width;
+};
+
+/**
  * struct phy - represents the phy device
  * @dev: phy device
  * @id: id of the phy device
@@ -46,6 +54,7 @@
  * @mutex: mutex to protect phy_ops
  * @init_count: used to protect when the PHY is used by multiple consumers
  * @power_count: used to protect when the PHY is used by multiple consumers
+ * @phy_attrs: used to specify PHY specific attributes
  */
 struct phy {
 	struct device		dev;
@@ -55,6 +64,7 @@
 	struct mutex		mutex;
 	int			init_count;
 	int			power_count;
+	struct phy_attrs	attrs;
 };
 
 /**
@@ -127,6 +137,14 @@
 int phy_exit(struct phy *phy);
 int phy_power_on(struct phy *phy);
 int phy_power_off(struct phy *phy);
+static inline int phy_get_bus_width(struct phy *phy)
+{
+	return phy->attrs.bus_width;
+}
+static inline void phy_set_bus_width(struct phy *phy, int bus_width)
+{
+	phy->attrs.bus_width = bus_width;
+}
 struct phy *phy_get(struct device *dev, const char *string);
 struct phy *devm_phy_get(struct device *dev, const char *string);
 void phy_put(struct phy *phy);
@@ -199,6 +217,16 @@
 	return -ENOSYS;
 }
 
+static inline int phy_get_bus_width(struct phy *phy)
+{
+	return -ENOSYS;
+}
+
+static inline void phy_set_bus_width(struct phy *phy, int bus_width)
+{
+	return;
+}
+
 static inline struct phy *phy_get(struct device *dev, const char *string)
 {
 	return ERR_PTR(-ENOSYS);
diff --git a/include/linux/platform_data/usb-omap1.h b/include/linux/platform_data/usb-omap1.h
new file mode 100644
index 0000000..43b5ce1
--- /dev/null
+++ b/include/linux/platform_data/usb-omap1.h
@@ -0,0 +1,53 @@
+/*
+ * Platform data for OMAP1 USB
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive for
+ * more details.
+ */
+#ifndef __LINUX_USB_OMAP1_H
+#define __LINUX_USB_OMAP1_H
+
+#include <linux/platform_device.h>
+
+struct omap_usb_config {
+	/* Configure drivers according to the connectors on your board:
+	 *  - "A" connector (rectagular)
+	 *	... for host/OHCI use, set "register_host".
+	 *  - "B" connector (squarish) or "Mini-B"
+	 *	... for device/gadget use, set "register_dev".
+	 *  - "Mini-AB" connector (very similar to Mini-B)
+	 *	... for OTG use as device OR host, initialize "otg"
+	 */
+	unsigned	register_host:1;
+	unsigned	register_dev:1;
+	u8		otg;	/* port number, 1-based:  usb1 == 2 */
+
+	const char	*extcon;	/* extcon device for OTG */
+
+	u8		hmc_mode;
+
+	/* implicitly true if otg:  host supports remote wakeup? */
+	u8		rwc;
+
+	/* signaling pins used to talk to transceiver on usbN:
+	 *  0 == usbN unused
+	 *  2 == usb0-only, using internal transceiver
+	 *  3 == 3 wire bidirectional
+	 *  4 == 4 wire bidirectional
+	 *  6 == 6 wire unidirectional (or TLL)
+	 */
+	u8		pins[3];
+
+	struct platform_device *udc_device;
+	struct platform_device *ohci_device;
+	struct platform_device *otg_device;
+
+	u32 (*usb0_init)(unsigned nwires, unsigned is_device);
+	u32 (*usb1_init)(unsigned nwires);
+	u32 (*usb2_init)(unsigned nwires, unsigned alt_pingroup);
+
+	int (*ocpi_enable)(void);
+};
+
+#endif /* __LINUX_USB_OMAP1_H */
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 5e61589..dba63f5 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -468,6 +468,8 @@
 	struct config_group group;
 	struct list_head cfs_list;
 	struct usb_function_driver *fd;
+	int (*set_inst_name)(struct usb_function_instance *inst,
+			      const char *name);
 	void (*free_func_inst)(struct usb_function_instance *inst);
 };
 
diff --git a/include/linux/usb/functionfs.h b/include/linux/usb/functionfs.h
index 65d0a88..7119066 100644
--- a/include/linux/usb/functionfs.h
+++ b/include/linux/usb/functionfs.h
@@ -3,34 +3,4 @@
 
 #include <uapi/linux/usb/functionfs.h>
 
-
-struct ffs_data;
-struct usb_composite_dev;
-struct usb_configuration;
-
-
-static int  functionfs_init(void) __attribute__((warn_unused_result));
-static void functionfs_cleanup(void);
-
-static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
-	__attribute__((warn_unused_result, nonnull));
-static void functionfs_unbind(struct ffs_data *ffs)
-	__attribute__((nonnull));
-
-static int functionfs_bind_config(struct usb_composite_dev *cdev,
-				  struct usb_configuration *c,
-				  struct ffs_data *ffs)
-	__attribute__((warn_unused_result, nonnull));
-
-
-static int functionfs_ready_callback(struct ffs_data *ffs)
-	__attribute__((warn_unused_result, nonnull));
-static void functionfs_closed_callback(struct ffs_data *ffs)
-	__attribute__((nonnull));
-static void *functionfs_acquire_dev_callback(const char *dev_name)
-	__attribute__((warn_unused_result, nonnull));
-static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
-	__attribute__((nonnull));
-
-
 #endif
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 942ef5e..c3a6185 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -148,6 +148,9 @@
  * @maxpacket:The maximum packet size used on this endpoint.  The initial
  *	value can sometimes be reduced (hardware allowing), according to
  *      the endpoint descriptor used to configure the endpoint.
+ * @maxpacket_limit:The maximum packet size value which can be handled by this
+ *	endpoint. It's set once by UDC driver when endpoint is initialized, and
+ *	should not be changed. Should not be confused with maxpacket.
  * @max_streams: The maximum number of streams supported
  *	by this EP (0 - 16, actual number is 2^n)
  * @mult: multiplier, 'mult' value for SS Isoc EPs
@@ -171,6 +174,7 @@
 	const struct usb_ep_ops	*ops;
 	struct list_head	ep_list;
 	unsigned		maxpacket:16;
+	unsigned		maxpacket_limit:16;
 	unsigned		max_streams:16;
 	unsigned		mult:2;
 	unsigned		maxburst:5;
@@ -182,6 +186,21 @@
 /*-------------------------------------------------------------------------*/
 
 /**
+ * usb_ep_set_maxpacket_limit - set maximum packet size limit for endpoint
+ * @ep:the endpoint being configured
+ * @maxpacket_limit:value of maximum packet size limit
+ *
+ * This function shoud be used only in UDC drivers to initialize endpoint
+ * (usually in probe function).
+ */
+static inline void usb_ep_set_maxpacket_limit(struct usb_ep *ep,
+					      unsigned maxpacket_limit)
+{
+	ep->maxpacket_limit = maxpacket_limit;
+	ep->maxpacket = maxpacket_limit;
+}
+
+/**
  * usb_ep_enable - configure endpoint, making it usable
  * @ep:the endpoint being configured.  may not be the endpoint named "ep0".
  *	drivers discover endpoints through the ep_list of a usb_gadget.
@@ -485,6 +504,11 @@
  * @max_speed: Maximal speed the UDC can handle.  UDC must support this
  *      and all slower speeds.
  * @state: the state we are now (attached, suspended, configured, etc)
+ * @name: Identifies the controller hardware type.  Used in diagnostics
+ *	and sometimes configuration.
+ * @dev: Driver model state for this abstract device.
+ * @out_epnum: last used out ep number
+ * @in_epnum: last used in ep number
  * @sg_supported: true if we can handle scatter-gather
  * @is_otg: True if the USB device port uses a Mini-AB jack, so that the
  *	gadget driver must provide a USB OTG descriptor.
@@ -497,11 +521,8 @@
  *	only supports HNP on a different root port.
  * @b_hnp_enable: OTG device feature flag, indicating that the A-Host
  *	enabled HNP support.
- * @name: Identifies the controller hardware type.  Used in diagnostics
- *	and sometimes configuration.
- * @dev: Driver model state for this abstract device.
- * @out_epnum: last used out ep number
- * @in_epnum: last used in ep number
+ * @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to
+ *	MaxPacketSize.
  *
  * Gadgets have a mostly-portable "gadget driver" implementing device
  * functions, handling all usb configurations and interfaces.  Gadget
@@ -530,16 +551,18 @@
 	enum usb_device_speed		speed;
 	enum usb_device_speed		max_speed;
 	enum usb_device_state		state;
+	const char			*name;
+	struct device			dev;
+	unsigned			out_epnum;
+	unsigned			in_epnum;
+
 	unsigned			sg_supported:1;
 	unsigned			is_otg:1;
 	unsigned			is_a_peripheral:1;
 	unsigned			b_hnp_enable:1;
 	unsigned			a_hnp_support:1;
 	unsigned			a_alt_hnp_support:1;
-	const char			*name;
-	struct device			dev;
-	unsigned			out_epnum;
-	unsigned			in_epnum;
+	unsigned			quirk_ep_out_aligned_size:1;
 };
 #define work_to_gadget(w)	(container_of((w), struct usb_gadget, work))
 
@@ -558,6 +581,23 @@
 
 
 /**
+ * usb_ep_align_maybe - returns @len aligned to ep's maxpacketsize if gadget
+ *	requires quirk_ep_out_aligned_size, otherwise reguens len.
+ * @g: controller to check for quirk
+ * @ep: the endpoint whose maxpacketsize is used to align @len
+ * @len: buffer size's length to align to @ep's maxpacketsize
+ *
+ * This helper is used in case it's required for any reason to check and maybe
+ * align buffer's size to an ep's maxpacketsize.
+ */
+static inline size_t
+usb_ep_align_maybe(struct usb_gadget *g, struct usb_ep *ep, size_t len)
+{
+	return !g->quirk_ep_out_aligned_size ? len :
+			round_up(len, (size_t)ep->desc->wMaxPacketSize);
+}
+
+/**
  * gadget_is_dualspeed - return true iff the hardware handles high speed
  * @g: controller that might support both high and full speeds
  */
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
index eb50525..a4ee1b5 100644
--- a/include/linux/usb/musb.h
+++ b/include/linux/usb/musb.h
@@ -76,6 +76,9 @@
 	unsigned	dma:1 __deprecated; /* supports DMA */
 	unsigned	vendor_req:1 __deprecated; /* vendor registers required */
 
+	/* need to explicitly de-assert the port reset after resume? */
+	unsigned	host_port_deassert_reset_at_resume:1;
+
 	u8		num_eps;	/* number of endpoints _with_ ep0 */
 	u8		dma_channels __deprecated; /* number of dma channels */
 	u8		dyn_fifo_size;	/* dynamic size in bytes */
diff --git a/include/linux/usb/omap_control_usb.h b/include/linux/usb/omap_control_usb.h
index 596b019..69ae383 100644
--- a/include/linux/usb/omap_control_usb.h
+++ b/include/linux/usb/omap_control_usb.h
@@ -24,6 +24,7 @@
 	OMAP_CTRL_TYPE_USB2,	/* USB2_PHY, power down in CONTROL_DEV_CONF */
 	OMAP_CTRL_TYPE_PIPE3,	/* PIPE3 PHY, DPLL & seperate Rx/Tx power */
 	OMAP_CTRL_TYPE_DRA7USB2, /* USB2 PHY, power and power_aux e.g. DRA7 */
+	OMAP_CTRL_TYPE_AM437USB2, /* USB2 PHY, power e.g. AM437x */
 };
 
 struct omap_control_usb {
@@ -64,6 +65,11 @@
 
 #define OMAP_CTRL_USB2_PHY_PD		BIT(28)
 
+#define AM437X_CTRL_USB2_PHY_PD		BIT(0)
+#define AM437X_CTRL_USB2_OTG_PD		BIT(1)
+#define AM437X_CTRL_USB2_OTGVDET_EN	BIT(19)
+#define AM437X_CTRL_USB2_OTGSESSEND_EN	BIT(20)
+
 #if IS_ENABLED(CONFIG_OMAP_CONTROL_USB)
 extern void omap_control_usb_phy_power(struct device *dev, int on);
 extern void omap_control_usb_set_mode(struct device *dev,
diff --git a/drivers/usb/phy/phy-fsm-usb.h b/include/linux/usb/otg-fsm.h
similarity index 95%
rename from drivers/usb/phy/phy-fsm-usb.h
rename to include/linux/usb/otg-fsm.h
index 7441b46..b6ba1bf 100644
--- a/drivers/usb/phy/phy-fsm-usb.h
+++ b/include/linux/usb/otg-fsm.h
@@ -15,6 +15,12 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#ifndef __LINUX_USB_OTG_FSM_H
+#define __LINUX_USB_OTG_FSM_H
+
+#include <linux/mutex.h>
+#include <linux/errno.h>
+
 #undef VERBOSE
 
 #ifdef VERBOSE
@@ -110,7 +116,7 @@
 
 	/* Current usb protocol used: 0:undefine; 1:host; 2:client */
 	int protocol;
-	spinlock_t lock;
+	struct mutex lock;
 };
 
 struct otg_fsm_ops {
@@ -234,3 +240,5 @@
 }
 
 int otg_statemachine(struct otg_fsm *fsm);
+
+#endif /* __LINUX_USB_OTG_FSM_H */