Merge tag 'usb-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB merge for 3.4-rc1 from Greg KH:
 "Here's the big USB merge for the 3.4-rc1 merge window.

  Lots of gadget driver reworks here, driver updates, xhci changes, some
  new drivers added, usb-serial core reworking to fix some bugs, and
  other various minor things.

  There are some patches touching arch code, but they have all been
  acked by the various arch maintainers."

* tag 'usb-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (302 commits)
  net: qmi_wwan: add support for ZTE MF820D
  USB: option: add ZTE MF820D
  usb: gadget: f_fs: Remove lock is held before freeing checks
  USB: option: make interface blacklist work again
  usb/ub: deprecate & schedule for removal the "Low Performance USB Block" driver
  USB: ohci-pxa27x: add clk_prepare/clk_unprepare calls
  USB: use generic platform driver on ath79
  USB: EHCI: Add a generic platform device driver
  USB: OHCI: Add a generic platform device driver
  USB: ftdi_sio: new PID: LUMEL PD12
  USB: ftdi_sio: add support for FT-X series devices
  USB: serial: mos7840: Fixed MCS7820 device attach problem
  usb: Don't make USB_ARCH_HAS_{XHCI,OHCI,EHCI} depend on USB_SUPPORT.
  usb gadget: fix a section mismatch when compiling g_ffs with CONFIG_USB_FUNCTIONFS_ETH
  USB: ohci-nxp: Remove i2c_write(), use smbus
  USB: ohci-nxp: Support for LPC32xx
  USB: ohci-nxp: Rename symbols from pnx4008 to nxp
  USB: OHCI-HCD: Rename ohci-pnx4008 to ohci-nxp
  usb: gadget: Kconfig: fix typo for 'different'
  usb: dwc3: pci: fix another failure path in dwc3_pci_probe()
  ...
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index b4f5487..7c22a532 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -182,3 +182,14 @@
 		USB2 hardware LPM is enabled for the device. Developer can
 		write y/Y/1 or n/N/0 to the file to enable/disable the
 		feature.
+
+What:		/sys/bus/usb/devices/.../removable
+Date:		February 2012
+Contact:	Matthew Garrett <mjg@redhat.com>
+Description:
+		Some information about whether a given USB device is
+		physically fixed to the platform can be inferred from a
+		combination of hub decriptor bits and platform-specific data
+		such as ACPI. This file will read either "removable" or
+		"fixed" if the information is available, and "unknown"
+		otherwise.
\ No newline at end of file
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index a0ffac0..d5dc80f 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -524,3 +524,14 @@
 Why:	The code is not actively maintained and platforms are now hard to find.
 Who:	Nicolas Ferre <nicolas.ferre@atmel.com>
 	Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+----------------------------
+
+What:	Low Performance USB Block driver ("CONFIG_BLK_DEV_UB")
+When:	3.6
+Why:	This driver provides support for USB storage devices like "USB
+	sticks". As of now, it is deactivated in Debian, Fedora and
+        Ubuntu. All current users can switch over to usb-storage
+        (CONFIG_USB_STORAGE) which only drawback is the additional SCSI
+        stack.
+Who:	Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices
index 9edb75d..abf6361 100644
--- a/Documentation/i2c/instantiating-devices
+++ b/Documentation/i2c/instantiating-devices
@@ -87,11 +87,11 @@
 changing its design without notice). In this case, you can call
 i2c_new_probed_device() instead of i2c_new_device().
 
-Example (from the pnx4008 OHCI driver):
+Example (from the nxp OHCI driver):
 
 static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
 
-static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
+static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev)
 {
 	(...)
 	struct i2c_adapter *i2c_adap;
@@ -100,7 +100,7 @@
 	(...)
 	i2c_adap = i2c_get_adapter(2);
 	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
-	strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE);
+	strlcpy(i2c_info.type, "isp1301_nxp", I2C_NAME_SIZE);
 	isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
 						   normal_i2c, NULL);
 	i2c_put_adapter(i2c_adap);
diff --git a/arch/arm/mach-imx/mx31moboard-devboard.c b/arch/arm/mach-imx/mx31moboard-devboard.c
index 0aa2536..cc285e5 100644
--- a/arch/arm/mach-imx/mx31moboard-devboard.c
+++ b/arch/arm/mach-imx/mx31moboard-devboard.c
@@ -158,7 +158,7 @@
 #define USBH1_VBUSEN_B	IOMUX_TO_GPIO(MX31_PIN_NFRE_B)
 #define USBH1_MODE	IOMUX_TO_GPIO(MX31_PIN_NFALE)
 
-static int devboard_isp1105_init(struct otg_transceiver *otg)
+static int devboard_isp1105_init(struct usb_phy *otg)
 {
 	int ret = gpio_request(USBH1_MODE, "usbh1-mode");
 	if (ret)
@@ -177,7 +177,7 @@
 }
 
 
-static int devboard_isp1105_set_vbus(struct otg_transceiver *otg, bool on)
+static int devboard_isp1105_set_vbus(struct usb_otg *otg, bool on)
 {
 	if (on)
 		gpio_set_value(USBH1_VBUSEN_B, 0);
@@ -194,18 +194,24 @@
 
 static int __init devboard_usbh1_init(void)
 {
-	struct otg_transceiver *otg;
+	struct usb_phy *phy;
 	struct platform_device *pdev;
 
-	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
-	if (!otg)
+	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
+	if (!phy)
 		return -ENOMEM;
 
-	otg->label	= "ISP1105";
-	otg->init	= devboard_isp1105_init;
-	otg->set_vbus	= devboard_isp1105_set_vbus;
+	phy->otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
+	if (!phy->otg) {
+		kfree(phy);
+		return -ENOMEM;
+	}
 
-	usbh1_pdata.otg = otg;
+	phy->label	= "ISP1105";
+	phy->init	= devboard_isp1105_init;
+	phy->otg->set_vbus	= devboard_isp1105_set_vbus;
+
+	usbh1_pdata.otg = phy;
 
 	pdev = imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
 	if (IS_ERR(pdev))
diff --git a/arch/arm/mach-imx/mx31moboard-marxbot.c b/arch/arm/mach-imx/mx31moboard-marxbot.c
index bb639cb..135c90e 100644
--- a/arch/arm/mach-imx/mx31moboard-marxbot.c
+++ b/arch/arm/mach-imx/mx31moboard-marxbot.c
@@ -272,7 +272,7 @@
 #define USBH1_VBUSEN_B	IOMUX_TO_GPIO(MX31_PIN_NFRE_B)
 #define USBH1_MODE	IOMUX_TO_GPIO(MX31_PIN_NFALE)
 
-static int marxbot_isp1105_init(struct otg_transceiver *otg)
+static int marxbot_isp1105_init(struct usb_phy *otg)
 {
 	int ret = gpio_request(USBH1_MODE, "usbh1-mode");
 	if (ret)
@@ -291,7 +291,7 @@
 }
 
 
-static int marxbot_isp1105_set_vbus(struct otg_transceiver *otg, bool on)
+static int marxbot_isp1105_set_vbus(struct usb_otg *otg, bool on)
 {
 	if (on)
 		gpio_set_value(USBH1_VBUSEN_B, 0);
@@ -308,18 +308,24 @@
 
 static int __init marxbot_usbh1_init(void)
 {
-	struct otg_transceiver *otg;
+	struct usb_phy *phy;
 	struct platform_device *pdev;
 
-	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
-	if (!otg)
+	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
+	if (!phy)
 		return -ENOMEM;
 
-	otg->label	= "ISP1105";
-	otg->init	= marxbot_isp1105_init;
-	otg->set_vbus	= marxbot_isp1105_set_vbus;
+	phy->otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
+	if (!phy->otg) {
+		kfree(phy);
+		return -ENOMEM;
+	}
 
-	usbh1_pdata.otg = otg;
+	phy->label	= "ISP1105";
+	phy->init	= marxbot_isp1105_init;
+	phy->otg->set_vbus	= marxbot_isp1105_set_vbus;
+
+	usbh1_pdata.otg = phy;
 
 	pdev = imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
 	if (IS_ERR(pdev))
diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c
index e28dfb88..5ead6d4 100644
--- a/arch/arm/mach-pxa/pxa3xx-ulpi.c
+++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c
@@ -33,7 +33,7 @@
 	struct clk		*clk;
 	void __iomem		*mmio_base;
 
-	struct otg_transceiver	*otg;
+	struct usb_phy		*otg;
 	unsigned int		ulpi_mode;
 };
 
@@ -79,7 +79,7 @@
 	return -ETIMEDOUT;
 }
 
-static int pxa310_ulpi_read(struct otg_transceiver *otg, u32 reg)
+static int pxa310_ulpi_read(struct usb_phy *otg, u32 reg)
 {
 	int err;
 
@@ -98,7 +98,7 @@
 	return u2d_readl(U2DOTGUCR) & U2DOTGUCR_RDATA;
 }
 
-static int pxa310_ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
+static int pxa310_ulpi_write(struct usb_phy *otg, u32 val, u32 reg)
 {
 	if (pxa310_ulpi_get_phymode() != SYNCH) {
 		pr_warning("%s: PHY is not in SYNCH mode!\n", __func__);
@@ -111,7 +111,7 @@
 	return pxa310_ulpi_poll();
 }
 
-struct otg_io_access_ops pxa310_ulpi_access_ops = {
+struct usb_phy_io_ops pxa310_ulpi_access_ops = {
 	.read	= pxa310_ulpi_read,
 	.write	= pxa310_ulpi_write,
 };
@@ -139,19 +139,19 @@
 
 	pxa310_otg_transceiver_rtsm();
 
-	err = otg_init(u2d->otg);
+	err = usb_phy_init(u2d->otg);
 	if (err) {
 		pr_err("OTG transceiver init failed");
 		return err;
 	}
 
-	err = otg_set_vbus(u2d->otg, 1);
+	err = otg_set_vbus(u2d->otg->otg, 1);
 	if (err) {
 		pr_err("OTG transceiver VBUS set failed");
 		return err;
 	}
 
-	err = otg_set_host(u2d->otg, host);
+	err = otg_set_host(u2d->otg->otg, host);
 	if (err)
 		pr_err("OTG transceiver Host mode set failed");
 
@@ -189,9 +189,9 @@
 {
 	pxa310_otg_transceiver_rtsm();
 
-	otg_set_host(u2d->otg, NULL);
-	otg_set_vbus(u2d->otg, 0);
-	otg_shutdown(u2d->otg);
+	otg_set_host(u2d->otg->otg, NULL);
+	otg_set_vbus(u2d->otg->otg, 0);
+	usb_phy_shutdown(u2d->otg);
 }
 
 static void pxa310_u2d_setup_otg_hc(void)
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h
index d4b8f9e..de1a0f6 100644
--- a/arch/arm/mach-tegra/include/mach/usb_phy.h
+++ b/arch/arm/mach-tegra/include/mach/usb_phy.h
@@ -58,7 +58,7 @@
 	struct clk *pad_clk;
 	enum tegra_usb_phy_mode mode;
 	void *config;
-	struct otg_transceiver *ulpi;
+	struct usb_phy *ulpi;
 };
 
 struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index 37576a7..ad321f9 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -608,13 +608,13 @@
 	writel(val, base + ULPI_TIMING_CTRL_1);
 
 	/* Fix VbusInvalid due to floating VBUS */
-	ret = otg_io_write(phy->ulpi, 0x40, 0x08);
+	ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08);
 	if (ret) {
 		pr_err("%s: ulpi write failed\n", __func__);
 		return ret;
 	}
 
-	ret = otg_io_write(phy->ulpi, 0x80, 0x0B);
+	ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B);
 	if (ret) {
 		pr_err("%s: ulpi write failed\n", __func__);
 		return ret;
diff --git a/arch/arm/plat-mxc/include/mach/mxc_ehci.h b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
index 2c159dc..9ffd1bb 100644
--- a/arch/arm/plat-mxc/include/mach/mxc_ehci.h
+++ b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
@@ -44,7 +44,7 @@
 	int (*exit)(struct platform_device *pdev);
 
 	unsigned int		 portsc;
-	struct otg_transceiver	*otg;
+	struct usb_phy		*otg;
 };
 
 int mx51_initialize_usb_hw(int port, unsigned int flags);
diff --git a/arch/arm/plat-mxc/include/mach/ulpi.h b/arch/arm/plat-mxc/include/mach/ulpi.h
index f9161c9..42bdaca 100644
--- a/arch/arm/plat-mxc/include/mach/ulpi.h
+++ b/arch/arm/plat-mxc/include/mach/ulpi.h
@@ -2,15 +2,15 @@
 #define __MACH_ULPI_H
 
 #ifdef CONFIG_USB_ULPI
-struct otg_transceiver *imx_otg_ulpi_create(unsigned int flags);
+struct usb_phy *imx_otg_ulpi_create(unsigned int flags);
 #else
-static inline struct otg_transceiver *imx_otg_ulpi_create(unsigned int flags)
+static inline struct usb_phy *imx_otg_ulpi_create(unsigned int flags)
 {
 	return NULL;
 }
 #endif
 
-extern struct otg_io_access_ops mxc_ulpi_access_ops;
+extern struct usb_phy_io_ops mxc_ulpi_access_ops;
 
 #endif /* __MACH_ULPI_H */
 
diff --git a/arch/arm/plat-mxc/ulpi.c b/arch/arm/plat-mxc/ulpi.c
index 477e45b..d296342 100644
--- a/arch/arm/plat-mxc/ulpi.c
+++ b/arch/arm/plat-mxc/ulpi.c
@@ -58,7 +58,7 @@
 	return -ETIMEDOUT;
 }
 
-static int ulpi_read(struct otg_transceiver *otg, u32 reg)
+static int ulpi_read(struct usb_phy *otg, u32 reg)
 {
 	int ret;
 	void __iomem *view = otg->io_priv;
@@ -84,7 +84,7 @@
 	return (__raw_readl(view) >> ULPIVW_RDATA_SHIFT) & ULPIVW_RDATA_MASK;
 }
 
-static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
+static int ulpi_write(struct usb_phy *otg, u32 val, u32 reg)
 {
 	int ret;
 	void __iomem *view = otg->io_priv;
@@ -106,13 +106,13 @@
 	return ulpi_poll(view, ULPIVW_RUN);
 }
 
-struct otg_io_access_ops mxc_ulpi_access_ops = {
+struct usb_phy_io_ops mxc_ulpi_access_ops = {
 	.read	= ulpi_read,
 	.write	= ulpi_write,
 };
 EXPORT_SYMBOL_GPL(mxc_ulpi_access_ops);
 
-struct otg_transceiver *imx_otg_ulpi_create(unsigned int flags)
+struct usb_phy *imx_otg_ulpi_create(unsigned int flags)
 {
 	return otg_ulpi_create(&mxc_ulpi_access_ops, flags);
 }
diff --git a/arch/mips/ath79/dev-usb.c b/arch/mips/ath79/dev-usb.c
index 002d6d2..36e9570 100644
--- a/arch/mips/ath79/dev-usb.c
+++ b/arch/mips/ath79/dev-usb.c
@@ -17,6 +17,8 @@
 #include <linux/irq.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
 
 #include <asm/mach-ath79/ath79.h>
 #include <asm/mach-ath79/ar71xx_regs.h>
@@ -36,14 +38,19 @@
 };
 
 static u64 ath79_ohci_dmamask = DMA_BIT_MASK(32);
+
+static struct usb_ohci_pdata ath79_ohci_pdata = {
+};
+
 static struct platform_device ath79_ohci_device = {
-	.name		= "ath79-ohci",
+	.name		= "ohci-platform",
 	.id		= -1,
 	.resource	= ath79_ohci_resources,
 	.num_resources	= ARRAY_SIZE(ath79_ohci_resources),
 	.dev = {
 		.dma_mask		= &ath79_ohci_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &ath79_ohci_pdata,
 	},
 };
 
@@ -60,8 +67,20 @@
 };
 
 static u64 ath79_ehci_dmamask = DMA_BIT_MASK(32);
+
+static struct usb_ehci_pdata ath79_ehci_pdata_v1 = {
+	.has_synopsys_hc_bug	= 1,
+	.port_power_off		= 1,
+};
+
+static struct usb_ehci_pdata ath79_ehci_pdata_v2 = {
+	.caps_offset		= 0x100,
+	.has_tt			= 1,
+	.port_power_off		= 1,
+};
+
 static struct platform_device ath79_ehci_device = {
-	.name		= "ath79-ehci",
+	.name		= "ehci-platform",
 	.id		= -1,
 	.resource	= ath79_ehci_resources,
 	.num_resources	= ARRAY_SIZE(ath79_ehci_resources),
@@ -101,7 +120,7 @@
 
 	ath79_ehci_resources[0].start = AR71XX_EHCI_BASE;
 	ath79_ehci_resources[0].end = AR71XX_EHCI_BASE + AR71XX_EHCI_SIZE - 1;
-	ath79_ehci_device.name = "ar71xx-ehci";
+	ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v1;
 	platform_device_register(&ath79_ehci_device);
 }
 
@@ -142,7 +161,7 @@
 
 	ath79_ehci_resources[0].start = AR724X_EHCI_BASE;
 	ath79_ehci_resources[0].end = AR724X_EHCI_BASE + AR724X_EHCI_SIZE - 1;
-	ath79_ehci_device.name = "ar724x-ehci";
+	ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2;
 	platform_device_register(&ath79_ehci_device);
 }
 
@@ -159,7 +178,7 @@
 
 	ath79_ehci_resources[0].start = AR913X_EHCI_BASE;
 	ath79_ehci_resources[0].end = AR913X_EHCI_BASE + AR913X_EHCI_SIZE - 1;
-	ath79_ehci_device.name = "ar913x-ehci";
+	ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2;
 	platform_device_register(&ath79_ehci_device);
 }
 
@@ -176,7 +195,7 @@
 
 	ath79_ehci_resources[0].start = AR933X_EHCI_BASE;
 	ath79_ehci_resources[0].end = AR933X_EHCI_BASE + AR933X_EHCI_SIZE - 1;
-	ath79_ehci_device.name = "ar933x-ehci";
+	ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2;
 	platform_device_register(&ath79_ehci_device);
 }
 
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 4e4c8a4..a796407 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -354,7 +354,7 @@
 	  Use devices /dev/sx8/$N and /dev/sx8/$Np$M.
 
 config BLK_DEV_UB
-	tristate "Low Performance USB Block driver"
+	tristate "Low Performance USB Block driver (deprecated)"
 	depends on USB
 	help
 	  This driver supports certain USB attached storage devices
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 7333b9e..fcec022 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -119,43 +119,6 @@
 
 /*
  */
-
-/* command block wrapper */
-struct bulk_cb_wrap {
-	__le32	Signature;		/* contains 'USBC' */
-	u32	Tag;			/* unique per command id */
-	__le32	DataTransferLength;	/* size of data */
-	u8	Flags;			/* direction in bit 0 */
-	u8	Lun;			/* LUN */
-	u8	Length;			/* of of the CDB */
-	u8	CDB[UB_MAX_CDB_SIZE];	/* max command */
-};
-
-#define US_BULK_CB_WRAP_LEN	31
-#define US_BULK_CB_SIGN		0x43425355	/*spells out USBC */
-#define US_BULK_FLAG_IN		1
-#define US_BULK_FLAG_OUT	0
-
-/* command status wrapper */
-struct bulk_cs_wrap {
-	__le32	Signature;		/* should = 'USBS' */
-	u32	Tag;			/* same as original command */
-	__le32	Residue;		/* amount not transferred */
-	u8	Status;			/* see below */
-};
-
-#define US_BULK_CS_WRAP_LEN	13
-#define US_BULK_CS_SIGN		0x53425355	/* spells out 'USBS' */
-#define US_BULK_STAT_OK		0
-#define US_BULK_STAT_FAIL	1
-#define US_BULK_STAT_PHASE	2
-
-/* bulk-only class specific requests */
-#define US_BULK_RESET_REQUEST	0xff
-#define US_BULK_GET_MAX_LUN	0xfe
-
-/*
- */
 struct ub_dev;
 
 #define UB_MAX_REQ_SG	9	/* cdrecord requires 32KB and maybe a header */
@@ -2477,6 +2440,8 @@
 	int rc;
 	int i;
 
+	pr_info("'Low Performance USB Block' driver is deprecated. "
+			"Please switch to usb-storage\n");
 	for (i = 0; i < UB_QLOCK_NUM; i++)
 		spin_lock_init(&ub_qlockv[i]);
 
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 2335761..4bad899 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -398,6 +398,27 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called kalmia.
 
+config USB_NET_QMI_WWAN
+	tristate "QMI WWAN driver for Qualcomm MSM based 3G and LTE modems"
+	depends on USB_USBNET
+	help
+	  Support WWAN LTE/3G devices based on Qualcomm Mobile Data Modem
+	  (MDM) chipsets.  Examples of such devices are
+	    * Huawei E392/E398
+
+	  This driver will only drive the ethernet part of the chips.
+	  The devices require additional configuration to be usable.
+	  Multiple management interfaces with linux drivers are
+	  available:
+
+	    * option: AT commands on /dev/ttyUSBx
+	    * cdc-wdm: Qualcomm MSM Interface (QMI) protocol on /dev/cdc-wdmx
+
+	  A modem manager with support for QMI is recommended.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called qmi_wwan.
+
 config USB_HSO
 	tristate "Option USB High Speed Mobile Devices"
 	depends on USB && RFKILL
@@ -461,4 +482,5 @@
 
 	  http://ubuntuforums.org/showpost.php?p=10589647&postcount=17
 
+
 endmenu
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile
index c203fa2..a2e2d72 100644
--- a/drivers/net/usb/Makefile
+++ b/drivers/net/usb/Makefile
@@ -29,4 +29,5 @@
 obj-$(CONFIG_USB_NET_CX82310_ETH)	+= cx82310_eth.o
 obj-$(CONFIG_USB_NET_CDC_NCM)	+= cdc_ncm.o
 obj-$(CONFIG_USB_VL600)		+= lg-vl600.o
+obj-$(CONFIG_USB_NET_QMI_WWAN)	+= qmi_wwan.o
 
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
new file mode 100644
index 0000000..aac68f5
--- /dev/null
+++ b/drivers/net/usb/qmi_wwan.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2012  Bjørn Mork <bjorn@mork.no>
+ *
+ * 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/module.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <linux/usb/usbnet.h>
+#include <linux/usb/cdc-wdm.h>
+
+/* The name of the CDC Device Management driver */
+#define DM_DRIVER "cdc_wdm"
+
+/*
+ * This driver supports wwan (3G/LTE/?) devices using a vendor
+ * specific management protocol called Qualcomm MSM Interface (QMI) -
+ * in addition to the more common AT commands over serial interface
+ * management
+ *
+ * QMI is wrapped in CDC, using CDC encapsulated commands on the
+ * control ("master") interface of a two-interface CDC Union
+ * resembling standard CDC ECM.  The devices do not use the control
+ * interface for any other CDC messages.  Most likely because the
+ * management protocol is used in place of the standard CDC
+ * notifications NOTIFY_NETWORK_CONNECTION and NOTIFY_SPEED_CHANGE
+ *
+ * Handling a protocol like QMI is out of the scope for any driver.
+ * It can be exported as a character device using the cdc-wdm driver,
+ * which will enable userspace applications ("modem managers") to
+ * handle it.  This may be required to use the network interface
+ * provided by the driver.
+ *
+ * These devices may alternatively/additionally be configured using AT
+ * commands on any of the serial interfaces driven by the option driver
+ *
+ * This driver binds only to the data ("slave") interface to enable
+ * the cdc-wdm driver to bind to the control interface.  It still
+ * parses the CDC functional descriptors on the control interface to
+ *  a) verify that this is indeed a handled interface (CDC Union
+ *     header lists it as slave)
+ *  b) get MAC address and other ethernet config from the CDC Ethernet
+ *     header
+ *  c) enable user bind requests against the control interface, which
+ *     is the common way to bind to CDC Ethernet Control Model type
+ *     interfaces
+ *  d) provide a hint to the user about which interface is the
+ *     corresponding management interface
+ */
+
+static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int status = -1;
+	struct usb_interface *control = NULL;
+	u8 *buf = intf->cur_altsetting->extra;
+	int len = intf->cur_altsetting->extralen;
+	struct usb_interface_descriptor *desc = &intf->cur_altsetting->desc;
+	struct usb_cdc_union_desc *cdc_union = NULL;
+	struct usb_cdc_ether_desc *cdc_ether = NULL;
+	u32 required = 1 << USB_CDC_HEADER_TYPE | 1 << USB_CDC_UNION_TYPE;
+	u32 found = 0;
+	atomic_t *pmcount = (void *)&dev->data[1];
+
+	atomic_set(pmcount, 0);
+
+	/*
+	 * assume a data interface has no additional descriptors and
+	 * that the control and data interface are numbered
+	 * consecutively - this holds for the Huawei device at least
+	 */
+	if (len == 0 && desc->bInterfaceNumber > 0) {
+		control = usb_ifnum_to_if(dev->udev, desc->bInterfaceNumber - 1);
+		if (!control)
+			goto err;
+
+		buf = control->cur_altsetting->extra;
+		len = control->cur_altsetting->extralen;
+		dev_dbg(&intf->dev, "guessing \"control\" => %s, \"data\" => this\n",
+			dev_name(&control->dev));
+	}
+
+	while (len > 3) {
+		struct usb_descriptor_header *h = (void *)buf;
+
+		/* ignore any misplaced descriptors */
+		if (h->bDescriptorType != USB_DT_CS_INTERFACE)
+			goto next_desc;
+
+		/* buf[2] is CDC descriptor subtype */
+		switch (buf[2]) {
+		case USB_CDC_HEADER_TYPE:
+			if (found & 1 << USB_CDC_HEADER_TYPE) {
+				dev_dbg(&intf->dev, "extra CDC header\n");
+				goto err;
+			}
+			if (h->bLength != sizeof(struct usb_cdc_header_desc)) {
+				dev_dbg(&intf->dev, "CDC header len %u\n", h->bLength);
+				goto err;
+			}
+			break;
+		case USB_CDC_UNION_TYPE:
+			if (found & 1 << USB_CDC_UNION_TYPE) {
+				dev_dbg(&intf->dev, "extra CDC union\n");
+				goto err;
+			}
+			if (h->bLength != sizeof(struct usb_cdc_union_desc)) {
+				dev_dbg(&intf->dev, "CDC union len %u\n", h->bLength);
+				goto err;
+			}
+			cdc_union = (struct usb_cdc_union_desc *)buf;
+			break;
+		case USB_CDC_ETHERNET_TYPE:
+			if (found & 1 << USB_CDC_ETHERNET_TYPE) {
+				dev_dbg(&intf->dev, "extra CDC ether\n");
+				goto err;
+			}
+			if (h->bLength != sizeof(struct usb_cdc_ether_desc)) {
+				dev_dbg(&intf->dev, "CDC ether len %u\n",  h->bLength);
+				goto err;
+			}
+			cdc_ether = (struct usb_cdc_ether_desc *)buf;
+			break;
+		}
+
+		/*
+		 * Remember which CDC functional descriptors we've seen.  Works
+		 * for all types we care about, of which USB_CDC_ETHERNET_TYPE
+		 * (0x0f) is the highest numbered
+		 */
+		if (buf[2] < 32)
+			found |= 1 << buf[2];
+
+next_desc:
+		len -= h->bLength;
+		buf += h->bLength;
+	}
+
+	/* did we find all the required ones? */
+	if ((found & required) != required) {
+		dev_err(&intf->dev, "CDC functional descriptors missing\n");
+		goto err;
+	}
+
+	/* give the user a helpful hint if trying to bind to the wrong interface */
+	if (cdc_union && desc->bInterfaceNumber == cdc_union->bMasterInterface0) {
+		dev_err(&intf->dev, "leaving \"control\" interface for " DM_DRIVER " - try binding to %s instead!\n",
+			dev_name(&usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0)->dev));
+		goto err;
+	}
+
+	/* errors aren't fatal - we can live with the dynamic address */
+	if (cdc_ether) {
+		dev->hard_mtu = le16_to_cpu(cdc_ether->wMaxSegmentSize);
+		usbnet_get_ethernet_addr(dev, cdc_ether->iMACAddress);
+	}
+
+	/* success! point the user to the management interface */
+	if (control)
+		dev_info(&intf->dev, "Use \"" DM_DRIVER "\" for QMI interface %s\n",
+			dev_name(&control->dev));
+
+	/* XXX: add a sysfs symlink somewhere to help management applications find it? */
+
+	/* collect bulk endpoints now that we know intf == "data" interface */
+	status = usbnet_get_endpoints(dev, intf);
+
+err:
+	return status;
+}
+
+/* using a counter to merge subdriver requests with our own into a combined state */
+static int qmi_wwan_manage_power(struct usbnet *dev, int on)
+{
+	atomic_t *pmcount = (void *)&dev->data[1];
+	int rv = 0;
+
+	dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(pmcount), on);
+
+	if ((on && atomic_add_return(1, pmcount) == 1) || (!on && atomic_dec_and_test(pmcount))) {
+		/* need autopm_get/put here to ensure the usbcore sees the new value */
+		rv = usb_autopm_get_interface(dev->intf);
+		if (rv < 0)
+			goto err;
+		dev->intf->needs_remote_wakeup = on;
+		usb_autopm_put_interface(dev->intf);
+	}
+err:
+	return rv;
+}
+
+static int qmi_wwan_cdc_wdm_manage_power(struct usb_interface *intf, int on)
+{
+	struct usbnet *dev = usb_get_intfdata(intf);
+	return qmi_wwan_manage_power(dev, on);
+}
+
+/* Some devices combine the "control" and "data" functions into a
+ * single interface with all three endpoints: interrupt + bulk in and
+ * out
+ *
+ * Setting up cdc-wdm as a subdriver owning the interrupt endpoint
+ * will let it provide userspace access to the encapsulated QMI
+ * protocol without interfering with the usbnet operations.
+  */
+static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf)
+{
+	int rv;
+	struct usb_driver *subdriver = NULL;
+	atomic_t *pmcount = (void *)&dev->data[1];
+
+	/* ZTE makes devices where the interface descriptors and endpoint
+	 * configurations of two or more interfaces are identical, even
+	 * though the functions are completely different.  If set, then
+	 * driver_info->data is a bitmap of acceptable interface numbers
+	 * allowing us to bind to one such interface without binding to
+	 * all of them
+	 */
+	if (dev->driver_info->data &&
+	    !test_bit(intf->cur_altsetting->desc.bInterfaceNumber, &dev->driver_info->data)) {
+		dev_info(&intf->dev, "not on our whitelist - ignored");
+		rv = -ENODEV;
+		goto err;
+	}
+
+	atomic_set(pmcount, 0);
+
+	/* collect all three endpoints */
+	rv = usbnet_get_endpoints(dev, intf);
+	if (rv < 0)
+		goto err;
+
+	/* require interrupt endpoint for subdriver */
+	if (!dev->status) {
+		rv = -EINVAL;
+		goto err;
+	}
+
+	subdriver = usb_cdc_wdm_register(intf, &dev->status->desc, 512, &qmi_wwan_cdc_wdm_manage_power);
+	if (IS_ERR(subdriver)) {
+		rv = PTR_ERR(subdriver);
+		goto err;
+	}
+
+	/* can't let usbnet use the interrupt endpoint */
+	dev->status = NULL;
+
+	/* save subdriver struct for suspend/resume wrappers */
+	dev->data[0] = (unsigned long)subdriver;
+
+err:
+	return rv;
+}
+
+/* Gobi devices uses identical class/protocol codes for all interfaces regardless
+ * of function. Some of these are CDC ACM like and have the exact same endpoints
+ * we are looking for. This leaves two possible strategies for identifying the
+ * correct interface:
+ *   a) hardcoding interface number, or
+ *   b) use the fact that the wwan interface is the only one lacking additional
+ *      (CDC functional) descriptors
+ *
+ * Let's see if we can get away with the generic b) solution.
+ */
+static int qmi_wwan_bind_gobi(struct usbnet *dev, struct usb_interface *intf)
+{
+	int rv = -EINVAL;
+
+	/* ignore any interface with additional descriptors */
+	if (intf->cur_altsetting->extralen)
+		goto err;
+
+	rv = qmi_wwan_bind_shared(dev, intf);
+err:
+	return rv;
+}
+
+static void qmi_wwan_unbind_shared(struct usbnet *dev, struct usb_interface *intf)
+{
+	struct usb_driver *subdriver = (void *)dev->data[0];
+
+	if (subdriver && subdriver->disconnect)
+		subdriver->disconnect(intf);
+
+	dev->data[0] = (unsigned long)NULL;
+}
+
+/* suspend/resume wrappers calling both usbnet and the cdc-wdm
+ * subdriver if present.
+ *
+ * NOTE: cdc-wdm also supports pre/post_reset, but we cannot provide
+ * wrappers for those without adding usbnet reset support first.
+ */
+static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct usbnet *dev = usb_get_intfdata(intf);
+	struct usb_driver *subdriver = (void *)dev->data[0];
+	int ret;
+
+	ret = usbnet_suspend(intf, message);
+	if (ret < 0)
+		goto err;
+
+	if (subdriver && subdriver->suspend)
+		ret = subdriver->suspend(intf, message);
+	if (ret < 0)
+		usbnet_resume(intf);
+err:
+	return ret;
+}
+
+static int qmi_wwan_resume(struct usb_interface *intf)
+{
+	struct usbnet *dev = usb_get_intfdata(intf);
+	struct usb_driver *subdriver = (void *)dev->data[0];
+	int ret = 0;
+
+	if (subdriver && subdriver->resume)
+		ret = subdriver->resume(intf);
+	if (ret < 0)
+		goto err;
+	ret = usbnet_resume(intf);
+	if (ret < 0 && subdriver && subdriver->resume && subdriver->suspend)
+		subdriver->suspend(intf, PMSG_SUSPEND);
+err:
+	return ret;
+}
+
+
+static const struct driver_info	qmi_wwan_info = {
+	.description	= "QMI speaking wwan device",
+	.flags		= FLAG_WWAN,
+	.bind		= qmi_wwan_bind,
+	.manage_power	= qmi_wwan_manage_power,
+};
+
+static const struct driver_info	qmi_wwan_shared = {
+	.description	= "QMI speaking wwan device with combined interface",
+	.flags		= FLAG_WWAN,
+	.bind		= qmi_wwan_bind_shared,
+	.unbind		= qmi_wwan_unbind_shared,
+	.manage_power	= qmi_wwan_manage_power,
+};
+
+static const struct driver_info	qmi_wwan_gobi = {
+	.description	= "Qualcomm Gobi wwan/QMI device",
+	.flags		= FLAG_WWAN,
+	.bind		= qmi_wwan_bind_gobi,
+	.unbind		= qmi_wwan_unbind_shared,
+	.manage_power	= qmi_wwan_manage_power,
+};
+
+/* ZTE suck at making USB descriptors */
+static const struct driver_info	qmi_wwan_force_int4 = {
+	.description	= "Qualcomm Gobi wwan/QMI device",
+	.flags		= FLAG_WWAN,
+	.bind		= qmi_wwan_bind_gobi,
+	.unbind		= qmi_wwan_unbind_shared,
+	.manage_power	= qmi_wwan_manage_power,
+	.data		= BIT(4), /* interface whitelist bitmap */
+};
+
+
+#define HUAWEI_VENDOR_ID	0x12D1
+#define QMI_GOBI_DEVICE(vend, prod) \
+	USB_DEVICE(vend, prod), \
+	.driver_info = (unsigned long)&qmi_wwan_gobi
+
+static const struct usb_device_id products[] = {
+	{	/* Huawei E392, E398 and possibly others sharing both device id and more... */
+		.match_flags        = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO,
+		.idVendor           = HUAWEI_VENDOR_ID,
+		.bInterfaceClass    = USB_CLASS_VENDOR_SPEC,
+		.bInterfaceSubClass = 1,
+		.bInterfaceProtocol = 8, /* NOTE: This is the *slave* interface of the CDC Union! */
+		.driver_info        = (unsigned long)&qmi_wwan_info,
+	},
+	{	/* Huawei E392, E398 and possibly others in "Windows mode"
+		 * using a combined control and data interface without any CDC
+		 * functional descriptors
+		 */
+		.match_flags        = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO,
+		.idVendor           = HUAWEI_VENDOR_ID,
+		.bInterfaceClass    = USB_CLASS_VENDOR_SPEC,
+		.bInterfaceSubClass = 1,
+		.bInterfaceProtocol = 17,
+		.driver_info        = (unsigned long)&qmi_wwan_shared,
+	},
+	{	/* Pantech UML290 */
+		.match_flags	    = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
+		.idVendor           = 0x106c,
+		.idProduct          = 0x3718,
+		.bInterfaceClass    = 0xff,
+		.bInterfaceSubClass = 0xf0,
+		.bInterfaceProtocol = 0xff,
+		.driver_info        = (unsigned long)&qmi_wwan_shared,
+	},
+	{	/* ZTE MF820D */
+		.match_flags	    = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
+		.idVendor           = 0x19d2,
+		.idProduct          = 0x0167,
+		.bInterfaceClass    = 0xff,
+		.bInterfaceSubClass = 0xff,
+		.bInterfaceProtocol = 0xff,
+		.driver_info        = (unsigned long)&qmi_wwan_force_int4,
+	},
+	{QMI_GOBI_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
+	{QMI_GOBI_DEVICE(0x03f0, 0x1f1d)},	/* HP un2400 Gobi Modem Device */
+	{QMI_GOBI_DEVICE(0x03f0, 0x371d)},	/* HP un2430 Mobile Broadband Module */
+	{QMI_GOBI_DEVICE(0x04da, 0x250d)},	/* Panasonic Gobi Modem device */
+	{QMI_GOBI_DEVICE(0x413c, 0x8172)},	/* Dell Gobi Modem device */
+	{QMI_GOBI_DEVICE(0x1410, 0xa001)},	/* Novatel Gobi Modem device */
+	{QMI_GOBI_DEVICE(0x0b05, 0x1776)},	/* Asus Gobi Modem device */
+	{QMI_GOBI_DEVICE(0x19d2, 0xfff3)},	/* ONDA Gobi Modem device */
+	{QMI_GOBI_DEVICE(0x05c6, 0x9001)},	/* Generic Gobi Modem device */
+	{QMI_GOBI_DEVICE(0x05c6, 0x9002)},	/* Generic Gobi Modem device */
+	{QMI_GOBI_DEVICE(0x05c6, 0x9202)},	/* Generic Gobi Modem device */
+	{QMI_GOBI_DEVICE(0x05c6, 0x9203)},	/* Generic Gobi Modem device */
+	{QMI_GOBI_DEVICE(0x05c6, 0x9222)},	/* Generic Gobi Modem device */
+	{QMI_GOBI_DEVICE(0x05c6, 0x9009)},	/* Generic Gobi Modem device */
+	{QMI_GOBI_DEVICE(0x413c, 0x8186)},	/* Dell Gobi 2000 Modem device (N0218, VU936) */
+	{QMI_GOBI_DEVICE(0x05c6, 0x920b)},	/* Generic Gobi 2000 Modem device */
+	{QMI_GOBI_DEVICE(0x05c6, 0x9225)},	/* Sony Gobi 2000 Modem device (N0279, VU730) */
+	{QMI_GOBI_DEVICE(0x05c6, 0x9245)},	/* Samsung Gobi 2000 Modem device (VL176) */
+	{QMI_GOBI_DEVICE(0x03f0, 0x251d)},	/* HP Gobi 2000 Modem device (VP412) */
+	{QMI_GOBI_DEVICE(0x05c6, 0x9215)},	/* Acer Gobi 2000 Modem device (VP413) */
+	{QMI_GOBI_DEVICE(0x05c6, 0x9265)},	/* Asus Gobi 2000 Modem device (VR305) */
+	{QMI_GOBI_DEVICE(0x05c6, 0x9235)},	/* Top Global Gobi 2000 Modem device (VR306) */
+	{QMI_GOBI_DEVICE(0x05c6, 0x9275)},	/* iRex Technologies Gobi 2000 Modem device (VR307) */
+	{QMI_GOBI_DEVICE(0x1199, 0x9001)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{QMI_GOBI_DEVICE(0x1199, 0x9002)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{QMI_GOBI_DEVICE(0x1199, 0x9003)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{QMI_GOBI_DEVICE(0x1199, 0x9004)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{QMI_GOBI_DEVICE(0x1199, 0x9005)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{QMI_GOBI_DEVICE(0x1199, 0x9006)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{QMI_GOBI_DEVICE(0x1199, 0x9007)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{QMI_GOBI_DEVICE(0x1199, 0x9008)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{QMI_GOBI_DEVICE(0x1199, 0x9009)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{QMI_GOBI_DEVICE(0x1199, 0x900a)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{QMI_GOBI_DEVICE(0x1199, 0x9011)},	/* Sierra Wireless Gobi 2000 Modem device (MC8305) */
+	{QMI_GOBI_DEVICE(0x16d8, 0x8002)},	/* CMDTech Gobi 2000 Modem device (VU922) */
+	{QMI_GOBI_DEVICE(0x05c6, 0x9205)},	/* Gobi 2000 Modem device */
+	{QMI_GOBI_DEVICE(0x1199, 0x9013)},	/* Sierra Wireless Gobi 3000 Modem device (MC8355) */
+	{ }					/* END */
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver qmi_wwan_driver = {
+	.name		      = "qmi_wwan",
+	.id_table	      = products,
+	.probe		      =	usbnet_probe,
+	.disconnect	      = usbnet_disconnect,
+	.suspend	      = qmi_wwan_suspend,
+	.resume		      =	qmi_wwan_resume,
+	.reset_resume         = qmi_wwan_resume,
+	.supports_autosuspend = 1,
+};
+
+static int __init qmi_wwan_init(void)
+{
+	return usb_register(&qmi_wwan_driver);
+}
+module_init(qmi_wwan_init);
+
+static void __exit qmi_wwan_exit(void)
+{
+	usb_deregister(&qmi_wwan_driver);
+}
+module_exit(qmi_wwan_exit);
+
+MODULE_AUTHOR("Bjørn Mork <bjorn@mork.no>");
+MODULE_DESCRIPTION("Qualcomm MSM Interface (QMI) WWAN driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
index b806667..1289a5f 100644
--- a/drivers/power/isp1704_charger.c
+++ b/drivers/power/isp1704_charger.c
@@ -56,7 +56,7 @@
 struct isp1704_charger {
 	struct device		*dev;
 	struct power_supply	psy;
-	struct otg_transceiver	*otg;
+	struct usb_phy		*phy;
 	struct notifier_block	nb;
 	struct work_struct	work;
 
@@ -71,6 +71,16 @@
 	unsigned		max_power;
 };
 
+static inline int isp1704_read(struct isp1704_charger *isp, u32 reg)
+{
+	return usb_phy_io_read(isp->phy, reg);
+}
+
+static inline int isp1704_write(struct isp1704_charger *isp, u32 val, u32 reg)
+{
+	return usb_phy_io_write(isp->phy, val, reg);
+}
+
 /*
  * Disable/enable the power from the isp1704 if a function for it
  * has been provided with platform data.
@@ -97,31 +107,31 @@
 	u8 otg_ctrl;
 	int type = POWER_SUPPLY_TYPE_USB_DCP;
 
-	func_ctrl = otg_io_read(isp->otg, ULPI_FUNC_CTRL);
-	otg_ctrl = otg_io_read(isp->otg, ULPI_OTG_CTRL);
+	func_ctrl = isp1704_read(isp, ULPI_FUNC_CTRL);
+	otg_ctrl = isp1704_read(isp, ULPI_OTG_CTRL);
 
 	/* disable pulldowns */
 	reg = ULPI_OTG_CTRL_DM_PULLDOWN | ULPI_OTG_CTRL_DP_PULLDOWN;
-	otg_io_write(isp->otg, ULPI_CLR(ULPI_OTG_CTRL), reg);
+	isp1704_write(isp, ULPI_CLR(ULPI_OTG_CTRL), reg);
 
 	/* full speed */
-	otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL),
+	isp1704_write(isp, ULPI_CLR(ULPI_FUNC_CTRL),
 			ULPI_FUNC_CTRL_XCVRSEL_MASK);
-	otg_io_write(isp->otg, ULPI_SET(ULPI_FUNC_CTRL),
+	isp1704_write(isp, ULPI_SET(ULPI_FUNC_CTRL),
 			ULPI_FUNC_CTRL_FULL_SPEED);
 
 	/* Enable strong pull-up on DP (1.5K) and reset */
 	reg = ULPI_FUNC_CTRL_TERMSELECT | ULPI_FUNC_CTRL_RESET;
-	otg_io_write(isp->otg, ULPI_SET(ULPI_FUNC_CTRL), reg);
+	isp1704_write(isp, ULPI_SET(ULPI_FUNC_CTRL), reg);
 	usleep_range(1000, 2000);
 
-	reg = otg_io_read(isp->otg, ULPI_DEBUG);
+	reg = isp1704_read(isp, ULPI_DEBUG);
 	if ((reg & 3) != 3)
 		type = POWER_SUPPLY_TYPE_USB_CDP;
 
 	/* recover original state */
-	otg_io_write(isp->otg, ULPI_FUNC_CTRL, func_ctrl);
-	otg_io_write(isp->otg, ULPI_OTG_CTRL, otg_ctrl);
+	isp1704_write(isp, ULPI_FUNC_CTRL, func_ctrl);
+	isp1704_write(isp, ULPI_OTG_CTRL, otg_ctrl);
 
 	return type;
 }
@@ -136,28 +146,28 @@
 	u8	r;
 
 	/* Reset the transceiver */
-	r = otg_io_read(isp->otg, ULPI_FUNC_CTRL);
+	r = isp1704_read(isp, ULPI_FUNC_CTRL);
 	r |= ULPI_FUNC_CTRL_RESET;
-	otg_io_write(isp->otg, ULPI_FUNC_CTRL, r);
+	isp1704_write(isp, ULPI_FUNC_CTRL, r);
 	usleep_range(1000, 2000);
 
 	/* Set normal mode */
 	r &= ~(ULPI_FUNC_CTRL_RESET | ULPI_FUNC_CTRL_OPMODE_MASK);
-	otg_io_write(isp->otg, ULPI_FUNC_CTRL, r);
+	isp1704_write(isp, ULPI_FUNC_CTRL, r);
 
 	/* Clear the DP and DM pull-down bits */
 	r = ULPI_OTG_CTRL_DP_PULLDOWN | ULPI_OTG_CTRL_DM_PULLDOWN;
-	otg_io_write(isp->otg, ULPI_CLR(ULPI_OTG_CTRL), r);
+	isp1704_write(isp, ULPI_CLR(ULPI_OTG_CTRL), r);
 
 	/* Enable strong pull-up on DP (1.5K) and reset */
 	r = ULPI_FUNC_CTRL_TERMSELECT | ULPI_FUNC_CTRL_RESET;
-	otg_io_write(isp->otg, ULPI_SET(ULPI_FUNC_CTRL), r);
+	isp1704_write(isp, ULPI_SET(ULPI_FUNC_CTRL), r);
 	usleep_range(1000, 2000);
 
 	/* Read the line state */
-	if (!otg_io_read(isp->otg, ULPI_DEBUG)) {
+	if (!isp1704_read(isp, ULPI_DEBUG)) {
 		/* Disable strong pull-up on DP (1.5K) */
-		otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL),
+		isp1704_write(isp, ULPI_CLR(ULPI_FUNC_CTRL),
 				ULPI_FUNC_CTRL_TERMSELECT);
 		return 1;
 	}
@@ -165,23 +175,23 @@
 	/* Is it a charger or PS/2 connection */
 
 	/* Enable weak pull-up resistor on DP */
-	otg_io_write(isp->otg, ULPI_SET(ISP1704_PWR_CTRL),
+	isp1704_write(isp, ULPI_SET(ISP1704_PWR_CTRL),
 			ISP1704_PWR_CTRL_DP_WKPU_EN);
 
 	/* Disable strong pull-up on DP (1.5K) */
-	otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL),
+	isp1704_write(isp, ULPI_CLR(ULPI_FUNC_CTRL),
 			ULPI_FUNC_CTRL_TERMSELECT);
 
 	/* Enable weak pull-down resistor on DM */
-	otg_io_write(isp->otg, ULPI_SET(ULPI_OTG_CTRL),
+	isp1704_write(isp, ULPI_SET(ULPI_OTG_CTRL),
 			ULPI_OTG_CTRL_DM_PULLDOWN);
 
 	/* It's a charger if the line states are clear */
-	if (!(otg_io_read(isp->otg, ULPI_DEBUG)))
+	if (!(isp1704_read(isp, ULPI_DEBUG)))
 		ret = 1;
 
 	/* Disable weak pull-up resistor on DP */
-	otg_io_write(isp->otg, ULPI_CLR(ISP1704_PWR_CTRL),
+	isp1704_write(isp, ULPI_CLR(ISP1704_PWR_CTRL),
 			ISP1704_PWR_CTRL_DP_WKPU_EN);
 
 	return ret;
@@ -193,14 +203,14 @@
 	u8		pwr_ctrl;
 	int		ret = 0;
 
-	pwr_ctrl = otg_io_read(isp->otg, ISP1704_PWR_CTRL);
+	pwr_ctrl = isp1704_read(isp, ISP1704_PWR_CTRL);
 
 	/* set SW control bit in PWR_CTRL register */
-	otg_io_write(isp->otg, ISP1704_PWR_CTRL,
+	isp1704_write(isp, ISP1704_PWR_CTRL,
 			ISP1704_PWR_CTRL_SWCTRL);
 
 	/* enable manual charger detection */
-	otg_io_write(isp->otg, ULPI_SET(ISP1704_PWR_CTRL),
+	isp1704_write(isp, ULPI_SET(ISP1704_PWR_CTRL),
 			ISP1704_PWR_CTRL_SWCTRL
 			| ISP1704_PWR_CTRL_DPVSRC_EN);
 	usleep_range(1000, 2000);
@@ -208,7 +218,7 @@
 	timeout = jiffies + msecs_to_jiffies(300);
 	do {
 		/* Check if there is a charger */
-		if (otg_io_read(isp->otg, ISP1704_PWR_CTRL)
+		if (isp1704_read(isp, ISP1704_PWR_CTRL)
 				& ISP1704_PWR_CTRL_VDAT_DET) {
 			ret = isp1704_charger_verify(isp);
 			break;
@@ -216,7 +226,7 @@
 	} while (!time_after(jiffies, timeout) && isp->online);
 
 	/* recover original state */
-	otg_io_write(isp->otg, ISP1704_PWR_CTRL, pwr_ctrl);
+	isp1704_write(isp, ISP1704_PWR_CTRL, pwr_ctrl);
 
 	return ret;
 }
@@ -264,8 +274,8 @@
 		case POWER_SUPPLY_TYPE_USB:
 		default:
 			/* enable data pullups */
-			if (isp->otg->gadget)
-				usb_gadget_connect(isp->otg->gadget);
+			if (isp->phy->otg->gadget)
+				usb_gadget_connect(isp->phy->otg->gadget);
 		}
 		break;
 	case USB_EVENT_NONE:
@@ -283,8 +293,8 @@
 		 * chargers. The pullups may be enabled elsewhere, so this can
 		 * not be the final solution.
 		 */
-		if (isp->otg->gadget)
-			usb_gadget_disconnect(isp->otg->gadget);
+		if (isp->phy->otg->gadget)
+			usb_gadget_disconnect(isp->phy->otg->gadget);
 
 		isp1704_charger_set_power(isp, 0);
 		break;
@@ -364,11 +374,11 @@
 	int ret = -ENODEV;
 
 	/* Test ULPI interface */
-	ret = otg_io_write(isp->otg, ULPI_SCRATCH, 0xaa);
+	ret = isp1704_write(isp, ULPI_SCRATCH, 0xaa);
 	if (ret < 0)
 		return ret;
 
-	ret = otg_io_read(isp->otg, ULPI_SCRATCH);
+	ret = isp1704_read(isp, ULPI_SCRATCH);
 	if (ret < 0)
 		return ret;
 
@@ -376,13 +386,13 @@
 		return -ENODEV;
 
 	/* Verify the product and vendor id matches */
-	vendor = otg_io_read(isp->otg, ULPI_VENDOR_ID_LOW);
-	vendor |= otg_io_read(isp->otg, ULPI_VENDOR_ID_HIGH) << 8;
+	vendor = isp1704_read(isp, ULPI_VENDOR_ID_LOW);
+	vendor |= isp1704_read(isp, ULPI_VENDOR_ID_HIGH) << 8;
 	if (vendor != NXP_VENDOR_ID)
 		return -ENODEV;
 
-	product = otg_io_read(isp->otg, ULPI_PRODUCT_ID_LOW);
-	product |= otg_io_read(isp->otg, ULPI_PRODUCT_ID_HIGH) << 8;
+	product = isp1704_read(isp, ULPI_PRODUCT_ID_LOW);
+	product |= isp1704_read(isp, ULPI_PRODUCT_ID_HIGH) << 8;
 
 	for (i = 0; i < ARRAY_SIZE(isp170x_id); i++) {
 		if (product == isp170x_id[i]) {
@@ -405,8 +415,8 @@
 	if (!isp)
 		return -ENOMEM;
 
-	isp->otg = otg_get_transceiver();
-	if (!isp->otg)
+	isp->phy = usb_get_transceiver();
+	if (!isp->phy)
 		goto fail0;
 
 	isp->dev = &pdev->dev;
@@ -429,14 +439,14 @@
 		goto fail1;
 
 	/*
-	 * REVISIT: using work in order to allow the otg notifications to be
+	 * REVISIT: using work in order to allow the usb notifications to be
 	 * made atomically in the future.
 	 */
 	INIT_WORK(&isp->work, isp1704_charger_work);
 
 	isp->nb.notifier_call = isp1704_notifier_call;
 
-	ret = otg_register_notifier(isp->otg, &isp->nb);
+	ret = usb_register_notifier(isp->phy, &isp->nb);
 	if (ret)
 		goto fail2;
 
@@ -449,13 +459,13 @@
 	 * enumerated. The charger driver should be always loaded before any
 	 * gadget is loaded.
 	 */
-	if (isp->otg->gadget)
-		usb_gadget_disconnect(isp->otg->gadget);
+	if (isp->phy->otg->gadget)
+		usb_gadget_disconnect(isp->phy->otg->gadget);
 
 	/* Detect charger if VBUS is valid (the cable was already plugged). */
-	ret = otg_io_read(isp->otg, ULPI_USB_INT_STS);
+	ret = isp1704_read(isp, ULPI_USB_INT_STS);
 	isp1704_charger_set_power(isp, 0);
-	if ((ret & ULPI_INT_VBUS_VALID) && !isp->otg->default_a) {
+	if ((ret & ULPI_INT_VBUS_VALID) && !isp->phy->otg->default_a) {
 		isp->event = USB_EVENT_VBUS;
 		schedule_work(&isp->work);
 	}
@@ -464,7 +474,7 @@
 fail2:
 	power_supply_unregister(&isp->psy);
 fail1:
-	otg_put_transceiver(isp->otg);
+	usb_put_transceiver(isp->phy);
 fail0:
 	kfree(isp);
 
@@ -477,9 +487,9 @@
 {
 	struct isp1704_charger *isp = platform_get_drvdata(pdev);
 
-	otg_unregister_notifier(isp->otg, &isp->nb);
+	usb_unregister_notifier(isp->phy, &isp->nb);
 	power_supply_unregister(&isp->psy);
-	otg_put_transceiver(isp->otg);
+	usb_put_transceiver(isp->phy);
 	isp1704_charger_set_power(isp, 0);
 	kfree(isp);
 
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
index fd49689..214468f 100644
--- a/drivers/power/pda_power.c
+++ b/drivers/power/pda_power.c
@@ -40,7 +40,7 @@
 static int polling;
 
 #ifdef CONFIG_USB_OTG_UTILS
-static struct otg_transceiver *transceiver;
+static struct usb_phy *transceiver;
 static struct notifier_block otg_nb;
 #endif
 
@@ -321,7 +321,7 @@
 	}
 
 #ifdef CONFIG_USB_OTG_UTILS
-	transceiver = otg_get_transceiver();
+	transceiver = usb_get_transceiver();
 	if (transceiver && !pdata->is_usb_online) {
 		pdata->is_usb_online = otg_is_usb_online;
 	}
@@ -375,7 +375,7 @@
 #ifdef CONFIG_USB_OTG_UTILS
 	if (transceiver && pdata->use_otg_notifier) {
 		otg_nb.notifier_call = otg_handle_notification;
-		ret = otg_register_notifier(transceiver, &otg_nb);
+		ret = usb_register_notifier(transceiver, &otg_nb);
 		if (ret) {
 			dev_err(dev, "failure to register otg notifier\n");
 			goto otg_reg_notifier_failed;
@@ -409,7 +409,7 @@
 		free_irq(ac_irq->start, &pda_psy_ac);
 #ifdef CONFIG_USB_OTG_UTILS
 	if (transceiver)
-		otg_put_transceiver(transceiver);
+		usb_put_transceiver(transceiver);
 #endif
 ac_irq_failed:
 	if (pdata->is_ac_online)
@@ -444,7 +444,7 @@
 		power_supply_unregister(&pda_psy_ac);
 #ifdef CONFIG_USB_OTG_UTILS
 	if (transceiver)
-		otg_put_transceiver(transceiver);
+		usb_put_transceiver(transceiver);
 #endif
 	if (ac_draw) {
 		regulator_put(ac_draw);
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 54b9198..fdad850 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -69,8 +69,8 @@
 	struct device		*dev;
 	struct power_supply	ac;
 	struct power_supply	usb;
-	struct otg_transceiver	*transceiver;
-	struct notifier_block	otg_nb;
+	struct usb_phy		*transceiver;
+	struct notifier_block	usb_nb;
 	struct work_struct	work;
 	int			irq_chg;
 	int			irq_bci;
@@ -279,7 +279,7 @@
 static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
 			       void *priv)
 {
-	struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, otg_nb);
+	struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, usb_nb);
 
 	dev_dbg(bci->dev, "OTG notify %lu\n", val);
 
@@ -479,10 +479,10 @@
 
 	INIT_WORK(&bci->work, twl4030_bci_usb_work);
 
-	bci->transceiver = otg_get_transceiver();
+	bci->transceiver = usb_get_transceiver();
 	if (bci->transceiver != NULL) {
-		bci->otg_nb.notifier_call = twl4030_bci_usb_ncb;
-		otg_register_notifier(bci->transceiver, &bci->otg_nb);
+		bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
+		usb_register_notifier(bci->transceiver, &bci->usb_nb);
 	}
 
 	/* Enable interrupts now. */
@@ -508,8 +508,8 @@
 
 fail_unmask_interrupts:
 	if (bci->transceiver != NULL) {
-		otg_unregister_notifier(bci->transceiver, &bci->otg_nb);
-		otg_put_transceiver(bci->transceiver);
+		usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
+		usb_put_transceiver(bci->transceiver);
 	}
 	free_irq(bci->irq_bci, bci);
 fail_bci_irq:
@@ -539,8 +539,8 @@
 			 TWL4030_INTERRUPTS_BCIIMR2A);
 
 	if (bci->transceiver != NULL) {
-		otg_unregister_notifier(bci->transceiver, &bci->otg_nb);
-		otg_put_transceiver(bci->transceiver);
+		usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
+		usb_put_transceiver(bci->transceiver);
 	}
 	free_irq(bci->irq_bci, bci);
 	free_irq(bci->irq_chg, bci);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 29c4c04..01b0374 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1295,6 +1295,7 @@
  *   LUNs even if it's older than SCSI-3.
  *   If BLIST_NOREPORTLUN is set, return 1 always.
  *   If BLIST_NOLUN is set, return 0 always.
+ *   If starget->no_report_luns is set, return 1 always.
  *
  * Return:
  *     0: scan completed (or no memory, so further scanning is futile)
@@ -1321,6 +1322,7 @@
 	 * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set.
 	 * Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does
 	 * support more than 8 LUNs.
+	 * Don't attempt if the target doesn't support REPORT LUNS.
 	 */
 	if (bflags & BLIST_NOREPORTLUN)
 		return 1;
@@ -1332,6 +1334,8 @@
 		return 1;
 	if (bflags & BLIST_NOLUN)
 		return 0;
+	if (starget->no_report_luns)
+		return 1;
 
 	if (!(sdev = scsi_device_lookup_by_target(starget, 0))) {
 		sdev = scsi_alloc_sdev(starget, 0, NULL);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index c691fb5..d173b90 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2349,7 +2349,7 @@
 	 * some USB ones crash on receiving them, and the pages
 	 * we currently ask for are for SPC-3 and beyond
 	 */
-	if (sdp->scsi_level > SCSI_SPC_2)
+	if (sdp->scsi_level > SCSI_SPC_2 && !sdp->skip_vpd_pages)
 		return 1;
 	return 0;
 }
diff --git a/drivers/staging/keucr/transport.h b/drivers/staging/keucr/transport.h
index 4ae57d0..2a11a98 100644
--- a/drivers/staging/keucr/transport.h
+++ b/drivers/staging/keucr/transport.h
@@ -3,43 +3,6 @@
 
 #include <linux/blkdev.h>
 
-/* Bulk only data structures */
-
-/* command block wrapper */
-struct bulk_cb_wrap {
-	__le32	Signature;			/* contains 'USBC' */
-	__u32	Tag;				/* unique per command id */
-	__le32	DataTransferLength;	/* size of data */
-	__u8	Flags;				/* direction in bit 0 */
-	__u8	Lun;					/* LUN normally 0 */
-	__u8	Length;				/* of of the CDB */
-	__u8	CDB[16];				/* max command */
-};
-
-#define US_BULK_CB_WRAP_LEN	31
-#define US_BULK_CB_SIGN		0x43425355	/*spells out USBC */
-#define US_BULK_FLAG_IN		1
-#define US_BULK_FLAG_OUT	0
-
-/* command status wrapper */
-struct bulk_cs_wrap {
-	__le32	Signature;		/* should = 'USBS' */
-	__u32		Tag;			/* same as original command */
-	__le32	Residue;		/* amount not transferred */
-	__u8		Status;		/* see below */
-	__u8		Filler[18];
-};
-
-#define US_BULK_CS_WRAP_LEN	13
-#define US_BULK_CS_SIGN		0x53425355	/* spells out 'USBS' */
-#define US_BULK_STAT_OK		0
-#define US_BULK_STAT_FAIL	1
-#define US_BULK_STAT_PHASE	2
-
-/* bulk-only class specific requests */
-#define US_BULK_RESET_REQUEST	0xff
-#define US_BULK_GET_MAX_LUN	0xfe
-
 /* usb_stor_bulk_transfer_xxx() return codes, in order of severity */
 #define USB_STOR_XFER_GOOD	0	/* good transfer                 */
 #define USB_STOR_XFER_SHORT	1	/* transferred less than expected */
diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c
index 897a3a9..bb977e0 100644
--- a/drivers/staging/quatech_usb2/quatech_usb2.c
+++ b/drivers/staging/quatech_usb2/quatech_usb2.c
@@ -135,7 +135,6 @@
 	.probe = usb_serial_probe,
 	.disconnect = usb_serial_disconnect,
 	.id_table = quausb2_id_table,
-	.no_dynamic_id = 1,
 };
 
 /**
@@ -1942,7 +1941,6 @@
 		.name = "quatech_usb2",
 	},
 	.description = DRIVER_DESC,
-	.usb_driver = &quausb2_usb_driver,
 	.id_table = quausb2_id_table,
 	.num_ports = 8,
 	.open = qt2_open,
@@ -1964,41 +1962,11 @@
 	.write_bulk_callback = qt2_write_bulk_callback,
 };
 
-static int __init quausb2_usb_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&quatech2_device, NULL
+};
 
-	dbg("%s\n", __func__);
-
-	/* register with usb-serial */
-	retval = usb_serial_register(&quatech2_device);
-
-	if (retval)
-		goto failed_usb_serial_register;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-			DRIVER_DESC "\n");
-
-	/* register with usb */
-
-	retval = usb_register(&quausb2_usb_driver);
-	if (retval == 0)
-		return 0;
-
-	/* if we're here, usb_register() failed */
-	usb_serial_deregister(&quatech2_device);
-failed_usb_serial_register:
-		return retval;
-}
-
-static void __exit quausb2_usb_exit(void)
-{
-	usb_deregister(&quausb2_usb_driver);
-	usb_serial_deregister(&quatech2_device);
-}
-
-module_init(quausb2_usb_init);
-module_exit(quausb2_usb_exit);
+module_usb_serial_driver(quausb2_usb_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
index 1c5780f..ae1d815 100644
--- a/drivers/staging/serqt_usb2/serqt_usb2.c
+++ b/drivers/staging/serqt_usb2/serqt_usb2.c
@@ -200,7 +200,6 @@
 	.probe = usb_serial_probe,
 	.disconnect = usb_serial_disconnect,
 	.id_table = serqt_id_table,
-	.no_dynamic_id = 1,
 };
 
 static int port_paranoia_check(struct usb_serial_port *port,
@@ -1590,7 +1589,6 @@
 		   .name = "serqt",
 		   },
 	.description = DRIVER_DESC,
-	.usb_driver = &serqt_usb_driver,
 	.id_table = serqt_id_table,
 	.num_ports = 8,
 	.open = qt_open,
@@ -1610,41 +1608,11 @@
 	.release = qt_release,
 };
 
-static int __init serqt_usb_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&quatech_device, NULL
+};
 
-	dbg("%s\n", __func__);
-
-	/* register with usb-serial */
-	retval = usb_serial_register(&quatech_device);
-
-	if (retval)
-		goto failed_usb_serial_register;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-
-	/* register with usb */
-
-	retval = usb_register(&serqt_usb_driver);
-	if (retval == 0)
-		return 0;
-
-	/* if we're here, usb_register() failed */
-	usb_serial_deregister(&quatech_device);
-failed_usb_serial_register:
-	return retval;
-}
-
-static void __exit serqt_usb_exit(void)
-{
-	usb_deregister(&serqt_usb_driver);
-	usb_serial_deregister(&quatech_device);
-}
-
-module_init(serqt_usb_init);
-module_exit(serqt_usb_exit);
+module_usb_serial_driver(serqt_usb_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 75823a1..e4405e0 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -10,27 +10,6 @@
 	  This option adds core support for Universal Serial Bus (USB).
 	  You will also need drivers from the following menu to make use of it.
 
-if USB_SUPPORT
-
-config USB_COMMON
-	tristate
-	default y
-	depends on USB || USB_GADGET
-
-# Host-side USB depends on having a host controller
-# NOTE:  dummy_hcd is always an option, but it's ignored here ...
-# NOTE:  SL-811 option should be board-specific ...
-config USB_ARCH_HAS_HCD
-	boolean
-	default y if USB_ARCH_HAS_OHCI
-	default y if USB_ARCH_HAS_EHCI
-	default y if USB_ARCH_HAS_XHCI
-	default y if PCMCIA && !M32R			# sl811_cs
-	default y if ARM				# SL-811
-	default y if BLACKFIN				# SL-811
-	default y if SUPERH				# r8a66597-hcd
-	default PCI
-
 # many non-PCI SOC chips embed OHCI
 config USB_ARCH_HAS_OHCI
 	boolean
@@ -76,6 +55,7 @@
 	default y if MICROBLAZE
 	default y if SPARC_LEON
 	default y if ARCH_MMP
+	default y if MACH_LOONGSON1
 	default PCI
 
 # some non-PCI HCDs implement xHCI
@@ -83,6 +63,27 @@
 	boolean
 	default PCI
 
+if USB_SUPPORT
+
+config USB_COMMON
+	tristate
+	default y
+	depends on USB || USB_GADGET
+
+# Host-side USB depends on having a host controller
+# NOTE:  dummy_hcd is always an option, but it's ignored here ...
+# NOTE:  SL-811 option should be board-specific ...
+config USB_ARCH_HAS_HCD
+	boolean
+	default y if USB_ARCH_HAS_OHCI
+	default y if USB_ARCH_HAS_EHCI
+	default y if USB_ARCH_HAS_XHCI
+	default y if PCMCIA && !M32R			# sl811_cs
+	default y if ARM				# SL-811
+	default y if BLACKFIN				# SL-811
+	default y if SUPERH				# r8a66597-hcd
+	default PCI
+
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
 config USB
 	tristate "Support for Host-side USB"
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 6bb8472..b32ccb4 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -39,6 +39,7 @@
 #include <linux/serial.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
+#include <linux/serial.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
@@ -768,10 +769,37 @@
 	return acm_set_control(acm, acm->ctrlout = newctrl);
 }
 
+static int get_serial_info(struct acm *acm, struct serial_struct __user *info)
+{
+	struct serial_struct tmp;
+
+	if (!info)
+		return -EINVAL;
+
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.flags = ASYNC_LOW_LATENCY;
+	tmp.xmit_fifo_size = acm->writesize;
+	tmp.baud_base = le32_to_cpu(acm->line.dwDTERate);
+
+	if (copy_to_user(info, &tmp, sizeof(tmp)))
+		return -EFAULT;
+	else
+		return 0;
+}
+
 static int acm_tty_ioctl(struct tty_struct *tty,
 					unsigned int cmd, unsigned long arg)
 {
-	return -ENOIOCTLCMD;
+	struct acm *acm = tty->driver_data;
+	int rv = -ENOIOCTLCMD;
+
+	switch (cmd) {
+	case TIOCGSERIAL: /* gets serial port data */
+		rv = get_serial_info(acm, (struct serial_struct __user *) arg);
+		break;
+	}
+
+	return rv;
 }
 
 static const __u32 acm_tty_speed[] = {
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index d2b3cff..c6f6560 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -23,6 +23,7 @@
 #include <linux/usb/cdc.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
+#include <linux/usb/cdc-wdm.h>
 
 /*
  * Version Information
@@ -31,6 +32,8 @@
 #define DRIVER_AUTHOR "Oliver Neukum"
 #define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"
 
+#define HUAWEI_VENDOR_ID	0x12D1
+
 static const struct usb_device_id wdm_ids[] = {
 	{
 		.match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
@@ -38,6 +41,20 @@
 		.bInterfaceClass = USB_CLASS_COMM,
 		.bInterfaceSubClass = USB_CDC_SUBCLASS_DMM
 	},
+	{
+		/* 
+		 * Huawei E392, E398 and possibly other Qualcomm based modems
+		 * embed the Qualcomm QMI protocol inside CDC on CDC ECM like
+		 * control interfaces.  Userspace access to this is required
+		 * to configure the accompanying data interface
+		 */
+		.match_flags        = USB_DEVICE_ID_MATCH_VENDOR |
+					USB_DEVICE_ID_MATCH_INT_INFO,
+		.idVendor           = HUAWEI_VENDOR_ID,
+		.bInterfaceClass    = USB_CLASS_VENDOR_SPEC,
+		.bInterfaceSubClass = 1,
+		.bInterfaceProtocol = 9, /* NOTE: CDC ECM control interface! */
+	},
 	{ }
 };
 
@@ -54,6 +71,7 @@
 #define WDM_POLL_RUNNING	6
 #define WDM_RESPONDING		7
 #define WDM_SUSPENDING		8
+#define WDM_RESETTING		9
 
 #define WDM_MAX			16
 
@@ -61,6 +79,8 @@
 #define WDM_DEFAULT_BUFSIZE	256
 
 static DEFINE_MUTEX(wdm_mutex);
+static DEFINE_SPINLOCK(wdm_device_list_lock);
+static LIST_HEAD(wdm_device_list);
 
 /* --- method tables --- */
 
@@ -82,7 +102,6 @@
 	u16			bufsize;
 	u16			wMaxCommand;
 	u16			wMaxPacketSize;
-	u16			bMaxPacketSize0;
 	__le16			inum;
 	int			reslength;
 	int			length;
@@ -96,10 +115,40 @@
 	struct work_struct	rxwork;
 	int			werr;
 	int			rerr;
+
+	struct list_head	device_list;
+	int			(*manage_power)(struct usb_interface *, int);
 };
 
 static struct usb_driver wdm_driver;
 
+/* return intfdata if we own the interface, else look up intf in the list */
+static struct wdm_device *wdm_find_device(struct usb_interface *intf)
+{
+	struct wdm_device *desc = NULL;
+
+	spin_lock(&wdm_device_list_lock);
+	list_for_each_entry(desc, &wdm_device_list, device_list)
+		if (desc->intf == intf)
+			break;
+	spin_unlock(&wdm_device_list_lock);
+
+	return desc;
+}
+
+static struct wdm_device *wdm_find_device_by_minor(int minor)
+{
+	struct wdm_device *desc = NULL;
+
+	spin_lock(&wdm_device_list_lock);
+	list_for_each_entry(desc, &wdm_device_list, device_list)
+		if (desc->intf->minor == minor)
+			break;
+	spin_unlock(&wdm_device_list_lock);
+
+	return desc;
+}
+
 /* --- callbacks --- */
 static void wdm_out_callback(struct urb *urb)
 {
@@ -162,11 +211,9 @@
 	int rv = 0;
 	int status = urb->status;
 	struct wdm_device *desc;
-	struct usb_ctrlrequest *req;
 	struct usb_cdc_notification *dr;
 
 	desc = urb->context;
-	req = desc->irq;
 	dr = (struct usb_cdc_notification *)desc->sbuf;
 
 	if (status) {
@@ -213,24 +260,6 @@
 		goto exit;
 	}
 
-	req->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
-	req->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
-	req->wValue = 0;
-	req->wIndex = desc->inum;
-	req->wLength = cpu_to_le16(desc->wMaxCommand);
-
-	usb_fill_control_urb(
-		desc->response,
-		interface_to_usbdev(desc->intf),
-		/* using common endpoint 0 */
-		usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0),
-		(unsigned char *)req,
-		desc->inbuf,
-		desc->wMaxCommand,
-		wdm_in_callback,
-		desc
-	);
-	desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	spin_lock(&desc->iuspin);
 	clear_bit(WDM_READ, &desc->flags);
 	set_bit(WDM_RESPONDING, &desc->flags);
@@ -279,14 +308,11 @@
 
 static void cleanup(struct wdm_device *desc)
 {
-	usb_free_coherent(interface_to_usbdev(desc->intf),
-			  desc->wMaxPacketSize,
-			  desc->sbuf,
-			  desc->validity->transfer_dma);
-	usb_free_coherent(interface_to_usbdev(desc->intf),
-			  desc->bMaxPacketSize0,
-			  desc->inbuf,
-			  desc->response->transfer_dma);
+	spin_lock(&wdm_device_list_lock);
+	list_del(&desc->device_list);
+	spin_unlock(&wdm_device_list_lock);
+	kfree(desc->sbuf);
+	kfree(desc->inbuf);
 	kfree(desc->orq);
 	kfree(desc->irq);
 	kfree(desc->ubuf);
@@ -351,6 +377,10 @@
 	else
 		if (test_bit(WDM_IN_USE, &desc->flags))
 			r = -EAGAIN;
+
+	if (test_bit(WDM_RESETTING, &desc->flags))
+		r = -EIO;
+
 	if (r < 0) {
 		kfree(buf);
 		goto out;
@@ -397,7 +427,7 @@
 static ssize_t wdm_read
 (struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-	int rv, cntr = 0;
+	int rv, cntr;
 	int i = 0;
 	struct wdm_device *desc = file->private_data;
 
@@ -406,7 +436,8 @@
 	if (rv < 0)
 		return -ERESTARTSYS;
 
-	if (desc->length == 0) {
+	cntr = ACCESS_ONCE(desc->length);
+	if (cntr == 0) {
 		desc->read = 0;
 retry:
 		if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
@@ -430,6 +461,10 @@
 			rv = -ENODEV;
 			goto err;
 		}
+		if (test_bit(WDM_RESETTING, &desc->flags)) {
+			rv = -EIO;
+			goto err;
+		}
 		usb_mark_last_busy(interface_to_usbdev(desc->intf));
 		if (rv < 0) {
 			rv = -ERESTARTSYS;
@@ -456,26 +491,30 @@
 			spin_unlock_irq(&desc->iuspin);
 			goto retry;
 		}
-		clear_bit(WDM_READ, &desc->flags);
+		cntr = desc->length;
 		spin_unlock_irq(&desc->iuspin);
 	}
 
-	cntr = count > desc->length ? desc->length : count;
+	if (cntr > count)
+		cntr = count;
 	rv = copy_to_user(buffer, desc->ubuf, cntr);
 	if (rv > 0) {
 		rv = -EFAULT;
 		goto err;
 	}
 
+	spin_lock_irq(&desc->iuspin);
+
 	for (i = 0; i < desc->length - cntr; i++)
 		desc->ubuf[i] = desc->ubuf[i + cntr];
 
-	spin_lock_irq(&desc->iuspin);
 	desc->length -= cntr;
-	spin_unlock_irq(&desc->iuspin);
 	/* in case we had outstanding data */
 	if (!desc->length)
 		clear_bit(WDM_READ, &desc->flags);
+
+	spin_unlock_irq(&desc->iuspin);
+
 	rv = cntr;
 
 err:
@@ -529,11 +568,11 @@
 	struct wdm_device *desc;
 
 	mutex_lock(&wdm_mutex);
-	intf = usb_find_interface(&wdm_driver, minor);
-	if (!intf)
+	desc = wdm_find_device_by_minor(minor);
+	if (!desc)
 		goto out;
 
-	desc = usb_get_intfdata(intf);
+	intf = desc->intf;
 	if (test_bit(WDM_DISCONNECTING, &desc->flags))
 		goto out;
 	file->private_data = desc;
@@ -543,7 +582,6 @@
 		dev_err(&desc->intf->dev, "Error autopm - %d\n", rv);
 		goto out;
 	}
-	intf->needs_remote_wakeup = 1;
 
 	/* using write lock to protect desc->count */
 	mutex_lock(&desc->wlock);
@@ -560,6 +598,8 @@
 		rv = 0;
 	}
 	mutex_unlock(&desc->wlock);
+	if (desc->count == 1)
+		desc->manage_power(intf, 1);
 	usb_autopm_put_interface(desc->intf);
 out:
 	mutex_unlock(&wdm_mutex);
@@ -581,7 +621,7 @@
 		dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
 		kill_urbs(desc);
 		if (!test_bit(WDM_DISCONNECTING, &desc->flags))
-			desc->intf->needs_remote_wakeup = 0;
+			desc->manage_power(desc->intf, 0);
 	}
 	mutex_unlock(&wdm_mutex);
 	return 0;
@@ -628,71 +668,31 @@
 
 /* --- hotplug --- */
 
-static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
+static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep,
+		u16 bufsize, int (*manage_power)(struct usb_interface *, int))
 {
-	int rv = -EINVAL;
-	struct usb_device *udev = interface_to_usbdev(intf);
+	int rv = -ENOMEM;
 	struct wdm_device *desc;
-	struct usb_host_interface *iface;
-	struct usb_endpoint_descriptor *ep;
-	struct usb_cdc_dmm_desc *dmhd;
-	u8 *buffer = intf->altsetting->extra;
-	int buflen = intf->altsetting->extralen;
-	u16 maxcom = WDM_DEFAULT_BUFSIZE;
 
-	if (!buffer)
-		goto out;
-
-	while (buflen > 2) {
-		if (buffer [1] != USB_DT_CS_INTERFACE) {
-			dev_err(&intf->dev, "skipping garbage\n");
-			goto next_desc;
-		}
-
-		switch (buffer [2]) {
-		case USB_CDC_HEADER_TYPE:
-			break;
-		case USB_CDC_DMM_TYPE:
-			dmhd = (struct usb_cdc_dmm_desc *)buffer;
-			maxcom = le16_to_cpu(dmhd->wMaxCommand);
-			dev_dbg(&intf->dev,
-				"Finding maximum buffer length: %d", maxcom);
-			break;
-		default:
-			dev_err(&intf->dev,
-				"Ignoring extra header, type %d, length %d\n",
-				buffer[2], buffer[0]);
-			break;
-		}
-next_desc:
-		buflen -= buffer[0];
-		buffer += buffer[0];
-	}
-
-	rv = -ENOMEM;
 	desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
 	if (!desc)
 		goto out;
+	INIT_LIST_HEAD(&desc->device_list);
 	mutex_init(&desc->rlock);
 	mutex_init(&desc->wlock);
 	spin_lock_init(&desc->iuspin);
 	init_waitqueue_head(&desc->wait);
-	desc->wMaxCommand = maxcom;
+	desc->wMaxCommand = bufsize;
 	/* this will be expanded and needed in hardware endianness */
 	desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber);
 	desc->intf = intf;
 	INIT_WORK(&desc->rxwork, wdm_rxwork);
 
 	rv = -EINVAL;
-	iface = intf->cur_altsetting;
-	if (iface->desc.bNumEndpoints != 1)
-		goto err;
-	ep = &iface->endpoint[0].desc;
-	if (!ep || !usb_endpoint_is_int_in(ep))
+	if (!usb_endpoint_is_int_in(ep))
 		goto err;
 
 	desc->wMaxPacketSize = usb_endpoint_maxp(ep);
-	desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0;
 
 	desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
 	if (!desc->orq)
@@ -717,19 +717,13 @@
 	if (!desc->ubuf)
 		goto err;
 
-	desc->sbuf = usb_alloc_coherent(interface_to_usbdev(intf),
-					desc->wMaxPacketSize,
-					GFP_KERNEL,
-					&desc->validity->transfer_dma);
+	desc->sbuf = kmalloc(desc->wMaxPacketSize, GFP_KERNEL);
 	if (!desc->sbuf)
 		goto err;
 
-	desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf),
-					 desc->wMaxCommand,
-					 GFP_KERNEL,
-					 &desc->response->transfer_dma);
+	desc->inbuf = kmalloc(desc->wMaxCommand, GFP_KERNEL);
 	if (!desc->inbuf)
-		goto err2;
+		goto err;
 
 	usb_fill_int_urb(
 		desc->validity,
@@ -741,45 +735,149 @@
 		desc,
 		ep->bInterval
 	);
-	desc->validity->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	usb_set_intfdata(intf, desc);
+	desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
+	desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
+	desc->irq->wValue = 0;
+	desc->irq->wIndex = desc->inum;
+	desc->irq->wLength = cpu_to_le16(desc->wMaxCommand);
+
+	usb_fill_control_urb(
+		desc->response,
+		interface_to_usbdev(intf),
+		/* using common endpoint 0 */
+		usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0),
+		(unsigned char *)desc->irq,
+		desc->inbuf,
+		desc->wMaxCommand,
+		wdm_in_callback,
+		desc
+	);
+
+	desc->manage_power = manage_power;
+
+	spin_lock(&wdm_device_list_lock);
+	list_add(&desc->device_list, &wdm_device_list);
+	spin_unlock(&wdm_device_list_lock);
+
 	rv = usb_register_dev(intf, &wdm_class);
 	if (rv < 0)
-		goto err3;
+		goto err;
 	else
-		dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n",
-			intf->minor - WDM_MINOR_BASE);
+		dev_info(&intf->dev, "%s: USB WDM device\n", dev_name(intf->usb_dev));
 out:
 	return rv;
-err3:
-	usb_set_intfdata(intf, NULL);
-	usb_free_coherent(interface_to_usbdev(desc->intf),
-			  desc->bMaxPacketSize0,
-			desc->inbuf,
-			desc->response->transfer_dma);
-err2:
-	usb_free_coherent(interface_to_usbdev(desc->intf),
-			  desc->wMaxPacketSize,
-			  desc->sbuf,
-			  desc->validity->transfer_dma);
 err:
-	free_urbs(desc);
-	kfree(desc->ubuf);
-	kfree(desc->orq);
-	kfree(desc->irq);
-	kfree(desc);
+	cleanup(desc);
 	return rv;
 }
 
+static int wdm_manage_power(struct usb_interface *intf, int on)
+{
+	/* need autopm_get/put here to ensure the usbcore sees the new value */
+	int rv = usb_autopm_get_interface(intf);
+	if (rv < 0)
+		goto err;
+
+	intf->needs_remote_wakeup = on;
+	usb_autopm_put_interface(intf);
+err:
+	return rv;
+}
+
+static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	int rv = -EINVAL;
+	struct usb_host_interface *iface;
+	struct usb_endpoint_descriptor *ep;
+	struct usb_cdc_dmm_desc *dmhd;
+	u8 *buffer = intf->altsetting->extra;
+	int buflen = intf->altsetting->extralen;
+	u16 maxcom = WDM_DEFAULT_BUFSIZE;
+
+	if (!buffer)
+		goto err;
+	while (buflen > 2) {
+		if (buffer[1] != USB_DT_CS_INTERFACE) {
+			dev_err(&intf->dev, "skipping garbage\n");
+			goto next_desc;
+		}
+
+		switch (buffer[2]) {
+		case USB_CDC_HEADER_TYPE:
+			break;
+		case USB_CDC_DMM_TYPE:
+			dmhd = (struct usb_cdc_dmm_desc *)buffer;
+			maxcom = le16_to_cpu(dmhd->wMaxCommand);
+			dev_dbg(&intf->dev,
+				"Finding maximum buffer length: %d", maxcom);
+			break;
+		default:
+			dev_err(&intf->dev,
+				"Ignoring extra header, type %d, length %d\n",
+				buffer[2], buffer[0]);
+			break;
+		}
+next_desc:
+		buflen -= buffer[0];
+		buffer += buffer[0];
+	}
+
+	iface = intf->cur_altsetting;
+	if (iface->desc.bNumEndpoints != 1)
+		goto err;
+	ep = &iface->endpoint[0].desc;
+
+	rv = wdm_create(intf, ep, maxcom, &wdm_manage_power);
+
+err:
+	return rv;
+}
+
+/**
+ * usb_cdc_wdm_register - register a WDM subdriver
+ * @intf: usb interface the subdriver will associate with
+ * @ep: interrupt endpoint to monitor for notifications
+ * @bufsize: maximum message size to support for read/write
+ *
+ * Create WDM usb class character device and associate it with intf
+ * without binding, allowing another driver to manage the interface.
+ *
+ * The subdriver will manage the given interrupt endpoint exclusively
+ * and will issue control requests referring to the given intf. It
+ * will otherwise avoid interferring, and in particular not do
+ * usb_set_intfdata/usb_get_intfdata on intf.
+ *
+ * The return value is a pointer to the subdriver's struct usb_driver.
+ * The registering driver is responsible for calling this subdriver's
+ * disconnect, suspend, resume, pre_reset and post_reset methods from
+ * its own.
+ */
+struct usb_driver *usb_cdc_wdm_register(struct usb_interface *intf,
+					struct usb_endpoint_descriptor *ep,
+					int bufsize,
+					int (*manage_power)(struct usb_interface *, int))
+{
+	int rv = -EINVAL;
+
+	rv = wdm_create(intf, ep, bufsize, manage_power);
+	if (rv < 0)
+		goto err;
+
+	return &wdm_driver;
+err:
+	return ERR_PTR(rv);
+}
+EXPORT_SYMBOL(usb_cdc_wdm_register);
+
 static void wdm_disconnect(struct usb_interface *intf)
 {
 	struct wdm_device *desc;
 	unsigned long flags;
 
 	usb_deregister_dev(intf, &wdm_class);
+	desc = wdm_find_device(intf);
 	mutex_lock(&wdm_mutex);
-	desc = usb_get_intfdata(intf);
 
 	/* the spinlock makes sure no new urbs are generated in the callbacks */
 	spin_lock_irqsave(&desc->iuspin, flags);
@@ -803,7 +901,7 @@
 #ifdef CONFIG_PM
 static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
 {
-	struct wdm_device *desc = usb_get_intfdata(intf);
+	struct wdm_device *desc = wdm_find_device(intf);
 	int rv = 0;
 
 	dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
@@ -853,7 +951,7 @@
 #ifdef CONFIG_PM
 static int wdm_resume(struct usb_interface *intf)
 {
-	struct wdm_device *desc = usb_get_intfdata(intf);
+	struct wdm_device *desc = wdm_find_device(intf);
 	int rv;
 
 	dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor);
@@ -867,11 +965,7 @@
 
 static int wdm_pre_reset(struct usb_interface *intf)
 {
-	struct wdm_device *desc = usb_get_intfdata(intf);
-
-	mutex_lock(&desc->rlock);
-	mutex_lock(&desc->wlock);
-	kill_urbs(desc);
+	struct wdm_device *desc = wdm_find_device(intf);
 
 	/*
 	 * we notify everybody using poll of
@@ -880,17 +974,25 @@
 	 * message from the device is lost
 	 */
 	spin_lock_irq(&desc->iuspin);
+	set_bit(WDM_RESETTING, &desc->flags);	/* inform read/write */
+	set_bit(WDM_READ, &desc->flags);	/* unblock read */
+	clear_bit(WDM_IN_USE, &desc->flags);	/* unblock write */
 	desc->rerr = -EINTR;
 	spin_unlock_irq(&desc->iuspin);
 	wake_up_all(&desc->wait);
+	mutex_lock(&desc->rlock);
+	mutex_lock(&desc->wlock);
+	kill_urbs(desc);
+	cancel_work_sync(&desc->rxwork);
 	return 0;
 }
 
 static int wdm_post_reset(struct usb_interface *intf)
 {
-	struct wdm_device *desc = usb_get_intfdata(intf);
+	struct wdm_device *desc = wdm_find_device(intf);
 	int rv;
 
+	clear_bit(WDM_RESETTING, &desc->flags);
 	rv = recover_from_urb_loss(desc);
 	mutex_unlock(&desc->wlock);
 	mutex_unlock(&desc->rlock);
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 4fee024..f8e2d6d 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -934,13 +934,8 @@
 	int rc;
 
 	/* Delayed unbind of an existing driver */
-	if (intf->dev.driver) {
-		struct usb_driver *driver =
-				to_usb_driver(intf->dev.driver);
-
-		dev_dbg(&intf->dev, "forced unbind\n");
-		usb_driver_release_interface(driver, intf);
-	}
+	if (intf->dev.driver)
+		usb_forced_unbind_intf(intf);
 
 	/* Try to rebind the interface */
 	if (!intf->dev.power.is_prepared) {
@@ -953,15 +948,13 @@
 
 #ifdef CONFIG_PM
 
-#define DO_UNBIND	0
-#define DO_REBIND	1
-
-/* Unbind drivers for @udev's interfaces that don't support suspend/resume,
- * or rebind interfaces that have been unbound, according to @action.
+/* Unbind drivers for @udev's interfaces that don't support suspend/resume
+ * There is no check for reset_resume here because it can be determined
+ * only during resume whether reset_resume is needed.
  *
  * The caller must hold @udev's device lock.
  */
-static void do_unbind_rebind(struct usb_device *udev, int action)
+static void unbind_no_pm_drivers_interfaces(struct usb_device *udev)
 {
 	struct usb_host_config	*config;
 	int			i;
@@ -972,23 +965,53 @@
 	if (config) {
 		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
 			intf = config->interface[i];
-			switch (action) {
-			case DO_UNBIND:
-				if (intf->dev.driver) {
-					drv = to_usb_driver(intf->dev.driver);
-					if (!drv->suspend || !drv->resume)
-						usb_forced_unbind_intf(intf);
-				}
-				break;
-			case DO_REBIND:
-				if (intf->needs_binding)
-					usb_rebind_intf(intf);
-				break;
+
+			if (intf->dev.driver) {
+				drv = to_usb_driver(intf->dev.driver);
+				if (!drv->suspend || !drv->resume)
+					usb_forced_unbind_intf(intf);
 			}
 		}
 	}
 }
 
+/* Unbind drivers for @udev's interfaces that failed to support reset-resume.
+ * These interfaces have the needs_binding flag set by usb_resume_interface().
+ *
+ * The caller must hold @udev's device lock.
+ */
+static void unbind_no_reset_resume_drivers_interfaces(struct usb_device *udev)
+{
+	struct usb_host_config	*config;
+	int			i;
+	struct usb_interface	*intf;
+
+	config = udev->actconfig;
+	if (config) {
+		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+			intf = config->interface[i];
+			if (intf->dev.driver && intf->needs_binding)
+				usb_forced_unbind_intf(intf);
+		}
+	}
+}
+
+static void do_rebind_interfaces(struct usb_device *udev)
+{
+	struct usb_host_config	*config;
+	int			i;
+	struct usb_interface	*intf;
+
+	config = udev->actconfig;
+	if (config) {
+		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+			intf = config->interface[i];
+			if (intf->needs_binding)
+				usb_rebind_intf(intf);
+		}
+	}
+}
+
 static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
 {
 	struct usb_device_driver	*udriver;
@@ -1278,35 +1301,48 @@
 {
 	struct usb_device	*udev = to_usb_device(dev);
 
-	do_unbind_rebind(udev, DO_UNBIND);
+	unbind_no_pm_drivers_interfaces(udev);
+
+	/* From now on we are sure all drivers support suspend/resume
+	 * but not necessarily reset_resume()
+	 * so we may still need to unbind and rebind upon resume
+	 */
 	choose_wakeup(udev, msg);
 	return usb_suspend_both(udev, msg);
 }
 
 /* The device lock is held by the PM core */
+int usb_resume_complete(struct device *dev)
+{
+	struct usb_device *udev = to_usb_device(dev);
+
+	/* For PM complete calls, all we do is rebind interfaces
+	 * whose needs_binding flag is set
+	 */
+	if (udev->state != USB_STATE_NOTATTACHED)
+		do_rebind_interfaces(udev);
+	return 0;
+}
+
+/* The device lock is held by the PM core */
 int usb_resume(struct device *dev, pm_message_t msg)
 {
 	struct usb_device	*udev = to_usb_device(dev);
 	int			status;
 
-	/* For PM complete calls, all we do is rebind interfaces */
-	if (msg.event == PM_EVENT_ON) {
-		if (udev->state != USB_STATE_NOTATTACHED)
-			do_unbind_rebind(udev, DO_REBIND);
-		status = 0;
-
-	/* For all other calls, take the device back to full power and
+	/* For all calls, take the device back to full power and
 	 * tell the PM core in case it was autosuspended previously.
-	 * Unbind the interfaces that will need rebinding later.
+	 * Unbind the interfaces that will need rebinding later,
+	 * because they fail to support reset_resume.
+	 * (This can't be done in usb_resume_interface()
+	 * above because it doesn't own the right set of locks.)
 	 */
-	} else {
-		status = usb_resume_both(udev, msg);
-		if (status == 0) {
-			pm_runtime_disable(dev);
-			pm_runtime_set_active(dev);
-			pm_runtime_enable(dev);
-			do_unbind_rebind(udev, DO_REBIND);
-		}
+	status = usb_resume_both(udev, msg);
+	if (status == 0) {
+		pm_runtime_disable(dev);
+		pm_runtime_set_active(dev);
+		pm_runtime_enable(dev);
+		unbind_no_reset_resume_drivers_interfaces(udev);
 	}
 
 	/* Avoid PM error messages for devices disconnected while suspended
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 81e2c0d9..622b4a4 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -380,6 +380,7 @@
 	return 0;
 }
 
+#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME)
 static int suspend_common(struct device *dev, bool do_wakeup)
 {
 	struct pci_dev		*pci_dev = to_pci_dev(dev);
@@ -471,6 +472,7 @@
 	}
 	return retval;
 }
+#endif	/* SLEEP || RUNTIME */
 
 #ifdef	CONFIG_PM_SLEEP
 
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index e128232..9d7fc9a 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2352,7 +2352,7 @@
 					"io mem" : "io base",
 					(unsigned long long)hcd->rsrc_start);
 	} else {
-		hcd->irq = -1;
+		hcd->irq = 0;
 		if (hcd->rsrc_start)
 			dev_info(hcd->self.controller, "%s 0x%08llx\n",
 					(hcd->driver->flags & HCD_MEMORY) ?
@@ -2508,7 +2508,7 @@
 	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 	del_timer_sync(&hcd->rh_timer);
 err_hcd_driver_start:
-	if (usb_hcd_is_primary_hcd(hcd) && hcd->irq >= 0)
+	if (usb_hcd_is_primary_hcd(hcd) && hcd->irq > 0)
 		free_irq(irqnum, hcd);
 err_request_irq:
 err_hcd_driver_setup:
@@ -2573,7 +2573,7 @@
 	del_timer_sync(&hcd->rh_timer);
 
 	if (usb_hcd_is_primary_hcd(hcd)) {
-		if (hcd->irq >= 0)
+		if (hcd->irq > 0)
 			free_irq(hcd->irq, hcd);
 	}
 
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 265c2f6..28664eb 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -62,6 +62,8 @@
 							resumed */
 	unsigned long		removed_bits[1]; /* ports with a "removed"
 							device present */
+	unsigned long		wakeup_bits[1];	/* ports that have signaled
+							remote wakeup */
 #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
 #error event_bits[] is too short!
 #endif
@@ -411,6 +413,29 @@
 		kick_khubd(hub);
 }
 
+/*
+ * Let the USB core know that a USB 3.0 device has sent a Function Wake Device
+ * Notification, which indicates it had initiated remote wakeup.
+ *
+ * USB 3.0 hubs do not report the port link state change from U3 to U0 when the
+ * device initiates resume, so the USB core will not receive notice of the
+ * resume through the normal hub interrupt URB.
+ */
+void usb_wakeup_notification(struct usb_device *hdev,
+		unsigned int portnum)
+{
+	struct usb_hub *hub;
+
+	if (!hdev)
+		return;
+
+	hub = hdev_to_hub(hdev);
+	if (hub) {
+		set_bit(portnum, hub->wakeup_bits);
+		kick_khubd(hub);
+	}
+}
+EXPORT_SYMBOL_GPL(usb_wakeup_notification);
 
 /* completion function, fires on port status changes and various faults */
 static void hub_irq(struct urb *urb)
@@ -823,12 +848,6 @@
 			clear_port_feature(hub->hdev, port1,
 					USB_PORT_FEAT_C_ENABLE);
 		}
-		if (portchange & USB_PORT_STAT_C_LINK_STATE) {
-			need_debounce_delay = true;
-			clear_port_feature(hub->hdev, port1,
-					USB_PORT_FEAT_C_PORT_LINK_STATE);
-		}
-
 		if ((portchange & USB_PORT_STAT_C_BH_RESET) &&
 				hub_is_superspeed(hub->hdev)) {
 			need_debounce_delay = true;
@@ -850,12 +869,19 @@
 				set_bit(port1, hub->change_bits);
 
 		} else if (portstatus & USB_PORT_STAT_ENABLE) {
+			bool port_resumed = (portstatus &
+					USB_PORT_STAT_LINK_STATE) ==
+				USB_SS_PORT_LS_U0;
 			/* The power session apparently survived the resume.
 			 * If there was an overcurrent or suspend change
 			 * (i.e., remote wakeup request), have khubd
-			 * take care of it.
+			 * take care of it.  Look at the port link state
+			 * for USB 3.0 hubs, since they don't have a suspend
+			 * change bit, and they don't set the port link change
+			 * bit on device-initiated resume.
 			 */
-			if (portchange)
+			if (portchange || (hub_is_superspeed(hub->hdev) &&
+						port_resumed))
 				set_bit(port1, hub->change_bits);
 
 		} else if (udev->persist_enabled) {
@@ -1021,8 +1047,10 @@
 	dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
 		(hdev->maxchild == 1) ? "" : "s");
 
+	hdev->children = kzalloc(hdev->maxchild *
+				sizeof(struct usb_device *), GFP_KERNEL);
 	hub->port_owners = kzalloc(hdev->maxchild * sizeof(void *), GFP_KERNEL);
-	if (!hub->port_owners) {
+	if (!hdev->children || !hub->port_owners) {
 		ret = -ENOMEM;
 		goto fail;
 	}
@@ -1253,7 +1281,8 @@
 
 static void hub_disconnect(struct usb_interface *intf)
 {
-	struct usb_hub *hub = usb_get_intfdata (intf);
+	struct usb_hub *hub = usb_get_intfdata(intf);
+	struct usb_device *hdev = interface_to_usbdev(intf);
 
 	/* Take the hub off the event list and don't let it be added again */
 	spin_lock_irq(&hub_event_lock);
@@ -1275,6 +1304,7 @@
 		highspeed_hubs--;
 
 	usb_free_urb(hub->urb);
+	kfree(hdev->children);
 	kfree(hub->port_owners);
 	kfree(hub->descriptor);
 	kfree(hub->status);
@@ -1293,14 +1323,8 @@
 	desc = intf->cur_altsetting;
 	hdev = interface_to_usbdev(intf);
 
-	/* Hubs have proper suspend/resume support.  USB 3.0 device suspend is
-	 * different from USB 2.0/1.1 device suspend, and unfortunately we
-	 * don't support it yet.  So leave autosuspend disabled for USB 3.0
-	 * external hubs for now.  Enable autosuspend for USB 3.0 roothubs,
-	 * since that isn't a "real" hub.
-	 */
-	if (!hub_is_superspeed(hdev) || !hdev->parent)
-		usb_enable_autosuspend(hdev);
+	/* Hubs have proper suspend/resume support. */
+	usb_enable_autosuspend(hdev);
 
 	if (hdev->level == MAX_TOPO_LEVEL) {
 		dev_err(&intf->dev,
@@ -1656,7 +1680,7 @@
 	usb_lock_device(udev);
 
 	/* Free up all the children before we remove this device */
-	for (i = 0; i < USB_MAXCHILDREN; i++) {
+	for (i = 0; i < udev->maxchild; i++) {
 		if (udev->children[i])
 			usb_disconnect(&udev->children[i]);
 	}
@@ -1842,6 +1866,37 @@
 	return err;
 }
 
+static void set_usb_port_removable(struct usb_device *udev)
+{
+	struct usb_device *hdev = udev->parent;
+	struct usb_hub *hub;
+	u8 port = udev->portnum;
+	u16 wHubCharacteristics;
+	bool removable = true;
+
+	if (!hdev)
+		return;
+
+	hub = hdev_to_hub(udev->parent);
+
+	wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
+
+	if (!(wHubCharacteristics & HUB_CHAR_COMPOUND))
+		return;
+
+	if (hub_is_superspeed(hdev)) {
+		if (hub->descriptor->u.ss.DeviceRemovable & (1 << port))
+			removable = false;
+	} else {
+		if (hub->descriptor->u.hs.DeviceRemovable[port / 8] & (1 << (port % 8)))
+			removable = false;
+	}
+
+	if (removable)
+		udev->removable = USB_DEVICE_REMOVABLE;
+	else
+		udev->removable = USB_DEVICE_FIXED;
+}
 
 /**
  * usb_new_device - perform initial device setup (usbcore-internal)
@@ -1900,6 +1955,15 @@
 	announce_device(udev);
 
 	device_enable_async_suspend(&udev->dev);
+
+	/*
+	 * check whether the hub marks this port as non-removable. Do it
+	 * now so that platform-specific data can override it in
+	 * device_add()
+	 */
+	if (udev->parent)
+		set_usb_port_removable(udev);
+
 	/* Register the device.  The device driver is responsible
 	 * for configuring the device and invoking the add-device
 	 * notifier chain (used by usbfs and possibly others).
@@ -2385,11 +2449,27 @@
 	 * we don't explicitly enable it here.
 	 */
 	if (udev->do_remote_wakeup) {
-		status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-				USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
-				USB_DEVICE_REMOTE_WAKEUP, 0,
-				NULL, 0,
-				USB_CTRL_SET_TIMEOUT);
+		if (!hub_is_superspeed(hub->hdev)) {
+			status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+					USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
+					USB_DEVICE_REMOTE_WAKEUP, 0,
+					NULL, 0,
+					USB_CTRL_SET_TIMEOUT);
+		} else {
+			/* Assume there's only one function on the USB 3.0
+			 * device and enable remote wake for the first
+			 * interface. FIXME if the interface association
+			 * descriptor shows there's more than one function.
+			 */
+			status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+					USB_REQ_SET_FEATURE,
+					USB_RECIP_INTERFACE,
+					USB_INTRF_FUNC_SUSPEND,
+					USB_INTRF_FUNC_SUSPEND_RW |
+					USB_INTRF_FUNC_SUSPEND_LP,
+					NULL, 0,
+					USB_CTRL_SET_TIMEOUT);
+		}
 		if (status) {
 			dev_dbg(&udev->dev, "won't remote wakeup, status %d\n",
 					status);
@@ -2679,6 +2759,7 @@
 	struct usb_hub		*hub = usb_get_intfdata (intf);
 	struct usb_device	*hdev = hub->hdev;
 	unsigned		port1;
+	int			status;
 
 	/* Warn if children aren't already suspended */
 	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
@@ -2691,6 +2772,17 @@
 				return -EBUSY;
 		}
 	}
+	if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) {
+		/* Enable hub to send remote wakeup for all ports. */
+		for (port1 = 1; port1 <= hdev->maxchild; port1++) {
+			status = set_port_feature(hdev,
+					port1 |
+					USB_PORT_FEAT_REMOTE_WAKE_CONNECT |
+					USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT |
+					USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT,
+					USB_PORT_FEAT_REMOTE_WAKE_MASK);
+		}
+	}
 
 	dev_dbg(&intf->dev, "%s\n", __func__);
 
@@ -3424,6 +3516,46 @@
 		hcd->driver->relinquish_port(hcd, port1);
 }
 
+/* Returns 1 if there was a remote wakeup and a connect status change. */
+static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
+		u16 portstatus, u16 portchange)
+{
+	struct usb_device *hdev;
+	struct usb_device *udev;
+	int connect_change = 0;
+	int ret;
+
+	hdev = hub->hdev;
+	udev = hdev->children[port-1];
+	if (!hub_is_superspeed(hdev)) {
+		if (!(portchange & USB_PORT_STAT_C_SUSPEND))
+			return 0;
+		clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND);
+	} else {
+		if (!udev || udev->state != USB_STATE_SUSPENDED ||
+				 (portstatus & USB_PORT_STAT_LINK_STATE) !=
+				 USB_SS_PORT_LS_U0)
+			return 0;
+	}
+
+	if (udev) {
+		/* TRSMRCY = 10 msec */
+		msleep(10);
+
+		usb_lock_device(udev);
+		ret = usb_remote_wakeup(udev);
+		usb_unlock_device(udev);
+		if (ret < 0)
+			connect_change = 1;
+	} else {
+		ret = -ENODEV;
+		hub_port_disable(hub, port, 1);
+	}
+	dev_dbg(hub->intfdev, "resume on port %d, status %d\n",
+			port, ret);
+	return connect_change;
+}
+
 static void hub_events(void)
 {
 	struct list_head *tmp;
@@ -3436,7 +3568,7 @@
 	u16 portstatus;
 	u16 portchange;
 	int i, ret;
-	int connect_change;
+	int connect_change, wakeup_change;
 
 	/*
 	 *  We restart the list every time to avoid a deadlock with
@@ -3515,8 +3647,9 @@
 			if (test_bit(i, hub->busy_bits))
 				continue;
 			connect_change = test_bit(i, hub->change_bits);
+			wakeup_change = test_and_clear_bit(i, hub->wakeup_bits);
 			if (!test_and_clear_bit(i, hub->event_bits) &&
-					!connect_change)
+					!connect_change && !wakeup_change)
 				continue;
 
 			ret = hub_port_status(hub, i,
@@ -3557,31 +3690,10 @@
 				}
 			}
 
-			if (portchange & USB_PORT_STAT_C_SUSPEND) {
-				struct usb_device *udev;
+			if (hub_handle_remote_wakeup(hub, i,
+						portstatus, portchange))
+				connect_change = 1;
 
-				clear_port_feature(hdev, i,
-					USB_PORT_FEAT_C_SUSPEND);
-				udev = hdev->children[i-1];
-				if (udev) {
-					/* TRSMRCY = 10 msec */
-					msleep(10);
-
-					usb_lock_device(udev);
-					ret = usb_remote_wakeup(hdev->
-							children[i-1]);
-					usb_unlock_device(udev);
-					if (ret < 0)
-						connect_change = 1;
-				} else {
-					ret = -ENODEV;
-					hub_port_disable(hub, i, 1);
-				}
-				dev_dbg (hub_dev,
-					"resume on port %d, status %d\n",
-					i, ret);
-			}
-			
 			if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
 				u16 status = 0;
 				u16 unused;
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 9e491ca..566d9f9 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -230,6 +230,28 @@
 }
 static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL);
 
+static ssize_t
+show_removable(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_device *udev;
+	char *state;
+
+	udev = to_usb_device(dev);
+
+	switch (udev->removable) {
+	case USB_DEVICE_REMOVABLE:
+		state = "removable";
+		break;
+	case USB_DEVICE_FIXED:
+		state = "fixed";
+		break;
+	default:
+		state = "unknown";
+	}
+
+	return sprintf(buf, "%s\n", state);
+}
+static DEVICE_ATTR(removable, S_IRUGO, show_removable, NULL);
 
 #ifdef	CONFIG_PM
 
@@ -626,6 +648,7 @@
 	&dev_attr_avoid_reset_quirk.attr,
 	&dev_attr_authorized.attr,
 	&dev_attr_remove.attr,
+	&dev_attr_removable.attr,
 	NULL,
 };
 static struct attribute_group dev_attr_grp = {
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 909625b..7239a73 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -403,20 +403,17 @@
 	 * cause problems in HCDs if they get it wrong.
 	 */
 	{
-	unsigned int	orig_flags = urb->transfer_flags;
 	unsigned int	allowed;
 	static int pipetypes[4] = {
 		PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
 	};
 
 	/* Check that the pipe's type matches the endpoint's type */
-	if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) {
-		dev_err(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
+	if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
+		dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
 			usb_pipetype(urb->pipe), pipetypes[xfertype]);
-		return -EPIPE;		/* The most suitable error code :-) */
-	}
 
-	/* enforce simple/standard policy */
+	/* Check against a simple/standard policy */
 	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK |
 			URB_FREE_BUFFER);
 	switch (xfertype) {
@@ -435,14 +432,12 @@
 		allowed |= URB_ISO_ASAP;
 		break;
 	}
-	urb->transfer_flags &= allowed;
+	allowed &= urb->transfer_flags;
 
-	/* fail if submitter gave bogus flags */
-	if (urb->transfer_flags != orig_flags) {
-		dev_err(&dev->dev, "BOGUS urb flags, %x --> %x\n",
-			orig_flags, urb->transfer_flags);
-		return -EINVAL;
-	}
+	/* warn if submitter gave bogus flags */
+	if (allowed != urb->transfer_flags)
+		dev_WARN(&dev->dev, "BOGUS urb flags, %x --> %x\n",
+			urb->transfer_flags, allowed);
 	}
 #endif
 	/*
@@ -532,10 +527,13 @@
  * a driver's I/O routines to insure that all URB-related activity has
  * completed before it returns.
  *
- * This request is always asynchronous.  Success is indicated by
- * returning -EINPROGRESS, at which time the URB will probably not yet
- * have been given back to the device driver.  When it is eventually
- * called, the completion function will see @urb->status == -ECONNRESET.
+ * This request is asynchronous, however the HCD might call the ->complete()
+ * callback during unlink. Therefore when drivers call usb_unlink_urb(), they
+ * must not hold any locks that may be taken by the completion function.
+ * Success is indicated by returning -EINPROGRESS, at which time the URB will
+ * probably not yet have been given back to the device driver. When it is
+ * eventually called, the completion function will see @urb->status ==
+ * -ECONNRESET.
  * Failure is indicated by usb_unlink_urb() returning any other value.
  * Unlinking will fail when @urb is not currently "linked" (i.e., it was
  * never submitted, or it was unlinked before, or the hardware is already
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 8ca9f99..c74ba7b 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -274,7 +274,7 @@
 static void usb_dev_complete(struct device *dev)
 {
 	/* Currently used only for rebinding interfaces */
-	usb_resume(dev, PMSG_ON);	/* FIXME: change to PMSG_COMPLETE */
+	usb_resume_complete(dev);
 }
 
 static int usb_dev_suspend(struct device *dev)
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 45e8479..71648dc 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -56,6 +56,7 @@
 
 extern int usb_suspend(struct device *dev, pm_message_t msg);
 extern int usb_resume(struct device *dev, pm_message_t msg);
+extern int usb_resume_complete(struct device *dev);
 
 extern int usb_port_suspend(struct usb_device *dev, pm_message_t msg);
 extern int usb_port_resume(struct usb_device *dev, pm_message_t msg);
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 900ae74..d441fe4 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -28,6 +28,19 @@
 
 obj-$(CONFIG_USB_DWC3)		+= dwc3-omap.o
 
+##
+# REVISIT Samsung Exynos platform needs the clk API which isn't
+# defined on all architectures. If we allow dwc3-exynos.c compile
+# always we will fail the linking phase on those architectures
+# which don't provide clk api implementation and that's unnaceptable.
+#
+# When Samsung's platform start supporting pm_runtime, this check
+# for HAVE_CLK should be removed.
+##
+ifneq ($(CONFIG_HAVE_CLK),)
+	obj-$(CONFIG_USB_DWC3)		+= dwc3-exynos.o
+endif
+
 ifneq ($(CONFIG_PCI),)
 	obj-$(CONFIG_USB_DWC3)		+= dwc3-pci.o
 endif
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 7c9df63..7bd815a 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -48,10 +48,10 @@
 #include <linux/list.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
+#include <linux/of.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-#include <linux/module.h>
 
 #include "core.h"
 #include "gadget.h"
@@ -86,7 +86,7 @@
 		id = -ENOMEM;
 	}
 
-	return 0;
+	return id;
 }
 EXPORT_SYMBOL_GPL(dwc3_get_device_id);
 
@@ -167,11 +167,11 @@
 }
 
 /**
- * dwc3_alloc_one_event_buffer - Allocated one event buffer structure
+ * dwc3_alloc_one_event_buffer - Allocates one event buffer structure
  * @dwc: Pointer to our controller context structure
  * @length: size of the event buffer
  *
- * Returns a pointer to the allocated event buffer structure on succes
+ * Returns a pointer to the allocated event buffer structure on success
  * otherwise ERR_PTR(errno).
  */
 static struct dwc3_event_buffer *__devinit
@@ -215,10 +215,10 @@
 
 /**
  * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length
- * @dwc: Pointer to out controller context structure
+ * @dwc: pointer to our controller context structure
  * @length: size of event buffer
  *
- * Returns 0 on success otherwise negative errno. In error the case, dwc
+ * Returns 0 on success otherwise negative errno. In the error case, dwc
  * may contain some buffers allocated but not all which were requested.
  */
 static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
@@ -251,7 +251,7 @@
 
 /**
  * dwc3_event_buffers_setup - setup our allocated event buffers
- * @dwc: Pointer to out controller context structure
+ * @dwc: pointer to our controller context structure
  *
  * Returns 0 on success otherwise negative errno.
  */
@@ -350,7 +350,7 @@
 	dwc3_cache_hwparams(dwc);
 
 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
-	reg &= ~DWC3_GCTL_SCALEDOWN(3);
+	reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
 	reg &= ~DWC3_GCTL_DISSCRAMBLE;
 
 	switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
@@ -363,9 +363,9 @@
 
 	/*
 	 * WORKAROUND: DWC3 revisions <1.90a have a bug
-	 * when The device fails to connect at SuperSpeed
+	 * where the device can fail to connect at SuperSpeed
 	 * and falls back to high-speed mode which causes
-	 * the device to enter in a Connect/Disconnect loop
+	 * the device to enter a Connect/Disconnect loop
 	 */
 	if (dwc->revision < DWC3_REVISION_190A)
 		reg |= DWC3_GCTL_U2RSTECN;
@@ -404,8 +404,10 @@
 
 static int __devinit dwc3_probe(struct platform_device *pdev)
 {
+	struct device_node	*node = pdev->dev.of_node;
 	struct resource		*res;
 	struct dwc3		*dwc;
+	struct device		*dev = &pdev->dev;
 
 	int			ret = -ENOMEM;
 	int			irq;
@@ -415,39 +417,39 @@
 
 	u8			mode;
 
-	mem = kzalloc(sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
+	mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
 	if (!mem) {
-		dev_err(&pdev->dev, "not enough memory\n");
-		goto err0;
+		dev_err(dev, "not enough memory\n");
+		return -ENOMEM;
 	}
 	dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
 	dwc->mem = mem;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
-		dev_err(&pdev->dev, "missing resource\n");
-		goto err1;
+		dev_err(dev, "missing resource\n");
+		return -ENODEV;
 	}
 
 	dwc->res = res;
 
-	res = request_mem_region(res->start, resource_size(res),
-			dev_name(&pdev->dev));
+	res = devm_request_mem_region(dev, res->start, resource_size(res),
+			dev_name(dev));
 	if (!res) {
-		dev_err(&pdev->dev, "can't request mem region\n");
-		goto err1;
+		dev_err(dev, "can't request mem region\n");
+		return -ENOMEM;
 	}
 
-	regs = ioremap(res->start, resource_size(res));
+	regs = devm_ioremap(dev, res->start, resource_size(res));
 	if (!regs) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		goto err2;
+		dev_err(dev, "ioremap failed\n");
+		return -ENOMEM;
 	}
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
-		dev_err(&pdev->dev, "missing IRQ\n");
-		goto err3;
+		dev_err(dev, "missing IRQ\n");
+		return -ENODEV;
 	}
 
 	spin_lock_init(&dwc->lock);
@@ -455,7 +457,7 @@
 
 	dwc->regs	= regs;
 	dwc->regs_size	= resource_size(res);
-	dwc->dev	= &pdev->dev;
+	dwc->dev	= dev;
 	dwc->irq	= irq;
 
 	if (!strncmp("super", maximum_speed, 5))
@@ -469,14 +471,17 @@
 	else
 		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
 
-	pm_runtime_enable(&pdev->dev);
-	pm_runtime_get_sync(&pdev->dev);
-	pm_runtime_forbid(&pdev->dev);
+	if (of_get_property(node, "tx-fifo-resize", NULL))
+		dwc->needs_fifo_resize = true;
+
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
+	pm_runtime_forbid(dev);
 
 	ret = dwc3_core_init(dwc);
 	if (ret) {
-		dev_err(&pdev->dev, "failed to initialize core\n");
-		goto err3;
+		dev_err(dev, "failed to initialize core\n");
+		return ret;
 	}
 
 	mode = DWC3_MODE(dwc->hwparams.hwparams0);
@@ -486,49 +491,49 @@
 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
 		ret = dwc3_gadget_init(dwc);
 		if (ret) {
-			dev_err(&pdev->dev, "failed to initialize gadget\n");
-			goto err4;
+			dev_err(dev, "failed to initialize gadget\n");
+			goto err1;
 		}
 		break;
 	case DWC3_MODE_HOST:
 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
 		ret = dwc3_host_init(dwc);
 		if (ret) {
-			dev_err(&pdev->dev, "failed to initialize host\n");
-			goto err4;
+			dev_err(dev, "failed to initialize host\n");
+			goto err1;
 		}
 		break;
 	case DWC3_MODE_DRD:
 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
 		ret = dwc3_host_init(dwc);
 		if (ret) {
-			dev_err(&pdev->dev, "failed to initialize host\n");
-			goto err4;
+			dev_err(dev, "failed to initialize host\n");
+			goto err1;
 		}
 
 		ret = dwc3_gadget_init(dwc);
 		if (ret) {
-			dev_err(&pdev->dev, "failed to initialize gadget\n");
-			goto err4;
+			dev_err(dev, "failed to initialize gadget\n");
+			goto err1;
 		}
 		break;
 	default:
-		dev_err(&pdev->dev, "Unsupported mode of operation %d\n", mode);
-		goto err4;
+		dev_err(dev, "Unsupported mode of operation %d\n", mode);
+		goto err1;
 	}
 	dwc->mode = mode;
 
 	ret = dwc3_debugfs_init(dwc);
 	if (ret) {
-		dev_err(&pdev->dev, "failed to initialize debugfs\n");
-		goto err5;
+		dev_err(dev, "failed to initialize debugfs\n");
+		goto err2;
 	}
 
-	pm_runtime_allow(&pdev->dev);
+	pm_runtime_allow(dev);
 
 	return 0;
 
-err5:
+err2:
 	switch (mode) {
 	case DWC3_MODE_DEVICE:
 		dwc3_gadget_exit(dwc);
@@ -545,19 +550,9 @@
 		break;
 	}
 
-err4:
+err1:
 	dwc3_core_exit(dwc);
 
-err3:
-	iounmap(regs);
-
-err2:
-	release_mem_region(res->start, resource_size(res));
-
-err1:
-	kfree(dwc->mem);
-
-err0:
 	return ret;
 }
 
@@ -590,9 +585,6 @@
 	}
 
 	dwc3_core_exit(dwc);
-	release_mem_region(res->start, resource_size(res));
-	iounmap(dwc->regs);
-	kfree(dwc->mem);
 
 	return 0;
 }
@@ -605,19 +597,9 @@
 	},
 };
 
+module_platform_driver(dwc3_driver);
+
 MODULE_ALIAS("platform:dwc3");
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
-
-static int __devinit dwc3_init(void)
-{
-	return platform_driver_register(&dwc3_driver);
-}
-module_init(dwc3_init);
-
-static void __exit dwc3_exit(void)
-{
-	platform_driver_unregister(&dwc3_driver);
-}
-module_exit(dwc3_exit);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 9e57f8e..6c7945b 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -145,22 +145,23 @@
 /* Bit fields */
 
 /* Global Configuration Register */
-#define DWC3_GCTL_PWRDNSCALE(n)	(n << 19)
+#define DWC3_GCTL_PWRDNSCALE(n)	((n) << 19)
 #define DWC3_GCTL_U2RSTECN	(1 << 16)
-#define DWC3_GCTL_RAMCLKSEL(x)	((x & DWC3_GCTL_CLK_MASK) << 6)
+#define DWC3_GCTL_RAMCLKSEL(x)	(((x) & DWC3_GCTL_CLK_MASK) << 6)
 #define DWC3_GCTL_CLK_BUS	(0)
 #define DWC3_GCTL_CLK_PIPE	(1)
 #define DWC3_GCTL_CLK_PIPEHALF	(2)
 #define DWC3_GCTL_CLK_MASK	(3)
 
 #define DWC3_GCTL_PRTCAP(n)	(((n) & (3 << 12)) >> 12)
-#define DWC3_GCTL_PRTCAPDIR(n)	(n << 12)
+#define DWC3_GCTL_PRTCAPDIR(n)	((n) << 12)
 #define DWC3_GCTL_PRTCAP_HOST	1
 #define DWC3_GCTL_PRTCAP_DEVICE	2
 #define DWC3_GCTL_PRTCAP_OTG	3
 
 #define DWC3_GCTL_CORESOFTRESET	(1 << 11)
-#define DWC3_GCTL_SCALEDOWN(n)	(n << 4)
+#define DWC3_GCTL_SCALEDOWN(n)	((n) << 4)
+#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3)
 #define DWC3_GCTL_DISSCRAMBLE	(1 << 3)
 #define DWC3_GCTL_DSBLCLKGTNG	(1 << 0)
 
@@ -172,8 +173,12 @@
 #define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31)
 #define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17)
 
+/* Global TX Fifo Size Register */
+#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff)
+#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000)
+
 /* Global HWPARAMS1 Register */
-#define DWC3_GHWPARAMS1_EN_PWROPT(n)	((n & (3 << 24)) >> 24)
+#define DWC3_GHWPARAMS1_EN_PWROPT(n)	(((n) & (3 << 24)) >> 24)
 #define DWC3_GHWPARAMS1_EN_PWROPT_NO	0
 #define DWC3_GHWPARAMS1_EN_PWROPT_CLK	1
 
@@ -198,6 +203,15 @@
 
 #define DWC3_DCTL_APPL1RES	(1 << 23)
 
+#define DWC3_DCTL_TRGTULST_MASK	(0x0f << 17)
+#define DWC3_DCTL_TRGTULST(n)	((n) << 17)
+
+#define DWC3_DCTL_TRGTULST_U2	(DWC3_DCTL_TRGTULST(2))
+#define DWC3_DCTL_TRGTULST_U3	(DWC3_DCTL_TRGTULST(3))
+#define DWC3_DCTL_TRGTULST_SS_DIS (DWC3_DCTL_TRGTULST(4))
+#define DWC3_DCTL_TRGTULST_RX_DET (DWC3_DCTL_TRGTULST(5))
+#define DWC3_DCTL_TRGTULST_SS_INACT (DWC3_DCTL_TRGTULST(6))
+
 #define DWC3_DCTL_INITU2ENA	(1 << 12)
 #define DWC3_DCTL_ACCEPTU2ENA	(1 << 11)
 #define DWC3_DCTL_INITU1ENA	(1 << 10)
@@ -260,10 +274,10 @@
 
 /* Device Endpoint Command Register */
 #define DWC3_DEPCMD_PARAM_SHIFT		16
-#define DWC3_DEPCMD_PARAM(x)		(x << DWC3_DEPCMD_PARAM_SHIFT)
-#define DWC3_DEPCMD_GET_RSC_IDX(x)	((x >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f)
+#define DWC3_DEPCMD_PARAM(x)		((x) << DWC3_DEPCMD_PARAM_SHIFT)
+#define DWC3_DEPCMD_GET_RSC_IDX(x)     (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f)
 #define DWC3_DEPCMD_STATUS_MASK		(0x0f << 12)
-#define DWC3_DEPCMD_STATUS(x)		((x & DWC3_DEPCMD_STATUS_MASK) >> 12)
+#define DWC3_DEPCMD_STATUS(x)		(((x) & DWC3_DEPCMD_STATUS_MASK) >> 12)
 #define DWC3_DEPCMD_HIPRI_FORCERM	(1 << 11)
 #define DWC3_DEPCMD_CMDACT		(1 << 10)
 #define DWC3_DEPCMD_CMDIOC		(1 << 8)
@@ -288,7 +302,7 @@
 
 /* Structures */
 
-struct dwc3_trb_hw;
+struct dwc3_trb;
 
 /**
  * struct dwc3_event_buffer - Software event buffer representation
@@ -343,7 +357,7 @@
 	struct list_head	request_list;
 	struct list_head	req_queued;
 
-	struct dwc3_trb_hw	*trb_pool;
+	struct dwc3_trb		*trb_pool;
 	dma_addr_t		trb_pool_dma;
 	u32			free_slot;
 	u32			busy_slot;
@@ -418,102 +432,49 @@
 	DWC3_CONFIGURED_STATE,
 };
 
-/**
- * struct dwc3_trb - transfer request block
- * @bpl: lower 32bit of the buffer
- * @bph: higher 32bit of the buffer
- * @length: buffer size (up to 16mb - 1)
- * @pcm1: packet count m1
- * @trbsts: trb status
- *	0 = ok
- *	1 = missed isoc
- *	2 = setup pending
- * @hwo: hardware owner of descriptor
- * @lst: last trb
- * @chn: chain buffers
- * @csp: continue on short packets (only supported on isoc eps)
- * @trbctl: trb control
- *	1 = normal
- *	2 = control-setup
- *	3 = control-status-2
- *	4 = control-status-3
- *	5 = control-data (first trb of data stage)
- *	6 = isochronous-first (first trb of service interval)
- *	7 = isochronous
- *	8 = link trb
- *	others = reserved
- * @isp_imi: interrupt on short packet / interrupt on missed isoc
- * @ioc: interrupt on complete
- * @sid_sofn: Stream ID / SOF Number
- */
-struct dwc3_trb {
-	u64             bplh;
+/* TRB Length, PCM and Status */
+#define DWC3_TRB_SIZE_MASK	(0x00ffffff)
+#define DWC3_TRB_SIZE_LENGTH(n)	((n) & DWC3_TRB_SIZE_MASK)
+#define DWC3_TRB_SIZE_PCM1(n)	(((n) & 0x03) << 24)
+#define DWC3_TRB_SIZE_TRBSTS(n)	(((n) & (0x0f << 28) >> 28))
 
-	union {
-		struct {
-			u32             length:24;
-			u32             pcm1:2;
-			u32             reserved27_26:2;
-			u32             trbsts:4;
-#define DWC3_TRB_STS_OKAY                       0
-#define DWC3_TRB_STS_MISSED_ISOC                1
-#define DWC3_TRB_STS_SETUP_PENDING              2
-		};
-		u32 len_pcm;
-	};
+#define DWC3_TRBSTS_OK			0
+#define DWC3_TRBSTS_MISSED_ISOC		1
+#define DWC3_TRBSTS_SETUP_PENDING	2
 
-	union {
-		struct {
-			u32             hwo:1;
-			u32             lst:1;
-			u32             chn:1;
-			u32             csp:1;
-			u32             trbctl:6;
-			u32             isp_imi:1;
-			u32             ioc:1;
-			u32             reserved13_12:2;
-			u32             sid_sofn:16;
-			u32             reserved31_30:2;
-		};
-		u32 control;
-	};
-} __packed;
+/* TRB Control */
+#define DWC3_TRB_CTRL_HWO		(1 << 0)
+#define DWC3_TRB_CTRL_LST		(1 << 1)
+#define DWC3_TRB_CTRL_CHN		(1 << 2)
+#define DWC3_TRB_CTRL_CSP		(1 << 3)
+#define DWC3_TRB_CTRL_TRBCTL(n)		(((n) & 0x3f) << 4)
+#define DWC3_TRB_CTRL_ISP_IMI		(1 << 10)
+#define DWC3_TRB_CTRL_IOC		(1 << 11)
+#define DWC3_TRB_CTRL_SID_SOFN(n)	(((n) & 0xffff) << 14)
+
+#define DWC3_TRBCTL_NORMAL		DWC3_TRB_CTRL_TRBCTL(1)
+#define DWC3_TRBCTL_CONTROL_SETUP	DWC3_TRB_CTRL_TRBCTL(2)
+#define DWC3_TRBCTL_CONTROL_STATUS2	DWC3_TRB_CTRL_TRBCTL(3)
+#define DWC3_TRBCTL_CONTROL_STATUS3	DWC3_TRB_CTRL_TRBCTL(4)
+#define DWC3_TRBCTL_CONTROL_DATA	DWC3_TRB_CTRL_TRBCTL(5)
+#define DWC3_TRBCTL_ISOCHRONOUS_FIRST	DWC3_TRB_CTRL_TRBCTL(6)
+#define DWC3_TRBCTL_ISOCHRONOUS		DWC3_TRB_CTRL_TRBCTL(7)
+#define DWC3_TRBCTL_LINK_TRB		DWC3_TRB_CTRL_TRBCTL(8)
 
 /**
- * struct dwc3_trb_hw - transfer request block (hw format)
+ * struct dwc3_trb - transfer request block (hw format)
  * @bpl: DW0-3
  * @bph: DW4-7
  * @size: DW8-B
  * @trl: DWC-F
  */
-struct dwc3_trb_hw {
-	__le32		bpl;
-	__le32		bph;
-	__le32		size;
-	__le32		ctrl;
+struct dwc3_trb {
+	u32		bpl;
+	u32		bph;
+	u32		size;
+	u32		ctrl;
 } __packed;
 
-static inline void dwc3_trb_to_hw(struct dwc3_trb *nat, struct dwc3_trb_hw *hw)
-{
-	hw->bpl = cpu_to_le32(lower_32_bits(nat->bplh));
-	hw->bph = cpu_to_le32(upper_32_bits(nat->bplh));
-	hw->size = cpu_to_le32p(&nat->len_pcm);
-	/* HWO is written last */
-	hw->ctrl = cpu_to_le32p(&nat->control);
-}
-
-static inline void dwc3_trb_to_nat(struct dwc3_trb_hw *hw, struct dwc3_trb *nat)
-{
-	u64 bplh;
-
-	bplh = le32_to_cpup(&hw->bpl);
-	bplh |= (u64) le32_to_cpup(&hw->bph) << 32;
-	nat->bplh = bplh;
-
-	nat->len_pcm = le32_to_cpup(&hw->size);
-	nat->control = le32_to_cpup(&hw->ctrl);
-}
-
 /**
  * dwc3_hwparams - copy of HWPARAMS registers
  * @hwparams0 - GHWPARAMS0
@@ -546,8 +507,13 @@
 #define DWC3_MODE_DRD		2
 #define DWC3_MODE_HUB		3
 
+#define DWC3_MDWIDTH(n)		(((n) & 0xff00) >> 8)
+
 /* HWPARAMS1 */
-#define DWC3_NUM_INT(n)	(((n) & (0x3f << 15)) >> 15)
+#define DWC3_NUM_INT(n)		(((n) & (0x3f << 15)) >> 15)
+
+/* HWPARAMS7 */
+#define DWC3_RAM1_DEPTH(n)	((n) & 0xffff)
 
 struct dwc3_request {
 	struct usb_request	request;
@@ -555,7 +521,7 @@
 	struct dwc3_ep		*dep;
 
 	u8			epnum;
-	struct dwc3_trb_hw	*trb;
+	struct dwc3_trb		*trb;
 	dma_addr_t		trb_dma;
 
 	unsigned		direction:1;
@@ -572,7 +538,6 @@
  * @ctrl_req_addr: dma address of ctrl_req
  * @ep0_trb: dma address of ep0_trb
  * @ep0_usb_req: dummy req used while handling STD USB requests
- * @setup_buf_addr: dma address of setup_buf
  * @ep0_bounce_addr: dma address of ep0_bounce
  * @lock: for synchronizing
  * @dev: pointer to our struct device
@@ -594,6 +559,8 @@
  * @ep0_expect_in: true when we expect a DATA IN transfer
  * @start_config_issued: true when StartConfig command has been issued
  * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
+ * @needs_fifo_resize: not all users might want fifo resizing, flag it
+ * @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes.
  * @ep0_next_event: hold the next expected event
  * @ep0state: state of endpoint zero
  * @link_state: link state
@@ -604,12 +571,11 @@
  */
 struct dwc3 {
 	struct usb_ctrlrequest	*ctrl_req;
-	struct dwc3_trb_hw	*ep0_trb;
+	struct dwc3_trb		*ep0_trb;
 	void			*ep0_bounce;
 	u8			*setup_buf;
 	dma_addr_t		ctrl_req_addr;
 	dma_addr_t		ep0_trb_addr;
-	dma_addr_t		setup_buf_addr;
 	dma_addr_t		ep0_bounce_addr;
 	struct dwc3_request	ep0_usb_req;
 	/* device lock */
@@ -651,6 +617,8 @@
 	unsigned		start_config_issued:1;
 	unsigned		setup_packet_pending:1;
 	unsigned		delayed_status:1;
+	unsigned		needs_fifo_resize:1;
+	unsigned		resize_fifos:1;
 
 	enum dwc3_ep0_next	ep0_next_event;
 	enum dwc3_ep0_state	ep0state;
@@ -662,23 +630,13 @@
 
 	struct dwc3_hwparams	hwparams;
 	struct dentry		*root;
+
+	u8			test_mode;
+	u8			test_mode_nr;
 };
 
 /* -------------------------------------------------------------------------- */
 
-#define DWC3_TRBSTS_OK			0
-#define DWC3_TRBSTS_MISSED_ISOC		1
-#define DWC3_TRBSTS_SETUP_PENDING	2
-
-#define DWC3_TRBCTL_NORMAL		1
-#define DWC3_TRBCTL_CONTROL_SETUP	2
-#define DWC3_TRBCTL_CONTROL_STATUS2	3
-#define DWC3_TRBCTL_CONTROL_STATUS3	4
-#define DWC3_TRBCTL_CONTROL_DATA	5
-#define DWC3_TRBCTL_ISOCHRONOUS_FIRST	6
-#define DWC3_TRBCTL_ISOCHRONOUS		7
-#define DWC3_TRBCTL_LINK_TRB		8
-
 /* -------------------------------------------------------------------------- */
 
 struct dwc3_event_type {
@@ -719,9 +677,14 @@
 	u32	endpoint_event:4;
 	u32	reserved11_10:2;
 	u32	status:4;
-#define DEPEVT_STATUS_BUSERR    (1 << 0)
-#define DEPEVT_STATUS_SHORT     (1 << 1)
-#define DEPEVT_STATUS_IOC       (1 << 2)
+
+/* Within XferNotReady */
+#define DEPEVT_STATUS_TRANSFER_ACTIVE	(1 << 3)
+
+/* Within XferComplete */
+#define DEPEVT_STATUS_BUSERR	(1 << 0)
+#define DEPEVT_STATUS_SHORT	(1 << 1)
+#define DEPEVT_STATUS_IOC	(1 << 2)
 #define DEPEVT_STATUS_LST	(1 << 3)
 
 /* Stream event only */
@@ -807,6 +770,7 @@
 
 /* prototypes */
 void dwc3_set_mode(struct dwc3 *dwc, u32 mode);
+int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc);
 
 int dwc3_host_init(struct dwc3 *dwc);
 void dwc3_host_exit(struct dwc3 *dwc);
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index 433c97c..d4a30f1 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -46,6 +46,8 @@
 #include <linux/delay.h>
 #include <linux/uaccess.h>
 
+#include <linux/usb/ch9.h>
+
 #include "core.h"
 #include "gadget.h"
 #include "io.h"
@@ -464,6 +466,192 @@
 	.release		= single_release,
 };
 
+static int dwc3_testmode_show(struct seq_file *s, void *unused)
+{
+	struct dwc3		*dwc = s->private;
+	unsigned long		flags;
+	u32			reg;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+	reg &= DWC3_DCTL_TSTCTRL_MASK;
+	reg >>= 1;
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	switch (reg) {
+	case 0:
+		seq_printf(s, "no test\n");
+		break;
+	case TEST_J:
+		seq_printf(s, "test_j\n");
+		break;
+	case TEST_K:
+		seq_printf(s, "test_k\n");
+		break;
+	case TEST_SE0_NAK:
+		seq_printf(s, "test_se0_nak\n");
+		break;
+	case TEST_PACKET:
+		seq_printf(s, "test_packet\n");
+		break;
+	case TEST_FORCE_EN:
+		seq_printf(s, "test_force_enable\n");
+		break;
+	default:
+		seq_printf(s, "UNKNOWN %d\n", reg);
+	}
+
+	return 0;
+}
+
+static int dwc3_testmode_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dwc3_testmode_show, inode->i_private);
+}
+
+static ssize_t dwc3_testmode_write(struct file *file,
+		const char __user *ubuf, size_t count, loff_t *ppos)
+{
+	struct seq_file		*s = file->private_data;
+	struct dwc3		*dwc = s->private;
+	unsigned long		flags;
+	u32			testmode = 0;
+	char			buf[32];
+
+	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+		return -EFAULT;
+
+	if (!strncmp(buf, "test_j", 6))
+		testmode = TEST_J;
+	else if (!strncmp(buf, "test_k", 6))
+		testmode = TEST_K;
+	else if (!strncmp(buf, "test_se0_nak", 12))
+		testmode = TEST_SE0_NAK;
+	else if (!strncmp(buf, "test_packet", 11))
+		testmode = TEST_PACKET;
+	else if (!strncmp(buf, "test_force_enable", 17))
+		testmode = TEST_FORCE_EN;
+	else
+		testmode = 0;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+	dwc3_gadget_set_test_mode(dwc, testmode);
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	return count;
+}
+
+static const struct file_operations dwc3_testmode_fops = {
+	.open			= dwc3_testmode_open,
+	.write			= dwc3_testmode_write,
+	.read			= seq_read,
+	.llseek			= seq_lseek,
+	.release		= single_release,
+};
+
+static int dwc3_link_state_show(struct seq_file *s, void *unused)
+{
+	struct dwc3		*dwc = s->private;
+	unsigned long		flags;
+	enum dwc3_link_state	state;
+	u32			reg;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+	reg = dwc3_readl(dwc->regs, DWC3_DSTS);
+	state = DWC3_DSTS_USBLNKST(reg);
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	switch (state) {
+	case DWC3_LINK_STATE_U0:
+		seq_printf(s, "U0\n");
+		break;
+	case DWC3_LINK_STATE_U1:
+		seq_printf(s, "U1\n");
+		break;
+	case DWC3_LINK_STATE_U2:
+		seq_printf(s, "U2\n");
+		break;
+	case DWC3_LINK_STATE_U3:
+		seq_printf(s, "U3\n");
+		break;
+	case DWC3_LINK_STATE_SS_DIS:
+		seq_printf(s, "SS.Disabled\n");
+		break;
+	case DWC3_LINK_STATE_RX_DET:
+		seq_printf(s, "Rx.Detect\n");
+		break;
+	case DWC3_LINK_STATE_SS_INACT:
+		seq_printf(s, "SS.Inactive\n");
+		break;
+	case DWC3_LINK_STATE_POLL:
+		seq_printf(s, "Poll\n");
+		break;
+	case DWC3_LINK_STATE_RECOV:
+		seq_printf(s, "Recovery\n");
+		break;
+	case DWC3_LINK_STATE_HRESET:
+		seq_printf(s, "HRESET\n");
+		break;
+	case DWC3_LINK_STATE_CMPLY:
+		seq_printf(s, "Compliance\n");
+		break;
+	case DWC3_LINK_STATE_LPBK:
+		seq_printf(s, "Loopback\n");
+		break;
+	default:
+		seq_printf(s, "UNKNOWN %d\n", reg);
+	}
+
+	return 0;
+}
+
+static int dwc3_link_state_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dwc3_link_state_show, inode->i_private);
+}
+
+static ssize_t dwc3_link_state_write(struct file *file,
+		const char __user *ubuf, size_t count, loff_t *ppos)
+{
+	struct seq_file		*s = file->private_data;
+	struct dwc3		*dwc = s->private;
+	unsigned long		flags;
+	enum dwc3_link_state	state = 0;
+	char			buf[32];
+
+	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+		return -EFAULT;
+
+	if (!strncmp(buf, "SS.Disabled", 11))
+		state = DWC3_LINK_STATE_SS_DIS;
+	else if (!strncmp(buf, "Rx.Detect", 9))
+		state = DWC3_LINK_STATE_RX_DET;
+	else if (!strncmp(buf, "SS.Inactive", 11))
+		state = DWC3_LINK_STATE_SS_INACT;
+	else if (!strncmp(buf, "Recovery", 8))
+		state = DWC3_LINK_STATE_RECOV;
+	else if (!strncmp(buf, "Compliance", 10))
+		state = DWC3_LINK_STATE_CMPLY;
+	else if (!strncmp(buf, "Loopback", 8))
+		state = DWC3_LINK_STATE_LPBK;
+	else
+		return -EINVAL;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+	dwc3_gadget_set_link_state(dwc, state);
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	return count;
+}
+
+static const struct file_operations dwc3_link_state_fops = {
+	.open			= dwc3_link_state_open,
+	.write			= dwc3_link_state_write,
+	.read			= seq_read,
+	.llseek			= seq_lseek,
+	.release		= single_release,
+};
+
 int __devinit dwc3_debugfs_init(struct dwc3 *dwc)
 {
 	struct dentry		*root;
@@ -471,8 +659,8 @@
 	int			ret;
 
 	root = debugfs_create_dir(dev_name(dwc->dev), NULL);
-	if (IS_ERR(root)) {
-		ret = PTR_ERR(root);
+	if (!root) {
+		ret = -ENOMEM;
 		goto err0;
 	}
 
@@ -480,15 +668,29 @@
 
 	file = debugfs_create_file("regdump", S_IRUGO, root, dwc,
 			&dwc3_regdump_fops);
-	if (IS_ERR(file)) {
-		ret = PTR_ERR(file);
+	if (!file) {
+		ret = -ENOMEM;
 		goto err1;
 	}
 
 	file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
 			dwc, &dwc3_mode_fops);
-	if (IS_ERR(file)) {
-		ret = PTR_ERR(file);
+	if (!file) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
+			dwc, &dwc3_testmode_fops);
+	if (!file) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
+			dwc, &dwc3_link_state_fops);
+	if (!file) {
+		ret = -ENOMEM;
 		goto err1;
 	}
 
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
new file mode 100644
index 0000000..d190301
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -0,0 +1,151 @@
+/**
+ * dwc3-exynos.c - Samsung EXYNOS DWC3 Specific Glue layer
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Author: Anton Tikhomirov <av.tikhomirov@samsung.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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/dwc3-exynos.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+
+#include "core.h"
+
+struct dwc3_exynos {
+	struct platform_device	*dwc3;
+	struct device		*dev;
+
+	struct clk		*clk;
+};
+
+static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
+{
+	struct dwc3_exynos_data	*pdata = pdev->dev.platform_data;
+	struct platform_device	*dwc3;
+	struct dwc3_exynos	*exynos;
+	struct clk		*clk;
+
+	int			devid;
+	int			ret = -ENOMEM;
+
+	exynos = kzalloc(sizeof(*exynos), GFP_KERNEL);
+	if (!exynos) {
+		dev_err(&pdev->dev, "not enough memory\n");
+		goto err0;
+	}
+
+	platform_set_drvdata(pdev, exynos);
+
+	devid = dwc3_get_device_id();
+	if (devid < 0)
+		goto err1;
+
+	dwc3 = platform_device_alloc("dwc3", devid);
+	if (!dwc3) {
+		dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
+		goto err2;
+	}
+
+	clk = clk_get(&pdev->dev, "usbdrd30");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "couldn't get clock\n");
+		ret = -EINVAL;
+		goto err3;
+	}
+
+	dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask);
+
+	dwc3->dev.parent = &pdev->dev;
+	dwc3->dev.dma_mask = pdev->dev.dma_mask;
+	dwc3->dev.dma_parms = pdev->dev.dma_parms;
+	exynos->dwc3	= dwc3;
+	exynos->dev	= &pdev->dev;
+	exynos->clk	= clk;
+
+	clk_enable(exynos->clk);
+
+	/* PHY initialization */
+	if (!pdata) {
+		dev_dbg(&pdev->dev, "missing platform data\n");
+	} else {
+		if (pdata->phy_init)
+			pdata->phy_init(pdev, pdata->phy_type);
+	}
+
+	ret = platform_device_add_resources(dwc3, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n");
+		goto err4;
+	}
+
+	ret = platform_device_add(dwc3);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register dwc3 device\n");
+		goto err4;
+	}
+
+	return 0;
+
+err4:
+	if (pdata && pdata->phy_exit)
+		pdata->phy_exit(pdev, pdata->phy_type);
+
+	clk_disable(clk);
+	clk_put(clk);
+err3:
+	platform_device_put(dwc3);
+err2:
+	dwc3_put_device_id(devid);
+err1:
+	kfree(exynos);
+err0:
+	return ret;
+}
+
+static int __devexit dwc3_exynos_remove(struct platform_device *pdev)
+{
+	struct dwc3_exynos	*exynos = platform_get_drvdata(pdev);
+	struct dwc3_exynos_data *pdata = pdev->dev.platform_data;
+
+	platform_device_unregister(exynos->dwc3);
+
+	dwc3_put_device_id(exynos->dwc3->id);
+
+	if (pdata && pdata->phy_exit)
+		pdata->phy_exit(pdev, pdata->phy_type);
+
+	clk_disable(exynos->clk);
+	clk_put(exynos->clk);
+
+	kfree(exynos);
+
+	return 0;
+}
+
+static struct platform_driver dwc3_exynos_driver = {
+	.probe		= dwc3_exynos_probe,
+	.remove		= __devexit_p(dwc3_exynos_remove),
+	.driver		= {
+		.name	= "exynos-dwc3",
+	},
+};
+
+module_platform_driver(dwc3_exynos_driver);
+
+MODULE_ALIAS("platform:exynos-dwc3");
+MODULE_AUTHOR("Anton Tikhomirov <av.tikhomirov@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DesignWare USB3 EXYNOS Glue Layer");
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 3274ac8..d7d9c0e 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -46,7 +46,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/ioport.h>
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/of.h>
 
 #include "core.h"
 #include "io.h"
@@ -197,91 +197,99 @@
 static int __devinit dwc3_omap_probe(struct platform_device *pdev)
 {
 	struct dwc3_omap_data	*pdata = pdev->dev.platform_data;
+	struct device_node	*node = pdev->dev.of_node;
+
 	struct platform_device	*dwc3;
 	struct dwc3_omap	*omap;
 	struct resource		*res;
+	struct device		*dev = &pdev->dev;
 
 	int			devid;
+	int			size;
 	int			ret = -ENOMEM;
 	int			irq;
 
+	const u32		*utmi_mode;
 	u32			reg;
 
 	void __iomem		*base;
 	void			*context;
 
-	omap = kzalloc(sizeof(*omap), GFP_KERNEL);
+	omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
 	if (!omap) {
-		dev_err(&pdev->dev, "not enough memory\n");
-		goto err0;
+		dev_err(dev, "not enough memory\n");
+		return -ENOMEM;
 	}
 
 	platform_set_drvdata(pdev, omap);
 
 	irq = platform_get_irq(pdev, 1);
 	if (irq < 0) {
-		dev_err(&pdev->dev, "missing IRQ resource\n");
-		ret = -EINVAL;
-		goto err1;
+		dev_err(dev, "missing IRQ resource\n");
+		return -EINVAL;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	if (!res) {
-		dev_err(&pdev->dev, "missing memory base resource\n");
-		ret = -EINVAL;
-		goto err1;
+		dev_err(dev, "missing memory base resource\n");
+		return -EINVAL;
 	}
 
-	base = ioremap_nocache(res->start, resource_size(res));
+	base = devm_ioremap_nocache(dev, res->start, resource_size(res));
 	if (!base) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		goto err1;
+		dev_err(dev, "ioremap failed\n");
+		return -ENOMEM;
 	}
 
 	devid = dwc3_get_device_id();
 	if (devid < 0)
-		goto err2;
+		return -ENODEV;
 
 	dwc3 = platform_device_alloc("dwc3", devid);
 	if (!dwc3) {
-		dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
-		goto err3;
+		dev_err(dev, "couldn't allocate dwc3 device\n");
+		goto err1;
 	}
 
-	context = kzalloc(resource_size(res), GFP_KERNEL);
+	context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL);
 	if (!context) {
-		dev_err(&pdev->dev, "couldn't allocate dwc3 context memory\n");
-		goto err4;
+		dev_err(dev, "couldn't allocate dwc3 context memory\n");
+		goto err2;
 	}
 
 	spin_lock_init(&omap->lock);
-	dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask);
+	dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
 
-	dwc3->dev.parent = &pdev->dev;
-	dwc3->dev.dma_mask = pdev->dev.dma_mask;
-	dwc3->dev.dma_parms = pdev->dev.dma_parms;
+	dwc3->dev.parent = dev;
+	dwc3->dev.dma_mask = dev->dma_mask;
+	dwc3->dev.dma_parms = dev->dma_parms;
 	omap->resource_size = resource_size(res);
 	omap->context	= context;
-	omap->dev	= &pdev->dev;
+	omap->dev	= dev;
 	omap->irq	= irq;
 	omap->base	= base;
 	omap->dwc3	= dwc3;
 
 	reg = dwc3_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
 
-	if (!pdata) {
-		dev_dbg(&pdev->dev, "missing platform data\n");
+	utmi_mode = of_get_property(node, "utmi-mode", &size);
+	if (utmi_mode && size == sizeof(*utmi_mode)) {
+		reg |= *utmi_mode;
 	} else {
-		switch (pdata->utmi_mode) {
-		case DWC3_OMAP_UTMI_MODE_SW:
-			reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-			break;
-		case DWC3_OMAP_UTMI_MODE_HW:
-			reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-			break;
-		default:
-			dev_dbg(&pdev->dev, "UNKNOWN utmi mode %d\n",
-					pdata->utmi_mode);
+		if (!pdata) {
+			dev_dbg(dev, "missing platform data\n");
+		} else {
+			switch (pdata->utmi_mode) {
+			case DWC3_OMAP_UTMI_MODE_SW:
+				reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+				break;
+			case DWC3_OMAP_UTMI_MODE_HW:
+				reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+				break;
+			default:
+				dev_dbg(dev, "UNKNOWN utmi mode %d\n",
+						pdata->utmi_mode);
+			}
 		}
 	}
 
@@ -300,12 +308,12 @@
 
 	dwc3_writel(omap->base, USBOTGSS_SYSCONFIG, reg);
 
-	ret = request_irq(omap->irq, dwc3_omap_interrupt, 0,
+	ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0,
 			"dwc3-omap", omap);
 	if (ret) {
-		dev_err(&pdev->dev, "failed to request IRQ #%d --> %d\n",
+		dev_err(dev, "failed to request IRQ #%d --> %d\n",
 				omap->irq, ret);
-		goto err5;
+		goto err2;
 	}
 
 	/* enable all IRQs */
@@ -327,37 +335,24 @@
 	ret = platform_device_add_resources(dwc3, pdev->resource,
 			pdev->num_resources);
 	if (ret) {
-		dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n");
-		goto err6;
+		dev_err(dev, "couldn't add resources to dwc3 device\n");
+		goto err2;
 	}
 
 	ret = platform_device_add(dwc3);
 	if (ret) {
-		dev_err(&pdev->dev, "failed to register dwc3 device\n");
-		goto err6;
+		dev_err(dev, "failed to register dwc3 device\n");
+		goto err2;
 	}
 
 	return 0;
 
-err6:
-	free_irq(omap->irq, omap);
-
-err5:
-	kfree(omap->context);
-
-err4:
+err2:
 	platform_device_put(dwc3);
 
-err3:
+err1:
 	dwc3_put_device_id(devid);
 
-err2:
-	iounmap(base);
-
-err1:
-	kfree(omap);
-
-err0:
 	return ret;
 }
 
@@ -368,11 +363,6 @@
 	platform_device_unregister(omap->dwc3);
 
 	dwc3_put_device_id(omap->dwc3->id);
-	free_irq(omap->irq, omap);
-	iounmap(omap->base);
-
-	kfree(omap->context);
-	kfree(omap);
 
 	return 0;
 }
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index c68e427..a9ca9ad 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -61,32 +61,36 @@
 	struct dwc3_pci		*glue;
 	int			ret = -ENOMEM;
 	int			devid;
+	struct device		*dev = &pci->dev;
 
-	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
-		dev_err(&pci->dev, "not enough memory\n");
-		goto err0;
+		dev_err(dev, "not enough memory\n");
+		return -ENOMEM;
 	}
 
-	glue->dev	= &pci->dev;
+	glue->dev = dev;
 
 	ret = pci_enable_device(pci);
 	if (ret) {
-		dev_err(&pci->dev, "failed to enable pci device\n");
-		goto err1;
+		dev_err(dev, "failed to enable pci device\n");
+		return -ENODEV;
 	}
 
 	pci_set_power_state(pci, PCI_D0);
 	pci_set_master(pci);
 
 	devid = dwc3_get_device_id();
-	if (devid < 0)
-		goto err2;
+	if (devid < 0) {
+		ret = -ENOMEM;
+		goto err1;
+	}
 
 	dwc3 = platform_device_alloc("dwc3", devid);
 	if (!dwc3) {
-		dev_err(&pci->dev, "couldn't allocate dwc3 device\n");
-		goto err3;
+		dev_err(dev, "couldn't allocate dwc3 device\n");
+		ret = -ENOMEM;
+		goto err1;
 	}
 
 	memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
@@ -102,41 +106,37 @@
 
 	ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res));
 	if (ret) {
-		dev_err(&pci->dev, "couldn't add resources to dwc3 device\n");
-		goto err4;
+		dev_err(dev, "couldn't add resources to dwc3 device\n");
+		goto err2;
 	}
 
 	pci_set_drvdata(pci, glue);
 
-	dma_set_coherent_mask(&dwc3->dev, pci->dev.coherent_dma_mask);
+	dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
 
-	dwc3->dev.dma_mask = pci->dev.dma_mask;
-	dwc3->dev.dma_parms = pci->dev.dma_parms;
-	dwc3->dev.parent = &pci->dev;
-	glue->dwc3	= dwc3;
+	dwc3->dev.dma_mask = dev->dma_mask;
+	dwc3->dev.dma_parms = dev->dma_parms;
+	dwc3->dev.parent = dev;
+	glue->dwc3 = dwc3;
 
 	ret = platform_device_add(dwc3);
 	if (ret) {
-		dev_err(&pci->dev, "failed to register dwc3 device\n");
-		goto err4;
+		dev_err(dev, "failed to register dwc3 device\n");
+		goto err3;
 	}
 
 	return 0;
 
-err4:
+err3:
 	pci_set_drvdata(pci, NULL);
 	platform_device_put(dwc3);
 
-err3:
+err2:
 	dwc3_put_device_id(devid);
 
-err2:
+err1:
 	pci_disable_device(pci);
 
-err1:
-	kfree(glue);
-
-err0:
 	return ret;
 }
 
@@ -148,7 +148,6 @@
 	platform_device_unregister(glue->dwc3);
 	pci_set_drvdata(pci, NULL);
 	pci_disable_device(pci);
-	kfree(glue);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index c8df1dd..25910e2 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -76,8 +76,7 @@
 		u32 len, u32 type)
 {
 	struct dwc3_gadget_ep_cmd_params params;
-	struct dwc3_trb_hw		*trb_hw;
-	struct dwc3_trb			trb;
+	struct dwc3_trb			*trb;
 	struct dwc3_ep			*dep;
 
 	int				ret;
@@ -88,19 +87,17 @@
 		return 0;
 	}
 
-	trb_hw = dwc->ep0_trb;
-	memset(&trb, 0, sizeof(trb));
+	trb = dwc->ep0_trb;
 
-	trb.trbctl = type;
-	trb.bplh = buf_dma;
-	trb.length = len;
+	trb->bpl = lower_32_bits(buf_dma);
+	trb->bph = upper_32_bits(buf_dma);
+	trb->size = len;
+	trb->ctrl = type;
 
-	trb.hwo	= 1;
-	trb.lst	= 1;
-	trb.ioc	= 1;
-	trb.isp_imi = 1;
-
-	dwc3_trb_to_hw(&trb, trb_hw);
+	trb->ctrl |= (DWC3_TRB_CTRL_HWO
+			| DWC3_TRB_CTRL_LST
+			| DWC3_TRB_CTRL_IOC
+			| DWC3_TRB_CTRL_ISP_IMI);
 
 	memset(&params, 0, sizeof(params));
 	params.param0 = upper_32_bits(dwc->ep0_trb_addr);
@@ -302,7 +299,7 @@
 	dep = dwc->eps[0];
 	dwc->ep0_usb_req.dep = dep;
 	dwc->ep0_usb_req.request.length = sizeof(*response_pkt);
-	dwc->ep0_usb_req.request.dma = dwc->setup_buf_addr;
+	dwc->ep0_usb_req.request.buf = dwc->setup_buf;
 	dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl;
 
 	return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
@@ -315,9 +312,7 @@
 	u32			recip;
 	u32			wValue;
 	u32			wIndex;
-	u32			reg;
 	int			ret;
-	u32			mode;
 
 	wValue = le16_to_cpu(ctrl->wValue);
 	wIndex = le16_to_cpu(ctrl->wIndex);
@@ -356,25 +351,8 @@
 			if (!set)
 				return -EINVAL;
 
-			mode = wIndex >> 8;
-			reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-			reg &= ~DWC3_DCTL_TSTCTRL_MASK;
-
-			switch (mode) {
-			case TEST_J:
-			case TEST_K:
-			case TEST_SE0_NAK:
-			case TEST_PACKET:
-			case TEST_FORCE_EN:
-				reg |= mode << 1;
-				break;
-			default:
-				return -EINVAL;
-			}
-			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
-			break;
-		default:
-			return -EINVAL;
+			dwc->test_mode_nr = wIndex >> 8;
+			dwc->test_mode = true;
 		}
 		break;
 
@@ -396,7 +374,7 @@
 	case USB_RECIP_ENDPOINT:
 		switch (wValue) {
 		case USB_ENDPOINT_HALT:
-			dep =  dwc3_wIndex_to_dep(dwc, wIndex);
+			dep = dwc3_wIndex_to_dep(dwc, wIndex);
 			if (!dep)
 				return -EINVAL;
 			ret = __dwc3_gadget_ep_set_halt(dep, set);
@@ -470,8 +448,11 @@
 	case DWC3_ADDRESS_STATE:
 		ret = dwc3_ep0_delegate_req(dwc, ctrl);
 		/* if the cfg matches and the cfg is non zero */
-		if (!ret && cfg)
+		if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
 			dwc->dev_state = DWC3_CONFIGURED_STATE;
+			dwc->resize_fifos = true;
+			dev_dbg(dwc->dev, "resize fifos flag SET\n");
+		}
 		break;
 
 	case DWC3_CONFIGURED_STATE:
@@ -560,9 +541,10 @@
 {
 	struct dwc3_request	*r = NULL;
 	struct usb_request	*ur;
-	struct dwc3_trb		trb;
+	struct dwc3_trb		*trb;
 	struct dwc3_ep		*ep0;
 	u32			transferred;
+	u32			length;
 	u8			epnum;
 
 	epnum = event->endpoint_number;
@@ -573,16 +555,16 @@
 	r = next_request(&ep0->request_list);
 	ur = &r->request;
 
-	dwc3_trb_to_nat(dwc->ep0_trb, &trb);
+	trb = dwc->ep0_trb;
+	length = trb->size & DWC3_TRB_SIZE_MASK;
 
 	if (dwc->ep0_bounced) {
-
 		transferred = min_t(u32, ur->length,
-				ep0->endpoint.maxpacket - trb.length);
+				ep0->endpoint.maxpacket - length);
 		memcpy(ur->buf, dwc->ep0_bounce, transferred);
 		dwc->ep0_bounced = false;
 	} else {
-		transferred = ur->length - trb.length;
+		transferred = ur->length - length;
 		ur->actual += transferred;
 	}
 
@@ -614,6 +596,17 @@
 		dwc3_gadget_giveback(dep, r, 0);
 	}
 
+	if (dwc->test_mode) {
+		int ret;
+
+		ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr);
+		if (ret < 0) {
+			dev_dbg(dwc->dev, "Invalid Test #%d\n",
+					dwc->test_mode_nr);
+			dwc3_ep0_stall_and_restart(dwc);
+		}
+	}
+
 	dwc->ep0state = EP0_SETUP_PHASE;
 	dwc3_ep0_out_start(dwc);
 }
@@ -624,6 +617,7 @@
 	struct dwc3_ep		*dep = dwc->eps[event->endpoint_number];
 
 	dep->flags &= ~DWC3_EP_BUSY;
+	dep->res_trans_idx = 0;
 	dwc->setup_packet_pending = false;
 
 	switch (dwc->ep0state) {
@@ -679,7 +673,12 @@
 				DWC3_TRBCTL_CONTROL_DATA);
 	} else if ((req->request.length % dep->endpoint.maxpacket)
 			&& (event->endpoint_number == 0)) {
-		dwc3_map_buffer_to_dma(req);
+		ret = usb_gadget_map_request(&dwc->gadget, &req->request,
+				event->endpoint_number);
+		if (ret) {
+			dev_dbg(dwc->dev, "failed to map request\n");
+			return;
+		}
 
 		WARN_ON(req->request.length > dep->endpoint.maxpacket);
 
@@ -694,7 +693,12 @@
 				dwc->ep0_bounce_addr, dep->endpoint.maxpacket,
 				DWC3_TRBCTL_CONTROL_DATA);
 	} else {
-		dwc3_map_buffer_to_dma(req);
+		ret = usb_gadget_map_request(&dwc->gadget, &req->request,
+				event->endpoint_number);
+		if (ret) {
+			dev_dbg(dwc->dev, "failed to map request\n");
+			return;
+		}
 
 		ret = dwc3_ep0_start_trans(dwc, event->endpoint_number,
 				req->request.dma, req->request.length,
@@ -720,6 +724,12 @@
 {
 	struct dwc3_ep		*dep = dwc->eps[epnum];
 
+	if (dwc->resize_fifos) {
+		dev_dbg(dwc->dev, "starting to resize fifos\n");
+		dwc3_gadget_resize_tx_fifos(dwc);
+		dwc->resize_fifos = 0;
+	}
+
 	WARN_ON(dwc3_ep0_start_control_status(dep));
 }
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 064b6e2..5255fe97 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -54,68 +54,162 @@
 #include "gadget.h"
 #include "io.h"
 
-#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
-
-void dwc3_map_buffer_to_dma(struct dwc3_request *req)
+/**
+ * dwc3_gadget_set_test_mode - Enables USB2 Test Modes
+ * @dwc: pointer to our context structure
+ * @mode: the mode to set (J, K SE0 NAK, Force Enable)
+ *
+ * Caller should take care of locking. This function will
+ * return 0 on success or -EINVAL if wrong Test Selector
+ * is passed
+ */
+int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode)
 {
-	struct dwc3			*dwc = req->dep->dwc;
+	u32		reg;
 
-	if (req->request.length == 0) {
-		/* req->request.dma = dwc->setup_buf_addr; */
-		return;
+	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+	reg &= ~DWC3_DCTL_TSTCTRL_MASK;
+
+	switch (mode) {
+	case TEST_J:
+	case TEST_K:
+	case TEST_SE0_NAK:
+	case TEST_PACKET:
+	case TEST_FORCE_EN:
+		reg |= mode << 1;
+		break;
+	default:
+		return -EINVAL;
 	}
 
-	if (req->request.num_sgs) {
-		int	mapped;
+	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 
-		mapped = dma_map_sg(dwc->dev, req->request.sg,
-				req->request.num_sgs,
-				req->direction ? DMA_TO_DEVICE
-				: DMA_FROM_DEVICE);
-		if (mapped < 0) {
-			dev_err(dwc->dev, "failed to map SGs\n");
-			return;
-		}
-
-		req->request.num_mapped_sgs = mapped;
-		return;
-	}
-
-	if (req->request.dma == DMA_ADDR_INVALID) {
-		req->request.dma = dma_map_single(dwc->dev, req->request.buf,
-				req->request.length, req->direction
-				? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->mapped = true;
-	}
+	return 0;
 }
 
-void dwc3_unmap_buffer_from_dma(struct dwc3_request *req)
+/**
+ * dwc3_gadget_set_link_state - Sets USB Link to a particular State
+ * @dwc: pointer to our context structure
+ * @state: the state to put link into
+ *
+ * Caller should take care of locking. This function will
+ * return 0 on success or -ETIMEDOUT.
+ */
+int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state)
 {
-	struct dwc3			*dwc = req->dep->dwc;
+	int		retries = 10000;
+	u32		reg;
 
-	if (req->request.length == 0) {
-		req->request.dma = DMA_ADDR_INVALID;
-		return;
+	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+	reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
+
+	/* set requested state */
+	reg |= DWC3_DCTL_ULSTCHNGREQ(state);
+	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
+	/* wait for a change in DSTS */
+	while (--retries) {
+		reg = dwc3_readl(dwc->regs, DWC3_DSTS);
+
+		if (DWC3_DSTS_USBLNKST(reg) == state)
+			return 0;
+
+		udelay(5);
 	}
 
-	if (req->request.num_mapped_sgs) {
-		req->request.dma = DMA_ADDR_INVALID;
-		dma_unmap_sg(dwc->dev, req->request.sg,
-				req->request.num_mapped_sgs,
-				req->direction ? DMA_TO_DEVICE
-				: DMA_FROM_DEVICE);
+	dev_vdbg(dwc->dev, "link state change request timed out\n");
 
-		req->request.num_mapped_sgs = 0;
-		return;
+	return -ETIMEDOUT;
+}
+
+/**
+ * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case
+ * @dwc: pointer to our context structure
+ *
+ * This function will a best effort FIFO allocation in order
+ * to improve FIFO usage and throughput, while still allowing
+ * us to enable as many endpoints as possible.
+ *
+ * Keep in mind that this operation will be highly dependent
+ * on the configured size for RAM1 - which contains TxFifo -,
+ * the amount of endpoints enabled on coreConsultant tool, and
+ * the width of the Master Bus.
+ *
+ * In the ideal world, we would always be able to satisfy the
+ * following equation:
+ *
+ * ((512 + 2 * MDWIDTH-Bytes) + (Number of IN Endpoints - 1) * \
+ * (3 * (1024 + MDWIDTH-Bytes) + MDWIDTH-Bytes)) / MDWIDTH-Bytes
+ *
+ * Unfortunately, due to many variables that's not always the case.
+ */
+int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc)
+{
+	int		last_fifo_depth = 0;
+	int		ram1_depth;
+	int		fifo_size;
+	int		mdwidth;
+	int		num;
+
+	if (!dwc->needs_fifo_resize)
+		return 0;
+
+	ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
+	mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
+
+	/* MDWIDTH is represented in bits, we need it in bytes */
+	mdwidth >>= 3;
+
+	/*
+	 * FIXME For now we will only allocate 1 wMaxPacketSize space
+	 * for each enabled endpoint, later patches will come to
+	 * improve this algorithm so that we better use the internal
+	 * FIFO space
+	 */
+	for (num = 0; num < DWC3_ENDPOINTS_NUM; num++) {
+		struct dwc3_ep	*dep = dwc->eps[num];
+		int		fifo_number = dep->number >> 1;
+		int		mult = 1;
+		int		tmp;
+
+		if (!(dep->number & 1))
+			continue;
+
+		if (!(dep->flags & DWC3_EP_ENABLED))
+			continue;
+
+		if (usb_endpoint_xfer_bulk(dep->desc)
+				|| usb_endpoint_xfer_isoc(dep->desc))
+			mult = 3;
+
+		/*
+		 * REVISIT: the following assumes we will always have enough
+		 * space available on the FIFO RAM for all possible use cases.
+		 * Make sure that's true somehow and change FIFO allocation
+		 * accordingly.
+		 *
+		 * If we have Bulk or Isochronous endpoints, we want
+		 * them to be able to be very, very fast. So we're giving
+		 * those endpoints a fifo_size which is enough for 3 full
+		 * packets
+		 */
+		tmp = mult * (dep->endpoint.maxpacket + mdwidth);
+		tmp += mdwidth;
+
+		fifo_size = DIV_ROUND_UP(tmp, mdwidth);
+
+		fifo_size |= (last_fifo_depth << 16);
+
+		dev_vdbg(dwc->dev, "%s: Fifo Addr %04x Size %d\n",
+				dep->name, last_fifo_depth, fifo_size & 0xffff);
+
+		dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(fifo_number),
+				fifo_size);
+
+		last_fifo_depth += (fifo_size & 0xffff);
 	}
 
-	if (req->mapped) {
-		dma_unmap_single(dwc->dev, req->request.dma,
-				req->request.length, req->direction
-				? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->mapped = 0;
-		req->request.dma = DMA_ADDR_INVALID;
-	}
+	return 0;
 }
 
 void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
@@ -144,14 +238,15 @@
 	if (req->request.status == -EINPROGRESS)
 		req->request.status = status;
 
-	dwc3_unmap_buffer_from_dma(req);
+	usb_gadget_unmap_request(&dwc->gadget, &req->request,
+			req->direction);
 
 	dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n",
 			req, dep->name, req->request.actual,
 			req->request.length, status);
 
 	spin_unlock(&dwc->lock);
-	req->request.complete(&req->dep->endpoint, &req->request);
+	req->request.complete(&dep->endpoint, &req->request);
 	spin_lock(&dwc->lock);
 }
 
@@ -219,7 +314,7 @@
 }
 
 static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep,
-		struct dwc3_trb_hw *trb)
+		struct dwc3_trb *trb)
 {
 	u32		offset = (char *) trb - (char *) dep->trb_pool;
 
@@ -368,9 +463,8 @@
 		return ret;
 
 	if (!(dep->flags & DWC3_EP_ENABLED)) {
-		struct dwc3_trb_hw	*trb_st_hw;
-		struct dwc3_trb_hw	*trb_link_hw;
-		struct dwc3_trb		trb_link;
+		struct dwc3_trb	*trb_st_hw;
+		struct dwc3_trb	*trb_link;
 
 		ret = dwc3_gadget_set_xfer_resource(dwc, dep);
 		if (ret)
@@ -390,15 +484,15 @@
 
 		memset(&trb_link, 0, sizeof(trb_link));
 
-		/* Link TRB for ISOC. The HWO but is never reset */
+		/* Link TRB for ISOC. The HWO bit is never reset */
 		trb_st_hw = &dep->trb_pool[0];
 
-		trb_link.bplh = dwc3_trb_dma_offset(dep, trb_st_hw);
-		trb_link.trbctl = DWC3_TRBCTL_LINK_TRB;
-		trb_link.hwo = true;
+		trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1];
 
-		trb_link_hw = &dep->trb_pool[DWC3_TRB_NUM - 1];
-		dwc3_trb_to_hw(&trb_link, trb_link_hw);
+		trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw));
+		trb_link->bph = upper_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw));
+		trb_link->ctrl |= DWC3_TRBCTL_LINK_TRB;
+		trb_link->ctrl |= DWC3_TRB_CTRL_HWO;
 	}
 
 	return 0;
@@ -440,6 +534,7 @@
 
 	dep->stream_capable = false;
 	dep->desc = NULL;
+	dep->endpoint.desc = NULL;
 	dep->comp_desc = NULL;
 	dep->type = 0;
 	dep->flags = 0;
@@ -485,16 +580,16 @@
 
 	switch (usb_endpoint_type(desc)) {
 	case USB_ENDPOINT_XFER_CONTROL:
-		strncat(dep->name, "-control", sizeof(dep->name));
+		strlcat(dep->name, "-control", sizeof(dep->name));
 		break;
 	case USB_ENDPOINT_XFER_ISOC:
-		strncat(dep->name, "-isoc", sizeof(dep->name));
+		strlcat(dep->name, "-isoc", sizeof(dep->name));
 		break;
 	case USB_ENDPOINT_XFER_BULK:
-		strncat(dep->name, "-bulk", sizeof(dep->name));
+		strlcat(dep->name, "-bulk", sizeof(dep->name));
 		break;
 	case USB_ENDPOINT_XFER_INT:
-		strncat(dep->name, "-int", sizeof(dep->name));
+		strlcat(dep->name, "-int", sizeof(dep->name));
 		break;
 	default:
 		dev_err(dwc->dev, "invalid endpoint transfer type\n");
@@ -562,7 +657,6 @@
 
 	req->epnum	= dep->number;
 	req->dep	= dep;
-	req->request.dma = DMA_ADDR_INVALID;
 
 	return &req->request;
 }
@@ -585,8 +679,7 @@
 		unsigned length, unsigned last, unsigned chain)
 {
 	struct dwc3		*dwc = dep->dwc;
-	struct dwc3_trb_hw	*trb_hw;
-	struct dwc3_trb		trb;
+	struct dwc3_trb		*trb;
 
 	unsigned int		cur_slot;
 
@@ -595,7 +688,7 @@
 			length, last ? " last" : "",
 			chain ? " chain" : "");
 
-	trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
+	trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
 	cur_slot = dep->free_slot;
 	dep->free_slot++;
 
@@ -604,40 +697,32 @@
 			usb_endpoint_xfer_isoc(dep->desc))
 		return;
 
-	memset(&trb, 0, sizeof(trb));
 	if (!req->trb) {
 		dwc3_gadget_move_request_queued(req);
-		req->trb = trb_hw;
-		req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw);
+		req->trb = trb;
+		req->trb_dma = dwc3_trb_dma_offset(dep, trb);
 	}
 
-	if (usb_endpoint_xfer_isoc(dep->desc)) {
-		trb.isp_imi = true;
-		trb.csp = true;
-	} else {
-		trb.chn = chain;
-		trb.lst = last;
-	}
-
-	if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable)
-		trb.sid_sofn = req->request.stream_id;
+	trb->size = DWC3_TRB_SIZE_LENGTH(length);
+	trb->bpl = lower_32_bits(dma);
+	trb->bph = upper_32_bits(dma);
 
 	switch (usb_endpoint_type(dep->desc)) {
 	case USB_ENDPOINT_XFER_CONTROL:
-		trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP;
+		trb->ctrl = DWC3_TRBCTL_CONTROL_SETUP;
 		break;
 
 	case USB_ENDPOINT_XFER_ISOC:
-		trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;
+		trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;
 
 		/* IOC every DWC3_TRB_NUM / 4 so we can refill */
 		if (!(cur_slot % (DWC3_TRB_NUM / 4)))
-			trb.ioc = last;
+			trb->ctrl |= DWC3_TRB_CTRL_IOC;
 		break;
 
 	case USB_ENDPOINT_XFER_BULK:
 	case USB_ENDPOINT_XFER_INT:
-		trb.trbctl = DWC3_TRBCTL_NORMAL;
+		trb->ctrl = DWC3_TRBCTL_NORMAL;
 		break;
 	default:
 		/*
@@ -647,11 +732,21 @@
 		BUG();
 	}
 
-	trb.length	= length;
-	trb.bplh	= dma;
-	trb.hwo		= true;
+	if (usb_endpoint_xfer_isoc(dep->desc)) {
+		trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
+		trb->ctrl |= DWC3_TRB_CTRL_CSP;
+	} else {
+		if (chain)
+			trb->ctrl |= DWC3_TRB_CTRL_CHN;
 
-	dwc3_trb_to_hw(&trb, trb_hw);
+		if (last)
+			trb->ctrl |= DWC3_TRB_CTRL_LST;
+	}
+
+	if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable)
+		trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id);
+
+	trb->ctrl |= DWC3_TRB_CTRL_HWO;
 }
 
 /*
@@ -659,14 +754,15 @@
  * @dep: endpoint for which requests are being prepared
  * @starting: true if the endpoint is idle and no requests are queued.
  *
- * The functions goes through the requests list and setups TRBs for the
- * transfers. The functions returns once there are not more TRBs available or
- * it run out of requests.
+ * The function goes through the requests list and sets up TRBs for the
+ * transfers. The function returns once there are no more TRBs available or
+ * it runs out of requests.
  */
 static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
 {
 	struct dwc3_request	*req, *n;
 	u32			trbs_left;
+	u32			max;
 	unsigned int		last_one = 0;
 
 	BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
@@ -674,9 +770,16 @@
 	/* the first request must not be queued */
 	trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK;
 
+	/* Can't wrap around on a non-isoc EP since there's no link TRB */
+	if (!usb_endpoint_xfer_isoc(dep->desc)) {
+		max = DWC3_TRB_NUM - (dep->free_slot & DWC3_TRB_MASK);
+		if (trbs_left > max)
+			trbs_left = max;
+	}
+
 	/*
-	 * if busy & slot are equal than it is either full or empty. If we are
-	 * starting to proceed requests then we are empty. Otherwise we ar
+	 * If busy & slot are equal than it is either full or empty. If we are
+	 * starting to process requests then we are empty. Otherwise we are
 	 * full and don't do anything
 	 */
 	if (!trbs_left) {
@@ -687,7 +790,7 @@
 		 * In case we start from scratch, we queue the ISOC requests
 		 * starting from slot 1. This is done because we use ring
 		 * buffer and have no LST bit to stop us. Instead, we place
-		 * IOC bit TRB_NUM/4. We try to avoid to having an interrupt
+		 * IOC bit every TRB_NUM/4. We try to avoid having an interrupt
 		 * after the first request so we start at slot 1 and have
 		 * 7 requests proceed before we hit the first IOC.
 		 * Other transfer types don't use the ring buffer and are
@@ -723,8 +826,8 @@
 				length = sg_dma_len(s);
 				dma = sg_dma_address(s);
 
-				if (i == (request->num_mapped_sgs - 1)
-						|| sg_is_last(s)) {
+				if (i == (request->num_mapped_sgs - 1) ||
+						sg_is_last(s)) {
 					last_one = true;
 					chain = false;
 				}
@@ -792,8 +895,7 @@
 		dwc3_prepare_trbs(dep, start_new);
 
 		/*
-		 * req points to the first request where HWO changed
-		 * from 0 to 1
+		 * req points to the first request where HWO changed from 0 to 1
 		 */
 		req = next_request(&dep->req_queued);
 	}
@@ -819,9 +921,10 @@
 		/*
 		 * FIXME we need to iterate over the list of requests
 		 * here and stop, unmap, free and del each of the linked
-		 * requests instead of we do now.
+		 * requests instead of what we do now.
 		 */
-		dwc3_unmap_buffer_from_dma(req);
+		usb_gadget_unmap_request(&dwc->gadget, &req->request,
+				req->direction);
 		list_del(&req->list);
 		return ret;
 	}
@@ -837,6 +940,9 @@
 
 static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 {
+	struct dwc3		*dwc = dep->dwc;
+	int			ret;
+
 	req->request.actual	= 0;
 	req->request.status	= -EINPROGRESS;
 	req->direction		= dep->direction;
@@ -852,9 +958,13 @@
 	 * particular token from the Host side.
 	 *
 	 * This will also avoid Host cancelling URBs due to too
-	 * many NACKs.
+	 * many NAKs.
 	 */
-	dwc3_map_buffer_to_dma(req);
+	ret = usb_gadget_map_request(&dwc->gadget, &req->request,
+			dep->direction);
+	if (ret)
+		return ret;
+
 	list_add_tail(&req->list, &dep->request_list);
 
 	/*
@@ -874,11 +984,11 @@
 		int start_trans;
 
 		start_trans = 1;
-		if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
-				dep->flags & DWC3_EP_BUSY)
+		if (usb_endpoint_xfer_isoc(dep->desc) &&
+				(dep->flags & DWC3_EP_BUSY))
 			start_trans = 0;
 
-		ret =  __dwc3_gadget_kick_transfer(dep, 0, start_trans);
+		ret = __dwc3_gadget_kick_transfer(dep, 0, start_trans);
 		if (ret && ret != -EBUSY) {
 			struct dwc3	*dwc = dep->dwc;
 
@@ -1031,8 +1141,12 @@
 static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep)
 {
 	struct dwc3_ep			*dep = to_dwc3_ep(ep);
+	struct dwc3			*dwc = dep->dwc;
+	unsigned long			flags;
 
+	spin_lock_irqsave(&dwc->lock, flags);
 	dep->flags |= DWC3_EP_WEDGE;
+	spin_unlock_irqrestore(&dwc->lock, flags);
 
 	return dwc3_gadget_ep_set_halt(ep, 1);
 }
@@ -1122,26 +1236,20 @@
 		goto out;
 	}
 
-	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-
-	/*
-	 * Switch link state to Recovery. In HS/FS/LS this means
-	 * RemoteWakeup Request
-	 */
-	reg |= DWC3_DCTL_ULSTCHNG_RECOVERY;
-	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
-
-	/* wait for at least 2000us */
-	usleep_range(2000, 2500);
+	ret = dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RECOV);
+	if (ret < 0) {
+		dev_err(dwc->dev, "failed to put link in Recovery\n");
+		goto out;
+	}
 
 	/* write zeroes to Link Change Request */
 	reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 
-	/* pool until Link State change to ON */
+	/* poll until Link State changes to ON */
 	timeout = jiffies + msecs_to_jiffies(100);
 
-	while (!(time_after(jiffies, timeout))) {
+	while (!time_after(jiffies, timeout)) {
 		reg = dwc3_readl(dwc->regs, DWC3_DSTS);
 
 		/* in HS, means ON */
@@ -1164,8 +1272,11 @@
 		int is_selfpowered)
 {
 	struct dwc3		*dwc = gadget_to_dwc(g);
+	unsigned long		flags;
 
+	spin_lock_irqsave(&dwc->lock, flags);
 	dwc->is_selfpowered = !!is_selfpowered;
+	spin_unlock_irqrestore(&dwc->lock, flags);
 
 	return 0;
 }
@@ -1176,10 +1287,13 @@
 	u32			timeout = 500;
 
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-	if (is_on)
-		reg |= DWC3_DCTL_RUN_STOP;
-	else
+	if (is_on) {
+		reg &= ~DWC3_DCTL_TRGTULST_MASK;
+		reg |= (DWC3_DCTL_RUN_STOP
+				| DWC3_DCTL_TRGTULST_RX_DET);
+	} else {
 		reg &= ~DWC3_DCTL_RUN_STOP;
+	}
 
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 
@@ -1386,7 +1500,7 @@
 		const struct dwc3_event_depevt *event, int status)
 {
 	struct dwc3_request	*req;
-	struct dwc3_trb         trb;
+	struct dwc3_trb		*trb;
 	unsigned int		count;
 	unsigned int		s_pkt = 0;
 
@@ -1397,20 +1511,20 @@
 			return 1;
 		}
 
-		dwc3_trb_to_nat(req->trb, &trb);
+		trb = req->trb;
 
-		if (trb.hwo && status != -ESHUTDOWN)
+		if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN)
 			/*
 			 * We continue despite the error. There is not much we
-			 * can do. If we don't clean in up we loop for ever. If
-			 * we skip the TRB than it gets overwritten reused after
-			 * a while since we use them in a ring buffer. a BUG()
-			 * would help. Lets hope that if this occures, someone
+			 * can do. If we don't clean it up we loop forever. If
+			 * we skip the TRB then it gets overwritten after a
+			 * while since we use them in a ring buffer. A BUG()
+			 * would help. Lets hope that if this occurs, someone
 			 * fixes the root cause instead of looking away :)
 			 */
 			dev_err(dwc->dev, "%s's TRB (%p) still owned by HW\n",
 					dep->name, req->trb);
-		count = trb.length;
+		count = trb->size & DWC3_TRB_SIZE_MASK;
 
 		if (dep->direction) {
 			if (count) {
@@ -1434,13 +1548,16 @@
 		dwc3_gadget_giveback(dep, req, status);
 		if (s_pkt)
 			break;
-		if ((event->status & DEPEVT_STATUS_LST) && trb.lst)
+		if ((event->status & DEPEVT_STATUS_LST) &&
+				(trb->ctrl & DWC3_TRB_CTRL_LST))
 			break;
-		if ((event->status & DEPEVT_STATUS_IOC) && trb.ioc)
+		if ((event->status & DEPEVT_STATUS_IOC) &&
+				(trb->ctrl & DWC3_TRB_CTRL_IOC))
 			break;
 	} while (1);
 
-	if ((event->status & DEPEVT_STATUS_IOC) && trb.ioc)
+	if ((event->status & DEPEVT_STATUS_IOC) &&
+			(trb->ctrl & DWC3_TRB_CTRL_IOC))
 		return 0;
 	return 1;
 }
@@ -1455,11 +1572,9 @@
 	if (event->status & DEPEVT_STATUS_BUSERR)
 		status = -ECONNRESET;
 
-	clean_busy =  dwc3_cleanup_done_reqs(dwc, dep, event, status);
-	if (clean_busy) {
+	clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status);
+	if (clean_busy)
 		dep->flags &= ~DWC3_EP_BUSY;
-		dep->res_trans_idx = 0;
-	}
 
 	/*
 	 * WORKAROUND: This is the 2nd half of U1/U2 -> U0 workaround.
@@ -1490,7 +1605,7 @@
 static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
 		struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
 {
-	u32 uf;
+	u32 uf, mask;
 
 	if (list_empty(&dep->request_list)) {
 		dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n",
@@ -1498,16 +1613,10 @@
 		return;
 	}
 
-	if (event->parameters) {
-		u32 mask;
-
-		mask = ~(dep->interval - 1);
-		uf = event->parameters & mask;
-		/* 4 micro frames in the future */
-		uf += dep->interval * 4;
-	} else {
-		uf = 0;
-	}
+	mask = ~(dep->interval - 1);
+	uf = event->parameters & mask;
+	/* 4 micro frames in the future */
+	uf += dep->interval * 4;
 
 	__dwc3_gadget_kick_transfer(dep, uf, 1);
 }
@@ -1519,8 +1628,8 @@
 	struct dwc3_event_depevt mod_ev = *event;
 
 	/*
-	 * We were asked to remove one requests. It is possible that this
-	 * request and a few other were started together and have the same
+	 * We were asked to remove one request. It is possible that this
+	 * request and a few others were started together and have the same
 	 * transfer index. Since we stopped the complete endpoint we don't
 	 * know how many requests were already completed (and not yet)
 	 * reported and how could be done (later). We purge them all until
@@ -1529,7 +1638,7 @@
 	mod_ev.status = DEPEVT_STATUS_LST;
 	dwc3_cleanup_done_reqs(dwc, dep, &mod_ev, -ESHUTDOWN);
 	dep->flags &= ~DWC3_EP_BUSY;
-	/* pending requets are ignored and are queued on XferNotReady */
+	/* pending requests are ignored and are queued on XferNotReady */
 }
 
 static void dwc3_ep_cmd_compl(struct dwc3_ep *dep,
@@ -1570,6 +1679,8 @@
 
 	switch (event->endpoint_event) {
 	case DWC3_DEPEVT_XFERCOMPLETE:
+		dep->res_trans_idx = 0;
+
 		if (usb_endpoint_xfer_isoc(dep->desc)) {
 			dev_dbg(dwc->dev, "%s is an Isochronous endpoint\n",
 					dep->name);
@@ -1594,7 +1705,8 @@
 			int ret;
 
 			dev_vdbg(dwc->dev, "%s: reason %s\n",
-					dep->name, event->status
+					dep->name, event->status &
+					DEPEVT_STATUS_TRANSFER_ACTIVE
 					? "Transfer Active"
 					: "Transfer Not Active");
 
@@ -1805,6 +1917,7 @@
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	reg &= ~DWC3_DCTL_TSTCTRL_MASK;
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+	dwc->test_mode = false;
 
 	dwc3_stop_active_transfers(dwc);
 	dwc3_clear_stall_all_ep(dwc);
@@ -2082,7 +2195,8 @@
 	while (left > 0) {
 		union dwc3_event event;
 
-		memcpy(&event.raw, (evt->buf + evt->lpos), sizeof(event.raw));
+		event.raw = *(u32 *) (evt->buf + evt->lpos);
+
 		dwc3_process_event_entry(dwc, &event);
 		/*
 		 * XXX we wrap around correctly to the next entry as almost all
@@ -2123,7 +2237,7 @@
 
 /**
  * dwc3_gadget_init - Initializes gadget related registers
- * @dwc: Pointer to out controller context structure
+ * @dwc: pointer to our controller context structure
  *
  * Returns 0 on success otherwise negative errno.
  */
@@ -2149,9 +2263,8 @@
 		goto err1;
 	}
 
-	dwc->setup_buf = dma_alloc_coherent(dwc->dev,
-			sizeof(*dwc->setup_buf) * 2,
-			&dwc->setup_buf_addr, GFP_KERNEL);
+	dwc->setup_buf = kzalloc(sizeof(*dwc->setup_buf) * 2,
+			GFP_KERNEL);
 	if (!dwc->setup_buf) {
 		dev_err(dwc->dev, "failed to allocate setup buffer\n");
 		ret = -ENOMEM;
@@ -2242,8 +2355,7 @@
 			dwc->ep0_bounce_addr);
 
 err3:
-	dma_free_coherent(dwc->dev, sizeof(*dwc->setup_buf) * 2,
-			dwc->setup_buf, dwc->setup_buf_addr);
+	kfree(dwc->setup_buf);
 
 err2:
 	dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
@@ -2272,8 +2384,7 @@
 	dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce,
 			dwc->ep0_bounce_addr);
 
-	dma_free_coherent(dwc->dev, sizeof(*dwc->setup_buf) * 2,
-			dwc->setup_buf, dwc->setup_buf_addr);
+	kfree(dwc->setup_buf);
 
 	dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
 			dwc->ep0_trb, dwc->ep0_trb_addr);
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index d97f467..a860008 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -100,6 +100,9 @@
 void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
 		int status);
 
+int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode);
+int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state);
+
 void dwc3_ep0_interrupt(struct dwc3 *dwc,
 		const struct dwc3_event_depevt *event);
 void dwc3_ep0_out_start(struct dwc3 *dwc);
@@ -108,8 +111,6 @@
 int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value);
 int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
 		unsigned cmd, struct dwc3_gadget_ep_cmd_params *params);
-void dwc3_map_buffer_to_dma(struct dwc3_request *req);
-void dwc3_unmap_buffer_from_dma(struct dwc3_request *req);
 
 /**
  * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index 7cfe211b..b108d18 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -53,7 +53,7 @@
 	struct platform_device	*xhci;
 	int			ret;
 
-	xhci = platform_device_alloc("xhci", -1);
+	xhci = platform_device_alloc("xhci-hcd", -1);
 	if (!xhci) {
 		dev_err(dwc->dev, "couldn't allocate xHCI device\n");
 		ret = -ENOMEM;
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 7ecb68a..c14a397 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -599,16 +599,29 @@
 	depends on SND
 	select SND_PCM
 	help
-	  Gadget Audio is compatible with USB Audio Class specification 1.0.
-	  It will include at least one AudioControl interface, zero or more
-	  AudioStream interface and zero or more MIDIStream interface.
-
-	  Gadget Audio will use on-board ALSA (CONFIG_SND) audio card to
-	  playback or capture audio stream.
+	  This Gadget Audio driver is compatible with USB Audio Class
+	  specification 2.0. It implements 1 AudioControl interface,
+	  1 AudioStreaming Interface each for USB-OUT and USB-IN.
+	  Number of channels, sample rate and sample size can be
+	  specified as module parameters.
+	  This driver doesn't expect any real Audio codec to be present
+	  on the device - the audio streams are simply sinked to and
+	  sourced from a virtual ALSA sound card created. The user-space
+	  application may choose to do whatever it wants with the data
+	  received from the USB Host and choose to provide whatever it
+	  wants as audio data to the USB Host.
 
 	  Say "y" to link the driver statically, or "m" to build a
 	  dynamically linked module called "g_audio".
 
+config GADGET_UAC1
+	bool "UAC 1.0 (Legacy)"
+	depends on USB_AUDIO
+	help
+	  If you instead want older UAC Spec-1.0 driver that also has audio
+	  paths hardwired to the Audio codec chip on-board and doesn't work
+	  without one.
+
 config USB_ETH
 	tristate "Ethernet Gadget (with CDC Ethernet support)"
 	depends on NET
@@ -685,7 +698,7 @@
 	help
 	  This driver implements USB CDC NCM subclass standard. NCM is
 	  an advanced protocol for Ethernet encapsulation, allows grouping
-	  of several ethernet frames into one USB transfer and diffferent
+	  of several ethernet frames into one USB transfer and different
 	  alignment possibilities.
 
 	  Say "y" to link the driver statically, or "m" to build a
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index c16ff55..2204a4c 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -29,7 +29,7 @@
 
 /* Driver strings */
 #define UDC_MOD_DESCRIPTION		"AMD 5536 UDC - USB Device Controller"
-#define UDC_DRIVER_VERSION_STRING	"01.00.0206 - $Revision: #3 $"
+#define UDC_DRIVER_VERSION_STRING	"01.00.0206"
 
 /* system */
 #include <linux/module.h>
@@ -140,7 +140,7 @@
 
 /* endpoint names used for print */
 static const char ep0_string[] = "ep0in";
-static const char *ep_string[] = {
+static const char *const ep_string[] = {
 	ep0_string,
 	"ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk",
 	"ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk",
@@ -204,9 +204,8 @@
 		DBG(dev, "DMA mode       = BF (buffer fill mode)\n");
 		dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "BF");
 	}
-	if (!use_dma) {
+	if (!use_dma)
 		dev_info(&dev->pdev->dev, "FIFO mode\n");
-	}
 	DBG(dev, "-------------------------------------------------------\n");
 }
 
@@ -445,6 +444,7 @@
 
 	VDBG(ep->dev, "ep-%d reset\n", ep->num);
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->ep.ops = &udc_ep_ops;
 	INIT_LIST_HEAD(&ep->queue);
 
@@ -569,9 +569,8 @@
 		VDBG(ep->dev, "req->td_data=%p\n", req->td_data);
 
 		/* free dma chain if created */
-		if (req->chain_len > 1) {
+		if (req->chain_len > 1)
 			udc_free_dma_chain(ep->dev, req);
-		}
 
 		pci_pool_free(ep->dev->data_requests, req->td_data,
 							req->td_phys);
@@ -639,9 +638,8 @@
 		bytes = remaining;
 
 	/* dwords first */
-	for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) {
+	for (i = 0; i < bytes / UDC_DWORD_BYTES; i++)
 		writel(*(buf + i), ep->txfifo);
-	}
 
 	/* remaining bytes must be written by byte access */
 	for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) {
@@ -660,9 +658,8 @@
 
 	VDBG(dev, "udc_read_dwords(): %d dwords\n", dwords);
 
-	for (i = 0; i < dwords; i++) {
+	for (i = 0; i < dwords; i++)
 		*(buf + i) = readl(dev->rxfifo);
-	}
 	return 0;
 }
 
@@ -675,9 +672,8 @@
 	VDBG(dev, "udc_read_bytes(): %d bytes\n", bytes);
 
 	/* dwords first */
-	for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) {
+	for (i = 0; i < bytes / UDC_DWORD_BYTES; i++)
 		*((u32 *)(buf + (i<<2))) = readl(dev->rxfifo);
-	}
 
 	/* remaining bytes must be read by byte access */
 	if (bytes % UDC_DWORD_BYTES) {
@@ -831,20 +827,8 @@
 
 	dev = ep->dev;
 	/* unmap DMA */
-	if (req->dma_mapping) {
-		if (ep->in)
-			pci_unmap_single(dev->pdev,
-					req->req.dma,
-					req->req.length,
-					PCI_DMA_TODEVICE);
-		else
-			pci_unmap_single(dev->pdev,
-					req->req.dma,
-					req->req.length,
-					PCI_DMA_FROMDEVICE);
-		req->dma_mapping = 0;
-		req->req.dma = DMA_DONT_USE;
-	}
+	if (ep->dma)
+		usb_gadget_unmap_request(&dev->gadget, &req->req, ep->in);
 
 	halted = ep->halted;
 	ep->halted = 1;
@@ -897,9 +881,8 @@
 	struct udc_data_dma	*td;
 
 	td = req->td_data;
-	while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) {
+	while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L)))
 		td = phys_to_virt(td->next);
-	}
 
 	return td;
 
@@ -949,21 +932,18 @@
 	dma_addr = DMA_DONT_USE;
 
 	/* unset L bit in first desc for OUT */
-	if (!ep->in) {
+	if (!ep->in)
 		req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
-	}
 
 	/* alloc only new desc's if not already available */
 	len = req->req.length / ep->ep.maxpacket;
-	if (req->req.length % ep->ep.maxpacket) {
+	if (req->req.length % ep->ep.maxpacket)
 		len++;
-	}
 
 	if (len > req->chain_len) {
 		/* shorter chain already allocated before */
-		if (req->chain_len > 1) {
+		if (req->chain_len > 1)
 			udc_free_dma_chain(ep->dev, req);
-		}
 		req->chain_len = len;
 		create_new_chain = 1;
 	}
@@ -1006,11 +986,12 @@
 
 		/* link td and assign tx bytes */
 		if (i == buf_len) {
-			if (create_new_chain) {
+			if (create_new_chain)
 				req->td_data->next = dma_addr;
-			} else {
-				/* req->td_data->next = virt_to_phys(td); */
-			}
+			/*
+			else
+				req->td_data->next = virt_to_phys(td);
+			*/
 			/* write tx bytes */
 			if (ep->in) {
 				/* first desc */
@@ -1024,11 +1005,12 @@
 							UDC_DMA_IN_STS_TXBYTES);
 			}
 		} else {
-			if (create_new_chain) {
+			if (create_new_chain)
 				last->next = dma_addr;
-			} else {
-				/* last->next = virt_to_phys(td); */
-			}
+			/*
+			else
+				last->next = virt_to_phys(td);
+			*/
 			if (ep->in) {
 				/* write tx bytes */
 				td->status = AMD_ADDBITS(td->status,
@@ -1095,20 +1077,11 @@
 		return -ESHUTDOWN;
 
 	/* map dma (usually done before) */
-	if (ep->dma && usbreq->length != 0
-			&& (usbreq->dma == DMA_DONT_USE || usbreq->dma == 0)) {
+	if (ep->dma) {
 		VDBG(dev, "DMA map req %p\n", req);
-		if (ep->in)
-			usbreq->dma = pci_map_single(dev->pdev,
-						usbreq->buf,
-						usbreq->length,
-						PCI_DMA_TODEVICE);
-		else
-			usbreq->dma = pci_map_single(dev->pdev,
-						usbreq->buf,
-						usbreq->length,
-						PCI_DMA_FROMDEVICE);
-		req->dma_mapping = 1;
+		retval = usb_gadget_map_request(&udc->gadget, usbreq, ep->in);
+		if (retval)
+			return retval;
 	}
 
 	VDBG(dev, "%s queue req %p, len %d req->td_data=%p buf %p\n",
@@ -1479,11 +1452,10 @@
 
 	/* program speed */
 	tmp = readl(&dev->regs->cfg);
-	if (use_fullspeed) {
+	if (use_fullspeed)
 		tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
-	} else {
+	else
 		tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
-	}
 	writel(tmp, &dev->regs->cfg);
 
 	return 0;
@@ -1504,9 +1476,8 @@
 		mod_timer(&udc_timer, jiffies - 1);
 	}
 	/* stop poll stall timer */
-	if (timer_pending(&udc_pollstall_timer)) {
+	if (timer_pending(&udc_pollstall_timer))
 		mod_timer(&udc_pollstall_timer, jiffies - 1);
-	}
 	/* disable DMA */
 	tmp = readl(&dev->regs->ctl);
 	tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE);
@@ -1540,11 +1511,10 @@
 	/* read enum speed */
 	tmp = readl(&dev->regs->sts);
 	tmp = AMD_GETBITS(tmp, UDC_DEVSTS_ENUM_SPEED);
-	if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH) {
+	if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH)
 		dev->gadget.speed = USB_SPEED_HIGH;
-	} else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL) {
+	else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL)
 		dev->gadget.speed = USB_SPEED_FULL;
-	}
 
 	/* set basic ep parameters */
 	for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
@@ -1570,9 +1540,8 @@
 		 * disabling ep interrupts when ENUM interrupt occurs but ep is
 		 * not enabled by gadget driver
 		 */
-		if (!ep->desc) {
+		if (!ep->desc)
 			ep_init(dev->regs, ep);
-		}
 
 		if (use_dma) {
 			/*
@@ -1670,9 +1639,8 @@
 		spin_lock(&dev->lock);
 
 		/* empty queues */
-		for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
+		for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
 			empty_req_queue(&dev->ep[tmp]);
-		}
 
 	}
 
@@ -1746,9 +1714,8 @@
 			 * open the fifo
 			 */
 			udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV;
-			if (!stop_timer) {
+			if (!stop_timer)
 				add_timer(&udc_timer);
-			}
 		} else {
 			/*
 			 * fifo contains data now, setup timer for opening
@@ -1760,9 +1727,8 @@
 			set_rde++;
 			/* debug: lhadmot_timer_start = 221070 */
 			udc_timer.expires = jiffies + HZ*UDC_RDE_TIMER_SECONDS;
-			if (!stop_timer) {
+			if (!stop_timer)
 				add_timer(&udc_timer);
-			}
 		}
 
 	} else
@@ -1907,19 +1873,17 @@
 			mod_timer(&udc_timer, jiffies - 1);
 		}
 		/* stop pollstall timer */
-		if (timer_pending(&udc_pollstall_timer)) {
+		if (timer_pending(&udc_pollstall_timer))
 			mod_timer(&udc_pollstall_timer, jiffies - 1);
-		}
 		/* enable DMA */
 		tmp = readl(&dev->regs->ctl);
 		tmp |= AMD_BIT(UDC_DEVCTL_MODE)
 				| AMD_BIT(UDC_DEVCTL_RDE)
 				| AMD_BIT(UDC_DEVCTL_TDE);
-		if (use_dma_bufferfill_mode) {
+		if (use_dma_bufferfill_mode)
 			tmp |= AMD_BIT(UDC_DEVCTL_BF);
-		} else if (use_dma_ppb_du) {
+		else if (use_dma_ppb_du)
 			tmp |= AMD_BIT(UDC_DEVCTL_DU);
-		}
 		writel(tmp, &dev->regs->ctl);
 	}
 
@@ -2104,9 +2068,8 @@
 				udc_timer.expires =
 					jiffies + HZ/UDC_RDE_TIMER_DIV;
 				set_rde = 1;
-				if (!stop_timer) {
+				if (!stop_timer)
 					add_timer(&udc_timer);
-				}
 			}
 		}
 	}
@@ -2131,7 +2094,7 @@
 	if (use_dma) {
 		/* BNA event ? */
 		if (tmp & AMD_BIT(UDC_EPSTS_BNA)) {
-			DBG(dev, "BNA ep%dout occurred - DESPTR = %x \n",
+			DBG(dev, "BNA ep%dout occurred - DESPTR = %x\n",
 					ep->num, readl(&ep->regs->desptr));
 			/* clear BNA */
 			writel(tmp | AMD_BIT(UDC_EPSTS_BNA), &ep->regs->sts);
@@ -2294,9 +2257,8 @@
 						jiffies
 						+ HZ*UDC_RDE_TIMER_SECONDS;
 					set_rde = 1;
-					if (!stop_timer) {
+					if (!stop_timer)
 						add_timer(&udc_timer);
-					}
 				}
 				if (ep->num != UDC_EP0OUT_IX)
 					dev->data_ep_queued = 0;
@@ -2318,9 +2280,8 @@
 	/* check pending CNAKS */
 	if (cnak_pending) {
 		/* CNAk processing when rxfifo empty only */
-		if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {
+		if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY))
 			udc_process_cnak_queue(dev);
-		}
 	}
 
 	/* clear OUT bits in ep status */
@@ -2348,7 +2309,7 @@
 		/* BNA ? */
 		if (epsts & AMD_BIT(UDC_EPSTS_BNA)) {
 			dev_err(&dev->pdev->dev,
-				"BNA ep%din occurred - DESPTR = %08lx \n",
+				"BNA ep%din occurred - DESPTR = %08lx\n",
 				ep->num,
 				(unsigned long) readl(&ep->regs->desptr));
 
@@ -2361,7 +2322,7 @@
 	/* HE event ? */
 	if (epsts & AMD_BIT(UDC_EPSTS_HE)) {
 		dev_err(&dev->pdev->dev,
-			"HE ep%dn occurred - DESPTR = %08lx \n",
+			"HE ep%dn occurred - DESPTR = %08lx\n",
 			ep->num, (unsigned long) readl(&ep->regs->desptr));
 
 		/* clear HE */
@@ -2427,9 +2388,9 @@
 				/* write fifo */
 				udc_txfifo_write(ep, &req->req);
 				len = req->req.length - req->req.actual;
-						if (len > ep->ep.maxpacket)
-							len = ep->ep.maxpacket;
-						req->req.actual += len;
+				if (len > ep->ep.maxpacket)
+					len = ep->ep.maxpacket;
+				req->req.actual += len;
 				if (req->req.actual == req->req.length
 					|| (len != ep->ep.maxpacket)) {
 					/* complete req */
@@ -2581,9 +2542,8 @@
 			if (!timer_pending(&udc_timer)) {
 				udc_timer.expires = jiffies +
 							HZ/UDC_RDE_TIMER_DIV;
-				if (!stop_timer) {
+				if (!stop_timer)
 					add_timer(&udc_timer);
-				}
 			}
 		}
 
@@ -2697,9 +2657,8 @@
 	/* check pending CNAKS */
 	if (cnak_pending) {
 		/* CNAk processing when rxfifo empty only */
-		if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {
+		if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY))
 			udc_process_cnak_queue(dev);
-		}
 	}
 
 finished:
@@ -2723,7 +2682,7 @@
 	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->sts);
 	/* DMA completion */
 	if (tmp & AMD_BIT(UDC_EPSTS_TDC)) {
-		VDBG(dev, "isr: TDC clear \n");
+		VDBG(dev, "isr: TDC clear\n");
 		ret_val = IRQ_HANDLED;
 
 		/* clear TDC bit */
@@ -3426,7 +3385,7 @@
 }
 
 /* PCI device parameters */
-static const struct pci_device_id pci_id[] = {
+static DEFINE_PCI_DEVICE_TABLE(pci_id) = {
 	{
 		PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096),
 		.class =	(PCI_CLASS_SERIAL_USB << 8) | 0xfe,
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 143a725..15a8cdb 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -29,7 +29,6 @@
 #include <linux/clk.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-#include <linux/prefetch.h>
 
 #include <asm/byteorder.h>
 #include <mach/hardware.h>
@@ -558,6 +557,7 @@
 
 	/* restore the endpoint's pristine config */
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->ep.maxpacket = ep->maxpacket;
 
 	/* reset fifos and endpoint */
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index e2fb6d5..5e10f65 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -659,6 +659,7 @@
 		return -EINVAL;
 	}
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 
 	list_splice_init(&ep->queue, &req_list);
 	if (ep->can_dma) {
diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c
index 9d89ae47..9889924 100644
--- a/drivers/usb/gadget/audio.c
+++ b/drivers/usb/gadget/audio.c
@@ -14,10 +14,8 @@
 #include <linux/kernel.h>
 #include <linux/utsname.h>
 
-#include "u_audio.h"
-
 #define DRIVER_DESC		"Linux USB Audio Gadget"
-#define DRIVER_VERSION		"Dec 18, 2008"
+#define DRIVER_VERSION		"Feb 2, 2012"
 
 /*-------------------------------------------------------------------------*/
 
@@ -33,8 +31,36 @@
 #include "config.c"
 #include "epautoconf.c"
 
-#include "u_audio.c"
-#include "f_audio.c"
+/* string IDs are assigned dynamically */
+
+#define STRING_MANUFACTURER_IDX		0
+#define STRING_PRODUCT_IDX		1
+
+static char manufacturer[50];
+
+static struct usb_string strings_dev[] = {
+	[STRING_MANUFACTURER_IDX].s = manufacturer,
+	[STRING_PRODUCT_IDX].s = DRIVER_DESC,
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings stringtab_dev = {
+	.language = 0x0409,	/* en-us */
+	.strings = strings_dev,
+};
+
+static struct usb_gadget_strings *audio_strings[] = {
+	&stringtab_dev,
+	NULL,
+};
+
+#ifdef CONFIG_GADGET_UAC1
+#include "u_uac1.h"
+#include "u_uac1.c"
+#include "f_uac1.c"
+#else
+#include "f_uac2.c"
+#endif
 
 /*-------------------------------------------------------------------------*/
 
@@ -54,9 +80,15 @@
 
 	.bcdUSB =		__constant_cpu_to_le16(0x200),
 
+#ifdef CONFIG_GADGET_UAC1
 	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
 	.bDeviceSubClass =	0,
 	.bDeviceProtocol =	0,
+#else
+	.bDeviceClass =		USB_CLASS_MISC,
+	.bDeviceSubClass =	0x02,
+	.bDeviceProtocol =	0x01,
+#endif
 	/* .bMaxPacketSize0 = f(hardware) */
 
 	/* Vendor and product id defaults change according to what configs
@@ -108,6 +140,9 @@
 	.bConfigurationValue	= 1,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
+#ifndef CONFIG_GADGET_UAC1
+	.unbind			= uac2_unbind_config,
+#endif
 };
 
 /*-------------------------------------------------------------------------*/
@@ -157,7 +192,9 @@
 
 static int __exit audio_unbind(struct usb_composite_dev *cdev)
 {
+#ifdef CONFIG_GADGET_UAC1
 	gaudio_cleanup();
+#endif
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index 1fc6129..d07e44c 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -37,10 +37,10 @@
 		 * Put the transceiver in non-driving mode. Otherwise host
 		 * may not detect soft-disconnection.
 		 */
-		val = otg_io_read(udc->transceiver, ULPI_FUNC_CTRL);
+		val = usb_phy_io_read(udc->transceiver, ULPI_FUNC_CTRL);
 		val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
 		val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
-		otg_io_write(udc->transceiver, val, ULPI_FUNC_CTRL);
+		usb_phy_io_write(udc->transceiver, val, ULPI_FUNC_CTRL);
 		break;
 	default:
 		dev_dbg(dev, "unknown ci13xxx_udc event\n");
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 27e3137..243ef1a 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2181,6 +2181,7 @@
 	} while (mEp->dir != direction);
 
 	mEp->desc = NULL;
+	mEp->ep.desc = NULL;
 
 	spin_unlock_irqrestore(mEp->lock, flags);
 	return retval;
@@ -2537,7 +2538,7 @@
 	struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
 
 	if (udc->transceiver)
-		return otg_set_power(udc->transceiver, mA);
+		return usb_phy_set_power(udc->transceiver, mA);
 	return -ENOTSUPP;
 }
 
@@ -2900,7 +2901,7 @@
 	if (retval < 0)
 		goto free_udc;
 
-	udc->transceiver = otg_get_transceiver();
+	udc->transceiver = usb_get_transceiver();
 
 	if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
 		if (udc->transceiver == NULL) {
@@ -2928,7 +2929,8 @@
 		goto unreg_device;
 
 	if (udc->transceiver) {
-		retval = otg_set_peripheral(udc->transceiver, &udc->gadget);
+		retval = otg_set_peripheral(udc->transceiver->otg,
+						&udc->gadget);
 		if (retval)
 			goto remove_dbg;
 	}
@@ -2945,8 +2947,8 @@
 
 remove_trans:
 	if (udc->transceiver) {
-		otg_set_peripheral(udc->transceiver, &udc->gadget);
-		otg_put_transceiver(udc->transceiver);
+		otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
+		usb_put_transceiver(udc->transceiver);
 	}
 
 	err("error = %i", retval);
@@ -2958,7 +2960,7 @@
 	device_unregister(&udc->gadget.dev);
 put_transceiver:
 	if (udc->transceiver)
-		otg_put_transceiver(udc->transceiver);
+		usb_put_transceiver(udc->transceiver);
 free_udc:
 	kfree(udc);
 	_udc = NULL;
@@ -2981,8 +2983,8 @@
 	usb_del_gadget_udc(&udc->gadget);
 
 	if (udc->transceiver) {
-		otg_set_peripheral(udc->transceiver, &udc->gadget);
-		otg_put_transceiver(udc->transceiver);
+		otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
+		usb_put_transceiver(udc->transceiver);
 	}
 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
 	dbg_remove_files(&udc->gadget.dev);
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index f4871e1..0d31af5 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -136,7 +136,7 @@
 	struct usb_gadget_driver  *driver;     /* 3rd party gadget driver */
 	struct ci13xxx_udc_driver *udc_driver; /* device controller driver */
 	int                        vbus_active; /* is VBUS active */
-	struct otg_transceiver    *transceiver; /* Transceiver struct */
+	struct usb_phy            *transceiver; /* Transceiver struct */
 };
 
 /******************************************************************************
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index db815c2..e1cd56c 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -39,27 +39,27 @@
 #include <linux/usb.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/hcd.h>
+#include <linux/scatterlist.h>
 
 #include <asm/byteorder.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
 
-
 #define DRIVER_DESC	"USB Host+Gadget Emulator"
 #define DRIVER_VERSION	"02 May 2005"
 
 #define POWER_BUDGET	500	/* in mA; use 8 for low-power port testing */
 
-static const char	driver_name [] = "dummy_hcd";
-static const char	driver_desc [] = "USB Host+Gadget Emulator";
+static const char	driver_name[] = "dummy_hcd";
+static const char	driver_desc[] = "USB Host+Gadget Emulator";
 
-static const char	gadget_name [] = "dummy_udc";
+static const char	gadget_name[] = "dummy_udc";
 
-MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_AUTHOR ("David Brownell");
-MODULE_LICENSE ("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
 
 struct dummy_hcd_module_parameters {
 	bool is_super_speed;
@@ -83,10 +83,11 @@
 	struct usb_gadget		*gadget;
 	const struct usb_endpoint_descriptor *desc;
 	struct usb_ep			ep;
-	unsigned			halted : 1;
-	unsigned			wedged : 1;
-	unsigned			already_seen : 1;
-	unsigned			setup_stage : 1;
+	unsigned			halted:1;
+	unsigned			wedged:1;
+	unsigned			already_seen:1;
+	unsigned			setup_stage:1;
+	unsigned			stream_en:1;
 };
 
 struct dummy_request {
@@ -94,15 +95,15 @@
 	struct usb_request		req;
 };
 
-static inline struct dummy_ep *usb_ep_to_dummy_ep (struct usb_ep *_ep)
+static inline struct dummy_ep *usb_ep_to_dummy_ep(struct usb_ep *_ep)
 {
-	return container_of (_ep, struct dummy_ep, ep);
+	return container_of(_ep, struct dummy_ep, ep);
 }
 
 static inline struct dummy_request *usb_request_to_dummy_request
 		(struct usb_request *_req)
 {
-	return container_of (_req, struct dummy_request, req);
+	return container_of(_req, struct dummy_request, req);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -121,9 +122,9 @@
  * configurations, illegal or unsupported packet lengths, and so on.
  */
 
-static const char ep0name [] = "ep0";
+static const char ep0name[] = "ep0";
 
-static const char *const ep_name [] = {
+static const char *const ep_name[] = {
 	ep0name,				/* everyone has ep0 */
 
 	/* act like a net2280: high speed, six configurable endpoints */
@@ -147,6 +148,8 @@
 struct urbp {
 	struct urb		*urb;
 	struct list_head	urbp_list;
+	struct sg_mapping_iter	miter;
+	u32			miter_started;
 };
 
 
@@ -166,6 +169,8 @@
 
 	struct usb_device		*udev;
 	struct list_head		urbp_list;
+	u32				stream_en_ep;
+	u8				num_stream[30 / 2];
 
 	unsigned			active:1;
 	unsigned			old_active:1;
@@ -178,12 +183,12 @@
 	/*
 	 * SLAVE/GADGET side support
 	 */
-	struct dummy_ep			ep [DUMMY_ENDPOINTS];
+	struct dummy_ep			ep[DUMMY_ENDPOINTS];
 	int				address;
 	struct usb_gadget		gadget;
 	struct usb_gadget_driver	*driver;
 	struct dummy_request		fifo_req;
-	u8				fifo_buf [FIFO_SIZE];
+	u8				fifo_buf[FIFO_SIZE];
 	u16				devstatus;
 	unsigned			udc_suspended:1;
 	unsigned			pullup:1;
@@ -210,14 +215,14 @@
 	return dummy_hcd_to_hcd(dum)->self.controller;
 }
 
-static inline struct device *udc_dev (struct dummy *dum)
+static inline struct device *udc_dev(struct dummy *dum)
 {
 	return dum->gadget.dev.parent;
 }
 
-static inline struct dummy *ep_to_dummy (struct dummy_ep *ep)
+static inline struct dummy *ep_to_dummy(struct dummy_ep *ep)
 {
-	return container_of (ep->gadget, struct dummy, gadget);
+	return container_of(ep->gadget, struct dummy, gadget);
 }
 
 static inline struct dummy_hcd *gadget_to_dummy_hcd(struct usb_gadget *gadget)
@@ -229,9 +234,9 @@
 		return dum->hs_hcd;
 }
 
-static inline struct dummy *gadget_dev_to_dummy (struct device *dev)
+static inline struct dummy *gadget_dev_to_dummy(struct device *dev)
 {
-	return container_of (dev, struct dummy, gadget.dev);
+	return container_of(dev, struct dummy, gadget.dev);
 }
 
 static struct dummy			the_controller;
@@ -241,24 +246,23 @@
 /* SLAVE/GADGET SIDE UTILITY ROUTINES */
 
 /* called with spinlock held */
-static void nuke (struct dummy *dum, struct dummy_ep *ep)
+static void nuke(struct dummy *dum, struct dummy_ep *ep)
 {
-	while (!list_empty (&ep->queue)) {
+	while (!list_empty(&ep->queue)) {
 		struct dummy_request	*req;
 
-		req = list_entry (ep->queue.next, struct dummy_request, queue);
-		list_del_init (&req->queue);
+		req = list_entry(ep->queue.next, struct dummy_request, queue);
+		list_del_init(&req->queue);
 		req->req.status = -ESHUTDOWN;
 
-		spin_unlock (&dum->lock);
-		req->req.complete (&ep->ep, &req->req);
-		spin_lock (&dum->lock);
+		spin_unlock(&dum->lock);
+		req->req.complete(&ep->ep, &req->req);
+		spin_lock(&dum->lock);
 	}
 }
 
 /* caller must hold lock */
-static void
-stop_activity (struct dummy *dum)
+static void stop_activity(struct dummy *dum)
 {
 	struct dummy_ep	*ep;
 
@@ -268,8 +272,8 @@
 	/* The timer is left running so that outstanding URBs can fail */
 
 	/* nuke any pending requests first, so driver i/o is quiesced */
-	list_for_each_entry (ep, &dum->gadget.ep_list, ep.ep_list)
-		nuke (dum, ep);
+	list_for_each_entry(ep, &dum->gadget.ep_list, ep.ep_list)
+		nuke(dum, ep);
 
 	/* driver now does any non-usb quiescing necessary */
 }
@@ -404,8 +408,8 @@
 #define is_enabled(dum) \
 	(dum->port_status & USB_PORT_STAT_ENABLE)
 
-static int
-dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+static int dummy_enable(struct usb_ep *_ep,
+		const struct usb_endpoint_descriptor *desc)
 {
 	struct dummy		*dum;
 	struct dummy_hcd	*dum_hcd;
@@ -413,11 +417,11 @@
 	unsigned		max;
 	int			retval;
 
-	ep = usb_ep_to_dummy_ep (_ep);
+	ep = usb_ep_to_dummy_ep(_ep);
 	if (!_ep || !desc || ep->desc || _ep->name == ep0name
 			|| desc->bDescriptorType != USB_DT_ENDPOINT)
 		return -EINVAL;
-	dum = ep_to_dummy (ep);
+	dum = ep_to_dummy(ep);
 	if (!dum->driver)
 		return -ESHUTDOWN;
 
@@ -441,10 +445,10 @@
 	 * especially for "ep9out" style fixed function ones.)
 	 */
 	retval = -EINVAL;
-	switch (desc->bmAttributes & 0x03) {
+	switch (usb_endpoint_type(desc)) {
 	case USB_ENDPOINT_XFER_BULK:
-		if (strstr (ep->ep.name, "-iso")
-				|| strstr (ep->ep.name, "-int")) {
+		if (strstr(ep->ep.name, "-iso")
+				|| strstr(ep->ep.name, "-int")) {
 			goto done;
 		}
 		switch (dum->gadget.speed) {
@@ -466,7 +470,7 @@
 		}
 		break;
 	case USB_ENDPOINT_XFER_INT:
-		if (strstr (ep->ep.name, "-iso")) /* bulk is ok */
+		if (strstr(ep->ep.name, "-iso")) /* bulk is ok */
 			goto done;
 		/* real hardware might not handle all packet sizes */
 		switch (dum->gadget.speed) {
@@ -486,8 +490,8 @@
 		}
 		break;
 	case USB_ENDPOINT_XFER_ISOC:
-		if (strstr (ep->ep.name, "-bulk")
-				|| strstr (ep->ep.name, "-int"))
+		if (strstr(ep->ep.name, "-bulk")
+				|| strstr(ep->ep.name, "-int"))
 			goto done;
 		/* real hardware might not handle all packet sizes */
 		switch (dum->gadget.speed) {
@@ -510,14 +514,22 @@
 	}
 
 	_ep->maxpacket = max;
+	if (usb_ss_max_streams(_ep->comp_desc)) {
+		if (!usb_endpoint_xfer_bulk(desc)) {
+			dev_err(udc_dev(dum), "Can't enable stream support on "
+					"non-bulk ep %s\n", _ep->name);
+			return -EINVAL;
+		}
+		ep->stream_en = 1;
+	}
 	ep->desc = desc;
 
-	dev_dbg (udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n",
+	dev_dbg(udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d stream %s\n",
 		_ep->name,
 		desc->bEndpointAddress & 0x0f,
 		(desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
 		({ char *val;
-		 switch (desc->bmAttributes & 0x03) {
+		 switch (usb_endpoint_type(desc)) {
 		 case USB_ENDPOINT_XFER_BULK:
 			 val = "bulk";
 			 break;
@@ -531,7 +543,7 @@
 			 val = "ctrl";
 			 break;
 		 }; val; }),
-		max);
+		max, ep->stream_en ? "enabled" : "disabled");
 
 	/* at this point real hardware should be NAKing transfers
 	 * to that endpoint, until a buffer is queued to it.
@@ -542,67 +554,67 @@
 	return retval;
 }
 
-static int dummy_disable (struct usb_ep *_ep)
+static int dummy_disable(struct usb_ep *_ep)
 {
 	struct dummy_ep		*ep;
 	struct dummy		*dum;
 	unsigned long		flags;
 	int			retval;
 
-	ep = usb_ep_to_dummy_ep (_ep);
+	ep = usb_ep_to_dummy_ep(_ep);
 	if (!_ep || !ep->desc || _ep->name == ep0name)
 		return -EINVAL;
-	dum = ep_to_dummy (ep);
+	dum = ep_to_dummy(ep);
 
-	spin_lock_irqsave (&dum->lock, flags);
+	spin_lock_irqsave(&dum->lock, flags);
 	ep->desc = NULL;
+	ep->stream_en = 0;
 	retval = 0;
-	nuke (dum, ep);
-	spin_unlock_irqrestore (&dum->lock, flags);
+	nuke(dum, ep);
+	spin_unlock_irqrestore(&dum->lock, flags);
 
-	dev_dbg (udc_dev(dum), "disabled %s\n", _ep->name);
+	dev_dbg(udc_dev(dum), "disabled %s\n", _ep->name);
 	return retval;
 }
 
-static struct usb_request *
-dummy_alloc_request (struct usb_ep *_ep, gfp_t mem_flags)
+static struct usb_request *dummy_alloc_request(struct usb_ep *_ep,
+		gfp_t mem_flags)
 {
 	struct dummy_ep		*ep;
 	struct dummy_request	*req;
 
 	if (!_ep)
 		return NULL;
-	ep = usb_ep_to_dummy_ep (_ep);
+	ep = usb_ep_to_dummy_ep(_ep);
 
 	req = kzalloc(sizeof(*req), mem_flags);
 	if (!req)
 		return NULL;
-	INIT_LIST_HEAD (&req->queue);
+	INIT_LIST_HEAD(&req->queue);
 	return &req->req;
 }
 
-static void
-dummy_free_request (struct usb_ep *_ep, struct usb_request *_req)
+static void dummy_free_request(struct usb_ep *_ep, struct usb_request *_req)
 {
 	struct dummy_ep		*ep;
 	struct dummy_request	*req;
 
-	ep = usb_ep_to_dummy_ep (_ep);
-	if (!ep || !_req || (!ep->desc && _ep->name != ep0name))
+	if (!_ep || !_req)
+		return;
+	ep = usb_ep_to_dummy_ep(_ep);
+	if (!ep->desc && _ep->name != ep0name)
 		return;
 
-	req = usb_request_to_dummy_request (_req);
-	WARN_ON (!list_empty (&req->queue));
-	kfree (req);
+	req = usb_request_to_dummy_request(_req);
+	WARN_ON(!list_empty(&req->queue));
+	kfree(req);
 }
 
-static void
-fifo_complete (struct usb_ep *ep, struct usb_request *req)
+static void fifo_complete(struct usb_ep *ep, struct usb_request *req)
 {
 }
 
-static int
-dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
+static int dummy_queue(struct usb_ep *_ep, struct usb_request *_req,
 		gfp_t mem_flags)
 {
 	struct dummy_ep		*ep;
@@ -611,49 +623,48 @@
 	struct dummy_hcd	*dum_hcd;
 	unsigned long		flags;
 
-	req = usb_request_to_dummy_request (_req);
-	if (!_req || !list_empty (&req->queue) || !_req->complete)
+	req = usb_request_to_dummy_request(_req);
+	if (!_req || !list_empty(&req->queue) || !_req->complete)
 		return -EINVAL;
 
-	ep = usb_ep_to_dummy_ep (_ep);
+	ep = usb_ep_to_dummy_ep(_ep);
 	if (!_ep || (!ep->desc && _ep->name != ep0name))
 		return -EINVAL;
 
-	dum = ep_to_dummy (ep);
+	dum = ep_to_dummy(ep);
 	dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
 	if (!dum->driver || !is_enabled(dum_hcd))
 		return -ESHUTDOWN;
 
 #if 0
-	dev_dbg (udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n",
+	dev_dbg(udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n",
 			ep, _req, _ep->name, _req->length, _req->buf);
 #endif
-
 	_req->status = -EINPROGRESS;
 	_req->actual = 0;
-	spin_lock_irqsave (&dum->lock, flags);
+	spin_lock_irqsave(&dum->lock, flags);
 
 	/* implement an emulated single-request FIFO */
 	if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
-			list_empty (&dum->fifo_req.queue) &&
-			list_empty (&ep->queue) &&
+			list_empty(&dum->fifo_req.queue) &&
+			list_empty(&ep->queue) &&
 			_req->length <= FIFO_SIZE) {
 		req = &dum->fifo_req;
 		req->req = *_req;
 		req->req.buf = dum->fifo_buf;
-		memcpy (dum->fifo_buf, _req->buf, _req->length);
+		memcpy(dum->fifo_buf, _req->buf, _req->length);
 		req->req.context = dum;
 		req->req.complete = fifo_complete;
 
 		list_add_tail(&req->queue, &ep->queue);
-		spin_unlock (&dum->lock);
+		spin_unlock(&dum->lock);
 		_req->actual = _req->length;
 		_req->status = 0;
-		_req->complete (_ep, _req);
-		spin_lock (&dum->lock);
+		_req->complete(_ep, _req);
+		spin_lock(&dum->lock);
 	}  else
 		list_add_tail(&req->queue, &ep->queue);
-	spin_unlock_irqrestore (&dum->lock, flags);
+	spin_unlock_irqrestore(&dum->lock, flags);
 
 	/* real hardware would likely enable transfers here, in case
 	 * it'd been left NAKing.
@@ -661,7 +672,7 @@
 	return 0;
 }
 
-static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
+static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req)
 {
 	struct dummy_ep		*ep;
 	struct dummy		*dum;
@@ -671,31 +682,31 @@
 
 	if (!_ep || !_req)
 		return retval;
-	ep = usb_ep_to_dummy_ep (_ep);
-	dum = ep_to_dummy (ep);
+	ep = usb_ep_to_dummy_ep(_ep);
+	dum = ep_to_dummy(ep);
 
 	if (!dum->driver)
 		return -ESHUTDOWN;
 
-	local_irq_save (flags);
-	spin_lock (&dum->lock);
-	list_for_each_entry (req, &ep->queue, queue) {
+	local_irq_save(flags);
+	spin_lock(&dum->lock);
+	list_for_each_entry(req, &ep->queue, queue) {
 		if (&req->req == _req) {
-			list_del_init (&req->queue);
+			list_del_init(&req->queue);
 			_req->status = -ECONNRESET;
 			retval = 0;
 			break;
 		}
 	}
-	spin_unlock (&dum->lock);
+	spin_unlock(&dum->lock);
 
 	if (retval == 0) {
-		dev_dbg (udc_dev(dum),
+		dev_dbg(udc_dev(dum),
 				"dequeued req %p from %s, len %d buf %p\n",
 				req, _ep->name, _req->length, _req->buf);
-		_req->complete (_ep, _req);
+		_req->complete(_ep, _req);
 	}
-	local_irq_restore (flags);
+	local_irq_restore(flags);
 	return retval;
 }
 
@@ -707,14 +718,14 @@
 
 	if (!_ep)
 		return -EINVAL;
-	ep = usb_ep_to_dummy_ep (_ep);
-	dum = ep_to_dummy (ep);
+	ep = usb_ep_to_dummy_ep(_ep);
+	dum = ep_to_dummy(ep);
 	if (!dum->driver)
 		return -ESHUTDOWN;
 	if (!value)
 		ep->halted = ep->wedged = 0;
 	else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
-			!list_empty (&ep->queue))
+			!list_empty(&ep->queue))
 		return -EAGAIN;
 	else {
 		ep->halted = 1;
@@ -755,15 +766,15 @@
 /*-------------------------------------------------------------------------*/
 
 /* there are both host and device side versions of this call ... */
-static int dummy_g_get_frame (struct usb_gadget *_gadget)
+static int dummy_g_get_frame(struct usb_gadget *_gadget)
 {
 	struct timeval	tv;
 
-	do_gettimeofday (&tv);
+	do_gettimeofday(&tv);
 	return tv.tv_usec / 1000;
 }
 
-static int dummy_wakeup (struct usb_gadget *_gadget)
+static int dummy_wakeup(struct usb_gadget *_gadget)
 {
 	struct dummy_hcd *dum_hcd;
 
@@ -786,11 +797,11 @@
 	return 0;
 }
 
-static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value)
+static int dummy_set_selfpowered(struct usb_gadget *_gadget, int value)
 {
 	struct dummy	*dum;
 
-	dum = (gadget_to_dummy_hcd(_gadget))->dum;
+	dum = gadget_to_dummy_hcd(_gadget)->dum;
 	if (value)
 		dum->devstatus |= (1 << USB_DEVICE_SELF_POWERED);
 	else
@@ -798,22 +809,15 @@
 	return 0;
 }
 
-static void dummy_udc_udpate_ep0(struct dummy *dum)
+static void dummy_udc_update_ep0(struct dummy *dum)
 {
-	u32 i;
-
-	if (dum->gadget.speed == USB_SPEED_SUPER) {
-		for (i = 0; i < DUMMY_ENDPOINTS; i++)
-			dum->ep[i].ep.max_streams = 0x10;
+	if (dum->gadget.speed == USB_SPEED_SUPER)
 		dum->ep[0].ep.maxpacket = 9;
-	} else {
-		for (i = 0; i < DUMMY_ENDPOINTS; i++)
-			dum->ep[i].ep.max_streams = 0;
+	else
 		dum->ep[0].ep.maxpacket = 64;
-	}
 }
 
-static int dummy_pullup (struct usb_gadget *_gadget, int value)
+static int dummy_pullup(struct usb_gadget *_gadget, int value)
 {
 	struct dummy_hcd *dum_hcd;
 	struct dummy	*dum;
@@ -829,7 +833,7 @@
 					dum->driver->max_speed);
 		else
 			dum->gadget.speed = USB_SPEED_FULL;
-		dummy_udc_udpate_ep0(dum);
+		dummy_udc_update_ep0(dum);
 
 		if (dum->gadget.speed < dum->driver->max_speed)
 			dev_dbg(udc_dev(dum), "This device can perform faster"
@@ -838,10 +842,10 @@
 	}
 	dum_hcd = gadget_to_dummy_hcd(_gadget);
 
-	spin_lock_irqsave (&dum->lock, flags);
+	spin_lock_irqsave(&dum->lock, flags);
 	dum->pullup = (value != 0);
 	set_link_state(dum_hcd);
-	spin_unlock_irqrestore (&dum->lock, flags);
+	spin_unlock_irqrestore(&dum->lock, flags);
 
 	usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
 	return 0;
@@ -864,16 +868,16 @@
 /*-------------------------------------------------------------------------*/
 
 /* "function" sysfs attribute */
-static ssize_t
-show_function (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_function(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
-	struct dummy	*dum = gadget_dev_to_dummy (dev);
+	struct dummy	*dum = gadget_dev_to_dummy(dev);
 
 	if (!dum->driver || !dum->driver->function)
 		return 0;
-	return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", dum->driver->function);
 }
-static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
+static DEVICE_ATTR(function, S_IRUGO, show_function, NULL);
 
 /*-------------------------------------------------------------------------*/
 
@@ -908,7 +912,7 @@
 	dum->devstatus = 0;
 
 	dum->driver = driver;
-	dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
+	dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
 			driver->driver.name);
 	return 0;
 }
@@ -919,7 +923,7 @@
 	struct dummy_hcd	*dum_hcd = gadget_to_dummy_hcd(g);
 	struct dummy		*dum = dum_hcd->dum;
 
-	dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n",
+	dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
 			driver->driver.name);
 
 	dum->driver = NULL;
@@ -932,8 +936,7 @@
 
 /* The gadget structure is stored inside the hcd structure and will be
  * released along with it. */
-static void
-dummy_gadget_release (struct device *dev)
+static void dummy_gadget_release(struct device *dev)
 {
 	return;
 }
@@ -954,6 +957,7 @@
 		ep->halted = ep->wedged = ep->already_seen =
 				ep->setup_stage = 0;
 		ep->ep.maxpacket = ~0;
+		ep->ep.max_streams = 16;
 		ep->last_io = jiffies;
 		ep->gadget = &dum->gadget;
 		ep->desc = NULL;
@@ -969,7 +973,7 @@
 #endif
 }
 
-static int dummy_udc_probe (struct platform_device *pdev)
+static int dummy_udc_probe(struct platform_device *pdev)
 {
 	struct dummy	*dum = &the_controller;
 	int		rc;
@@ -981,7 +985,7 @@
 	dev_set_name(&dum->gadget.dev, "gadget");
 	dum->gadget.dev.parent = &pdev->dev;
 	dum->gadget.dev.release = dummy_gadget_release;
-	rc = device_register (&dum->gadget.dev);
+	rc = device_register(&dum->gadget.dev);
 	if (rc < 0) {
 		put_device(&dum->gadget.dev);
 		return rc;
@@ -993,7 +997,7 @@
 	if (rc < 0)
 		goto err_udc;
 
-	rc = device_create_file (&dum->gadget.dev, &dev_attr_function);
+	rc = device_create_file(&dum->gadget.dev, &dev_attr_function);
 	if (rc < 0)
 		goto err_dev;
 	platform_set_drvdata(pdev, dum);
@@ -1006,14 +1010,14 @@
 	return rc;
 }
 
-static int dummy_udc_remove (struct platform_device *pdev)
+static int dummy_udc_remove(struct platform_device *pdev)
 {
-	struct dummy	*dum = platform_get_drvdata (pdev);
+	struct dummy	*dum = platform_get_drvdata(pdev);
 
 	usb_del_gadget_udc(&dum->gadget);
-	platform_set_drvdata (pdev, NULL);
-	device_remove_file (&dum->gadget.dev, &dev_attr_function);
-	device_unregister (&dum->gadget.dev);
+	platform_set_drvdata(pdev, NULL);
+	device_remove_file(&dum->gadget.dev, &dev_attr_function);
+	device_unregister(&dum->gadget.dev);
 	return 0;
 }
 
@@ -1061,6 +1065,16 @@
 
 /*-------------------------------------------------------------------------*/
 
+static unsigned int dummy_get_ep_idx(const struct usb_endpoint_descriptor *desc)
+{
+	unsigned int index;
+
+	index = usb_endpoint_num(desc) << 1;
+	if (usb_endpoint_dir_in(desc))
+		index |= 1;
+	return index;
+}
+
 /* MASTER/HOST SIDE DRIVER
  *
  * this uses the hcd framework to hook up to host side drivers.
@@ -1073,7 +1087,82 @@
  * usb 2.0 rules.
  */
 
-static int dummy_urb_enqueue (
+static int dummy_ep_stream_en(struct dummy_hcd *dum_hcd, struct urb *urb)
+{
+	const struct usb_endpoint_descriptor *desc = &urb->ep->desc;
+	u32 index;
+
+	if (!usb_endpoint_xfer_bulk(desc))
+		return 0;
+
+	index = dummy_get_ep_idx(desc);
+	return (1 << index) & dum_hcd->stream_en_ep;
+}
+
+/*
+ * The max stream number is saved as a nibble so for the 30 possible endpoints
+ * we only 15 bytes of memory. Therefore we are limited to max 16 streams (0
+ * means we use only 1 stream). The maximum according to the spec is 16bit so
+ * if the 16 stream limit is about to go, the array size should be incremented
+ * to 30 elements of type u16.
+ */
+static int get_max_streams_for_pipe(struct dummy_hcd *dum_hcd,
+		unsigned int pipe)
+{
+	int max_streams;
+
+	max_streams = dum_hcd->num_stream[usb_pipeendpoint(pipe)];
+	if (usb_pipeout(pipe))
+		max_streams >>= 4;
+	else
+		max_streams &= 0xf;
+	max_streams++;
+	return max_streams;
+}
+
+static void set_max_streams_for_pipe(struct dummy_hcd *dum_hcd,
+		unsigned int pipe, unsigned int streams)
+{
+	int max_streams;
+
+	streams--;
+	max_streams = dum_hcd->num_stream[usb_pipeendpoint(pipe)];
+	if (usb_pipeout(pipe)) {
+		streams <<= 4;
+		max_streams &= 0xf;
+	} else {
+		max_streams &= 0xf0;
+	}
+	max_streams |= streams;
+	dum_hcd->num_stream[usb_pipeendpoint(pipe)] = max_streams;
+}
+
+static int dummy_validate_stream(struct dummy_hcd *dum_hcd, struct urb *urb)
+{
+	unsigned int max_streams;
+	int enabled;
+
+	enabled = dummy_ep_stream_en(dum_hcd, urb);
+	if (!urb->stream_id) {
+		if (enabled)
+			return -EINVAL;
+		return 0;
+	}
+	if (!enabled)
+		return -EINVAL;
+
+	max_streams = get_max_streams_for_pipe(dum_hcd,
+			usb_pipeendpoint(urb->pipe));
+	if (urb->stream_id > max_streams) {
+		dev_err(dummy_dev(dum_hcd), "Stream id %d is out of range.\n",
+				urb->stream_id);
+		BUG();
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int dummy_urb_enqueue(
 	struct usb_hcd			*hcd,
 	struct urb			*urb,
 	gfp_t				mem_flags
@@ -1083,16 +1172,21 @@
 	unsigned long	flags;
 	int		rc;
 
-	if (!urb->transfer_buffer && urb->transfer_buffer_length)
-		return -EINVAL;
-
-	urbp = kmalloc (sizeof *urbp, mem_flags);
+	urbp = kmalloc(sizeof *urbp, mem_flags);
 	if (!urbp)
 		return -ENOMEM;
 	urbp->urb = urb;
+	urbp->miter_started = 0;
 
 	dum_hcd = hcd_to_dummy_hcd(hcd);
 	spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+
+	rc = dummy_validate_stream(dum_hcd, urb);
+	if (rc) {
+		kfree(urbp);
+		goto done;
+	}
+
 	rc = usb_hcd_link_urb_to_ep(hcd, urb);
 	if (rc) {
 		kfree(urbp);
@@ -1107,7 +1201,7 @@
 
 	list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list);
 	urb->hcpriv = urbp;
-	if (usb_pipetype (urb->pipe) == PIPE_CONTROL)
+	if (usb_pipetype(urb->pipe) == PIPE_CONTROL)
 		urb->error_count = 1;		/* mark as a new urb */
 
 	/* kick the scheduler, it'll do the rest */
@@ -1139,20 +1233,91 @@
 	return rc;
 }
 
-/* transfer up to a frame's worth; caller must own lock */
-static int
-transfer(struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit,
-		int *status)
+static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req,
+		u32 len)
 {
+	void *ubuf, *rbuf;
+	struct urbp *urbp = urb->hcpriv;
+	int to_host;
+	struct sg_mapping_iter *miter = &urbp->miter;
+	u32 trans = 0;
+	u32 this_sg;
+	bool next_sg;
+
+	to_host = usb_pipein(urb->pipe);
+	rbuf = req->req.buf + req->req.actual;
+
+	if (!urb->num_sgs) {
+		ubuf = urb->transfer_buffer + urb->actual_length;
+		if (to_host)
+			memcpy(ubuf, rbuf, len);
+		else
+			memcpy(rbuf, ubuf, len);
+		return len;
+	}
+
+	if (!urbp->miter_started) {
+		u32 flags = SG_MITER_ATOMIC;
+
+		if (to_host)
+			flags |= SG_MITER_TO_SG;
+		else
+			flags |= SG_MITER_FROM_SG;
+
+		sg_miter_start(miter, urb->sg, urb->num_sgs, flags);
+		urbp->miter_started = 1;
+	}
+	next_sg = sg_miter_next(miter);
+	if (next_sg == false) {
+		WARN_ON_ONCE(1);
+		return -EINVAL;
+	}
+	do {
+		ubuf = miter->addr;
+		this_sg = min_t(u32, len, miter->length);
+		miter->consumed = this_sg;
+		trans += this_sg;
+
+		if (to_host)
+			memcpy(ubuf, rbuf, this_sg);
+		else
+			memcpy(rbuf, ubuf, this_sg);
+		len -= this_sg;
+
+		if (!len)
+			break;
+		next_sg = sg_miter_next(miter);
+		if (next_sg == false) {
+			WARN_ON_ONCE(1);
+			return -EINVAL;
+		}
+
+		rbuf += this_sg;
+	} while (1);
+
+	sg_miter_stop(miter);
+	return trans;
+}
+
+/* transfer up to a frame's worth; caller must own lock */
+static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
+		struct dummy_ep *ep, int limit, int *status)
+{
+	struct dummy		*dum = dum_hcd->dum;
 	struct dummy_request	*req;
 
 top:
 	/* if there's no request queued, the device is NAKing; return */
-	list_for_each_entry (req, &ep->queue, queue) {
+	list_for_each_entry(req, &ep->queue, queue) {
 		unsigned	host_len, dev_len, len;
 		int		is_short, to_host;
 		int		rescan = 0;
 
+		if (dummy_ep_stream_en(dum_hcd, urb)) {
+			if ((urb->stream_id != req->req.stream_id))
+				continue;
+		}
+
 		/* 1..N packets of ep->ep.maxpacket each ... the last one
 		 * may be short (including zero length).
 		 *
@@ -1162,20 +1327,18 @@
 		 */
 		host_len = urb->transfer_buffer_length - urb->actual_length;
 		dev_len = req->req.length - req->req.actual;
-		len = min (host_len, dev_len);
+		len = min(host_len, dev_len);
 
 		/* FIXME update emulated data toggle too */
 
-		to_host = usb_pipein (urb->pipe);
-		if (unlikely (len == 0))
+		to_host = usb_pipein(urb->pipe);
+		if (unlikely(len == 0))
 			is_short = 1;
 		else {
-			char		*ubuf, *rbuf;
-
 			/* not enough bandwidth left? */
 			if (limit < ep->ep.maxpacket && limit < len)
 				break;
-			len = min (len, (unsigned) limit);
+			len = min_t(unsigned, len, limit);
 			if (len == 0)
 				break;
 
@@ -1186,18 +1349,16 @@
 			}
 			is_short = (len % ep->ep.maxpacket) != 0;
 
-			/* else transfer packet(s) */
-			ubuf = urb->transfer_buffer + urb->actual_length;
-			rbuf = req->req.buf + req->req.actual;
-			if (to_host)
-				memcpy (ubuf, rbuf, len);
-			else
-				memcpy (rbuf, ubuf, len);
-			ep->last_io = jiffies;
+			len = dummy_perform_transfer(urb, req, len);
 
-			limit -= len;
-			urb->actual_length += len;
-			req->req.actual += len;
+			ep->last_io = jiffies;
+			if ((int)len < 0) {
+				req->req.status = len;
+			} else {
+				limit -= len;
+				urb->actual_length += len;
+				req->req.actual += len;
+			}
 		}
 
 		/* short packets terminate, maybe with overflow/underflow.
@@ -1238,11 +1399,11 @@
 
 		/* device side completion --> continuable */
 		if (req->req.status != -EINPROGRESS) {
-			list_del_init (&req->queue);
+			list_del_init(&req->queue);
 
-			spin_unlock (&dum->lock);
-			req->req.complete (&ep->ep, &req->req);
-			spin_lock (&dum->lock);
+			spin_unlock(&dum->lock);
+			req->req.complete(&ep->ep, &req->req);
+			spin_lock(&dum->lock);
 
 			/* requests might have been unlinked... */
 			rescan = 1;
@@ -1259,7 +1420,7 @@
 	return limit;
 }
 
-static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)
+static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep)
 {
 	int	limit = ep->ep.maxpacket;
 
@@ -1273,7 +1434,7 @@
 		limit += limit * tmp;
 	}
 	if (dum->gadget.speed == USB_SPEED_SUPER) {
-		switch (ep->desc->bmAttributes & 0x03) {
+		switch (usb_endpoint_type(ep->desc)) {
 		case USB_ENDPOINT_XFER_ISOC:
 			/* Sec. 4.4.8.2 USB3.0 Spec */
 			limit = 3 * 16 * 1024 * 8;
@@ -1295,7 +1456,7 @@
 			USB_PORT_STAT_SUSPEND)) \
 		== (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE))
 
-static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
+static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address)
 {
 	int		i;
 
@@ -1303,9 +1464,9 @@
 			dum->ss_hcd : dum->hs_hcd)))
 		return NULL;
 	if ((address & ~USB_DIR_IN) == 0)
-		return &dum->ep [0];
+		return &dum->ep[0];
 	for (i = 1; i < DUMMY_ENDPOINTS; i++) {
-		struct dummy_ep	*ep = &dum->ep [i];
+		struct dummy_ep	*ep = &dum->ep[i];
 
 		if (!ep->desc)
 			continue;
@@ -1535,19 +1696,19 @@
 	/* FIXME if HZ != 1000 this will probably misbehave ... */
 
 	/* look at each urb queued by the host side driver */
-	spin_lock_irqsave (&dum->lock, flags);
+	spin_lock_irqsave(&dum->lock, flags);
 
 	if (!dum_hcd->udev) {
 		dev_err(dummy_dev(dum_hcd),
 				"timer fired with no URBs pending?\n");
-		spin_unlock_irqrestore (&dum->lock, flags);
+		spin_unlock_irqrestore(&dum->lock, flags);
 		return;
 	}
 
 	for (i = 0; i < DUMMY_ENDPOINTS; i++) {
-		if (!ep_name [i])
+		if (!ep_name[i])
 			break;
-		dum->ep [i].already_seen = 0;
+		dum->ep[i].already_seen = 0;
 	}
 
 restart:
@@ -1564,7 +1725,7 @@
 			goto return_urb;
 		else if (dum_hcd->rh_state != DUMMY_RH_RUNNING)
 			continue;
-		type = usb_pipetype (urb->pipe);
+		type = usb_pipetype(urb->pipe);
 
 		/* used up this frame's non-periodic bandwidth?
 		 * FIXME there's infinite bandwidth for control and
@@ -1575,7 +1736,7 @@
 
 		/* find the gadget's ep for this request (if configured) */
 		address = usb_pipeendpoint (urb->pipe);
-		if (usb_pipein (urb->pipe))
+		if (usb_pipein(urb->pipe))
 			address |= USB_DIR_IN;
 		ep = find_endpoint(dum, address);
 		if (!ep) {
@@ -1590,7 +1751,7 @@
 		if (ep->already_seen)
 			continue;
 		ep->already_seen = 1;
-		if (ep == &dum->ep [0] && urb->error_count) {
+		if (ep == &dum->ep[0] && urb->error_count) {
 			ep->setup_stage = 1;	/* a new urb */
 			urb->error_count = 0;
 		}
@@ -1604,21 +1765,21 @@
 		/* FIXME make sure both ends agree on maxpacket */
 
 		/* handle control requests */
-		if (ep == &dum->ep [0] && ep->setup_stage) {
+		if (ep == &dum->ep[0] && ep->setup_stage) {
 			struct usb_ctrlrequest		setup;
 			int				value = 1;
 
-			setup = *(struct usb_ctrlrequest*) urb->setup_packet;
+			setup = *(struct usb_ctrlrequest *) urb->setup_packet;
 			/* paranoia, in case of stale queued data */
-			list_for_each_entry (req, &ep->queue, queue) {
-				list_del_init (&req->queue);
+			list_for_each_entry(req, &ep->queue, queue) {
+				list_del_init(&req->queue);
 				req->req.status = -EOVERFLOW;
-				dev_dbg (udc_dev(dum), "stale req = %p\n",
+				dev_dbg(udc_dev(dum), "stale req = %p\n",
 						req);
 
-				spin_unlock (&dum->lock);
-				req->req.complete (&ep->ep, &req->req);
-				spin_lock (&dum->lock);
+				spin_unlock(&dum->lock);
+				req->req.complete(&ep->ep, &req->req);
+				spin_lock(&dum->lock);
 				ep->already_seen = 0;
 				goto restart;
 			}
@@ -1638,10 +1799,10 @@
 			 * until setup() returns; no reentrancy issues etc.
 			 */
 			if (value > 0) {
-				spin_unlock (&dum->lock);
-				value = dum->driver->setup (&dum->gadget,
+				spin_unlock(&dum->lock);
+				value = dum->driver->setup(&dum->gadget,
 						&setup);
-				spin_lock (&dum->lock);
+				spin_lock(&dum->lock);
 
 				if (value >= 0) {
 					/* no delays (max 64KB data stage) */
@@ -1653,7 +1814,7 @@
 
 			if (value < 0) {
 				if (value != -EOPNOTSUPP)
-					dev_dbg (udc_dev(dum),
+					dev_dbg(udc_dev(dum),
 						"setup --> %d\n",
 						value);
 				status = -EPIPE;
@@ -1665,14 +1826,14 @@
 
 		/* non-control requests */
 		limit = total;
-		switch (usb_pipetype (urb->pipe)) {
+		switch (usb_pipetype(urb->pipe)) {
 		case PIPE_ISOCHRONOUS:
 			/* FIXME is it urb->interval since the last xfer?
 			 * use urb->iso_frame_desc[i].
 			 * complete whether or not ep has requests queued.
 			 * report random errors, to debug drivers.
 			 */
-			limit = max (limit, periodic_bytes (dum, ep));
+			limit = max(limit, periodic_bytes(dum, ep));
 			status = -ENOSYS;
 			break;
 
@@ -1680,14 +1841,13 @@
 			/* FIXME is it urb->interval since the last xfer?
 			 * this almost certainly polls too fast.
 			 */
-			limit = max (limit, periodic_bytes (dum, ep));
+			limit = max(limit, periodic_bytes(dum, ep));
 			/* FALLTHROUGH */
 
-		// case PIPE_BULK:  case PIPE_CONTROL:
 		default:
-		treat_control_like_bulk:
+treat_control_like_bulk:
 			ep->last_io = jiffies;
-			total = transfer(dum, urb, ep, limit, &status);
+			total = transfer(dum_hcd, urb, ep, limit, &status);
 			break;
 		}
 
@@ -1696,15 +1856,15 @@
 			continue;
 
 return_urb:
-		list_del (&urbp->urbp_list);
-		kfree (urbp);
+		list_del(&urbp->urbp_list);
+		kfree(urbp);
 		if (ep)
 			ep->already_seen = ep->setup_stage = 0;
 
 		usb_hcd_unlink_urb_from_ep(dummy_hcd_to_hcd(dum_hcd), urb);
-		spin_unlock (&dum->lock);
+		spin_unlock(&dum->lock);
 		usb_hcd_giveback_urb(dummy_hcd_to_hcd(dum_hcd), urb, status);
-		spin_lock (&dum->lock);
+		spin_lock(&dum->lock);
 
 		goto restart;
 	}
@@ -1717,7 +1877,7 @@
 		mod_timer(&dum_hcd->timer, jiffies + msecs_to_jiffies(1));
 	}
 
-	spin_unlock_irqrestore (&dum->lock, flags);
+	spin_unlock_irqrestore(&dum->lock, flags);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1729,7 +1889,7 @@
 	| USB_PORT_STAT_C_OVERCURRENT \
 	| USB_PORT_STAT_C_RESET) << 16)
 
-static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
+static int dummy_hub_status(struct usb_hcd *hcd, char *buf)
 {
 	struct dummy_hcd	*dum_hcd;
 	unsigned long		flags;
@@ -1753,7 +1913,7 @@
 				dum_hcd->port_status);
 		retval = 1;
 		if (dum_hcd->rh_state == DUMMY_RH_SUSPENDED)
-			usb_hcd_resume_root_hub (hcd);
+			usb_hcd_resume_root_hub(hcd);
 	}
 done:
 	spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
@@ -1772,10 +1932,9 @@
 	desc->u.ss.DeviceRemovable = 0xffff;
 }
 
-static inline void
-hub_descriptor (struct usb_hub_descriptor *desc)
+static inline void hub_descriptor(struct usb_hub_descriptor *desc)
 {
-	memset (desc, 0, sizeof *desc);
+	memset(desc, 0, sizeof *desc);
 	desc->bDescriptorType = 0x29;
 	desc->bDescLength = 9;
 	desc->wHubCharacteristics = cpu_to_le16(0x0001);
@@ -1784,7 +1943,7 @@
 	desc->u.hs.DeviceRemovable[1] = 0xff;
 }
 
-static int dummy_hub_control (
+static int dummy_hub_control(
 	struct usb_hcd	*hcd,
 	u16		typeReq,
 	u16		wValue,
@@ -1852,7 +2011,7 @@
 			hub_descriptor((struct usb_hub_descriptor *) buf);
 		break;
 	case GetHubStatus:
-		*(__le32 *) buf = cpu_to_le32 (0);
+		*(__le32 *) buf = cpu_to_le32(0);
 		break;
 	case GetPortStatus:
 		if (wIndex != 1)
@@ -1894,8 +2053,8 @@
 			}
 		}
 		set_link_state(dum_hcd);
-		((__le16 *) buf)[0] = cpu_to_le16 (dum_hcd->port_status);
-		((__le16 *) buf)[1] = cpu_to_le16 (dum_hcd->port_status >> 16);
+		((__le16 *) buf)[0] = cpu_to_le16(dum_hcd->port_status);
+		((__le16 *) buf)[1] = cpu_to_le16(dum_hcd->port_status >> 16);
 		break;
 	case SetHubFeature:
 		retval = -EPIPE;
@@ -2029,15 +2188,15 @@
 	spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
 
 	if ((dum_hcd->port_status & PORT_C_MASK) != 0)
-		usb_hcd_poll_rh_status (hcd);
+		usb_hcd_poll_rh_status(hcd);
 	return retval;
 }
 
-static int dummy_bus_suspend (struct usb_hcd *hcd)
+static int dummy_bus_suspend(struct usb_hcd *hcd)
 {
 	struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
 
-	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
+	dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
 
 	spin_lock_irq(&dum_hcd->dum->lock);
 	dum_hcd->rh_state = DUMMY_RH_SUSPENDED;
@@ -2047,12 +2206,12 @@
 	return 0;
 }
 
-static int dummy_bus_resume (struct usb_hcd *hcd)
+static int dummy_bus_resume(struct usb_hcd *hcd)
 {
 	struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
 	int rc = 0;
 
-	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
+	dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
 
 	spin_lock_irq(&dum_hcd->dum->lock);
 	if (!HCD_HW_ACCESSIBLE(hcd)) {
@@ -2070,55 +2229,54 @@
 
 /*-------------------------------------------------------------------------*/
 
-static inline ssize_t
-show_urb (char *buf, size_t size, struct urb *urb)
+static inline ssize_t show_urb(char *buf, size_t size, struct urb *urb)
 {
-	int ep = usb_pipeendpoint (urb->pipe);
+	int ep = usb_pipeendpoint(urb->pipe);
 
-	return snprintf (buf, size,
+	return snprintf(buf, size,
 		"urb/%p %s ep%d%s%s len %d/%d\n",
 		urb,
 		({ char *s;
-		 switch (urb->dev->speed) {
-		 case USB_SPEED_LOW:
+		switch (urb->dev->speed) {
+		case USB_SPEED_LOW:
 			s = "ls";
 			break;
-		 case USB_SPEED_FULL:
+		case USB_SPEED_FULL:
 			s = "fs";
 			break;
-		 case USB_SPEED_HIGH:
+		case USB_SPEED_HIGH:
 			s = "hs";
 			break;
-		 case USB_SPEED_SUPER:
+		case USB_SPEED_SUPER:
 			s = "ss";
 			break;
-		 default:
+		default:
 			s = "?";
 			break;
 		 }; s; }),
-		ep, ep ? (usb_pipein (urb->pipe) ? "in" : "out") : "",
+		ep, ep ? (usb_pipein(urb->pipe) ? "in" : "out") : "",
 		({ char *s; \
-		 switch (usb_pipetype (urb->pipe)) { \
-		 case PIPE_CONTROL: \
+		switch (usb_pipetype(urb->pipe)) { \
+		case PIPE_CONTROL: \
 			s = ""; \
 			break; \
-		 case PIPE_BULK: \
+		case PIPE_BULK: \
 			s = "-bulk"; \
 			break; \
-		 case PIPE_INTERRUPT: \
+		case PIPE_INTERRUPT: \
 			s = "-int"; \
 			break; \
-		 default: \
+		default: \
 			s = "-iso"; \
 			break; \
-		}; s;}),
+		}; s; }),
 		urb->actual_length, urb->transfer_buffer_length);
 }
 
-static ssize_t
-show_urbs (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_urbs(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
-	struct usb_hcd		*hcd = dev_get_drvdata (dev);
+	struct usb_hcd		*hcd = dev_get_drvdata(dev);
 	struct dummy_hcd	*dum_hcd = hcd_to_dummy_hcd(hcd);
 	struct urbp		*urbp;
 	size_t			size = 0;
@@ -2128,7 +2286,7 @@
 	list_for_each_entry(urbp, &dum_hcd->urbp_list, urbp_list) {
 		size_t		temp;
 
-		temp = show_urb (buf, PAGE_SIZE - size, urbp->urb);
+		temp = show_urb(buf, PAGE_SIZE - size, urbp->urb);
 		buf += temp;
 		size += temp;
 	}
@@ -2136,7 +2294,7 @@
 
 	return size;
 }
-static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL);
+static DEVICE_ATTR(urbs, S_IRUGO, show_urbs, NULL);
 
 static int dummy_start_ss(struct dummy_hcd *dum_hcd)
 {
@@ -2144,6 +2302,7 @@
 	dum_hcd->timer.function = dummy_timer;
 	dum_hcd->timer.data = (unsigned long)dum_hcd;
 	dum_hcd->rh_state = DUMMY_RH_RUNNING;
+	dum_hcd->stream_en_ep = 0;
 	INIT_LIST_HEAD(&dum_hcd->urbp_list);
 	dummy_hcd_to_hcd(dum_hcd)->power_budget = POWER_BUDGET;
 	dummy_hcd_to_hcd(dum_hcd)->state = HC_STATE_RUNNING;
@@ -2189,11 +2348,11 @@
 	return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs);
 }
 
-static void dummy_stop (struct usb_hcd *hcd)
+static void dummy_stop(struct usb_hcd *hcd)
 {
 	struct dummy		*dum;
 
-	dum = (hcd_to_dummy_hcd(hcd))->dum;
+	dum = hcd_to_dummy_hcd(hcd)->dum;
 	device_remove_file(dummy_dev(hcd_to_dummy_hcd(hcd)), &dev_attr_urbs);
 	usb_gadget_unregister_driver(dum->driver);
 	dev_info(dummy_dev(hcd_to_dummy_hcd(hcd)), "stopped\n");
@@ -2201,13 +2360,14 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int dummy_h_get_frame (struct usb_hcd *hcd)
+static int dummy_h_get_frame(struct usb_hcd *hcd)
 {
-	return dummy_g_get_frame (NULL);
+	return dummy_g_get_frame(NULL);
 }
 
 static int dummy_setup(struct usb_hcd *hcd)
 {
+	hcd->self.sg_tablesize = ~0;
 	if (usb_hcd_is_primary_hcd(hcd)) {
 		the_controller.hs_hcd = hcd_to_dummy_hcd(hcd);
 		the_controller.hs_hcd->dum = &the_controller;
@@ -2228,27 +2388,82 @@
 }
 
 /* Change a group of bulk endpoints to support multiple stream IDs */
-int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
+static int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
 	struct usb_host_endpoint **eps, unsigned int num_eps,
 	unsigned int num_streams, gfp_t mem_flags)
 {
-	if (hcd->speed != HCD_USB3)
-		dev_dbg(dummy_dev(hcd_to_dummy_hcd(hcd)),
-			"%s() - ERROR! Not supported for USB2.0 roothub\n",
-			__func__);
-	return 0;
+	struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
+	unsigned long flags;
+	int max_stream;
+	int ret_streams = num_streams;
+	unsigned int index;
+	unsigned int i;
+
+	if (!num_eps)
+		return -EINVAL;
+
+	spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+	for (i = 0; i < num_eps; i++) {
+		index = dummy_get_ep_idx(&eps[i]->desc);
+		if ((1 << index) & dum_hcd->stream_en_ep) {
+			ret_streams = -EINVAL;
+			goto out;
+		}
+		max_stream = usb_ss_max_streams(&eps[i]->ss_ep_comp);
+		if (!max_stream) {
+			ret_streams = -EINVAL;
+			goto out;
+		}
+		if (max_stream < ret_streams) {
+			dev_dbg(dummy_dev(dum_hcd), "Ep 0x%x only supports %u "
+					"stream IDs.\n",
+					eps[i]->desc.bEndpointAddress,
+					max_stream);
+			ret_streams = max_stream;
+		}
+	}
+
+	for (i = 0; i < num_eps; i++) {
+		index = dummy_get_ep_idx(&eps[i]->desc);
+		dum_hcd->stream_en_ep |= 1 << index;
+		set_max_streams_for_pipe(dum_hcd,
+				usb_endpoint_num(&eps[i]->desc), ret_streams);
+	}
+out:
+	spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
+	return ret_streams;
 }
 
 /* Reverts a group of bulk endpoints back to not using stream IDs. */
-int dummy_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
+static int dummy_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
 	struct usb_host_endpoint **eps, unsigned int num_eps,
 	gfp_t mem_flags)
 {
-	if (hcd->speed != HCD_USB3)
-		dev_dbg(dummy_dev(hcd_to_dummy_hcd(hcd)),
-			"%s() - ERROR! Not supported for USB2.0 roothub\n",
-			__func__);
-	return 0;
+	struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
+	unsigned long flags;
+	int ret;
+	unsigned int index;
+	unsigned int i;
+
+	spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+	for (i = 0; i < num_eps; i++) {
+		index = dummy_get_ep_idx(&eps[i]->desc);
+		if (!((1 << index) & dum_hcd->stream_en_ep)) {
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	for (i = 0; i < num_eps; i++) {
+		index = dummy_get_ep_idx(&eps[i]->desc);
+		dum_hcd->stream_en_ep &= ~(1 << index);
+		set_max_streams_for_pipe(dum_hcd,
+				usb_endpoint_num(&eps[i]->desc), 0);
+	}
+	ret = 0;
+out:
+	spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
+	return ret;
 }
 
 static struct hc_driver dummy_hcd = {
@@ -2262,13 +2477,13 @@
 	.start =		dummy_start,
 	.stop =			dummy_stop,
 
-	.urb_enqueue = 		dummy_urb_enqueue,
-	.urb_dequeue = 		dummy_urb_dequeue,
+	.urb_enqueue =		dummy_urb_enqueue,
+	.urb_dequeue =		dummy_urb_dequeue,
 
-	.get_frame_number = 	dummy_h_get_frame,
+	.get_frame_number =	dummy_h_get_frame,
 
-	.hub_status_data = 	dummy_hub_status,
-	.hub_control = 		dummy_hub_control,
+	.hub_status_data =	dummy_hub_status,
+	.hub_control =		dummy_hub_control,
 	.bus_suspend =		dummy_bus_suspend,
 	.bus_resume =		dummy_bus_resume,
 
@@ -2323,7 +2538,7 @@
 {
 	struct dummy		*dum;
 
-	dum = (hcd_to_dummy_hcd(platform_get_drvdata(pdev)))->dum;
+	dum = hcd_to_dummy_hcd(platform_get_drvdata(pdev))->dum;
 
 	if (dum->ss_hcd) {
 		usb_remove_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
@@ -2339,15 +2554,15 @@
 	return 0;
 }
 
-static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
+static int dummy_hcd_suspend(struct platform_device *pdev, pm_message_t state)
 {
 	struct usb_hcd		*hcd;
 	struct dummy_hcd	*dum_hcd;
 	int			rc = 0;
 
-	dev_dbg (&pdev->dev, "%s\n", __func__);
+	dev_dbg(&pdev->dev, "%s\n", __func__);
 
-	hcd = platform_get_drvdata (pdev);
+	hcd = platform_get_drvdata(pdev);
 	dum_hcd = hcd_to_dummy_hcd(hcd);
 	if (dum_hcd->rh_state == DUMMY_RH_RUNNING) {
 		dev_warn(&pdev->dev, "Root hub isn't suspended!\n");
@@ -2357,15 +2572,15 @@
 	return rc;
 }
 
-static int dummy_hcd_resume (struct platform_device *pdev)
+static int dummy_hcd_resume(struct platform_device *pdev)
 {
 	struct usb_hcd		*hcd;
 
-	dev_dbg (&pdev->dev, "%s\n", __func__);
+	dev_dbg(&pdev->dev, "%s\n", __func__);
 
-	hcd = platform_get_drvdata (pdev);
+	hcd = platform_get_drvdata(pdev);
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	usb_hcd_poll_rh_status (hcd);
+	usb_hcd_poll_rh_status(hcd);
 	return 0;
 }
 
@@ -2385,11 +2600,11 @@
 static struct platform_device *the_udc_pdev;
 static struct platform_device *the_hcd_pdev;
 
-static int __init init (void)
+static int __init init(void)
 {
 	int	retval = -ENOMEM;
 
-	if (usb_disabled ())
+	if (usb_disabled())
 		return -ENODEV;
 
 	if (!mod_data.is_high_speed && mod_data.is_super_speed)
@@ -2448,13 +2663,13 @@
 	platform_device_put(the_hcd_pdev);
 	return retval;
 }
-module_init (init);
+module_init(init);
 
-static void __exit cleanup (void)
+static void __exit cleanup(void)
 {
 	platform_device_unregister(the_udc_pdev);
 	platform_device_unregister(the_hcd_pdev);
 	platform_driver_unregister(&dummy_udc_driver);
 	platform_driver_unregister(&dummy_hcd_driver);
 }
-module_exit (cleanup);
+module_exit(cleanup);
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index e0e6375..51f3d42 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -275,24 +275,24 @@
 		/* ep-e, ep-f are PIO with only 64 byte fifos */
 		ep = find_ep (gadget, "ep-e");
 		if (ep && ep_matches(gadget, ep, desc, ep_comp))
-			return ep;
+			goto found_ep;
 		ep = find_ep (gadget, "ep-f");
 		if (ep && ep_matches(gadget, ep, desc, ep_comp))
-			return ep;
+			goto found_ep;
 
 	} else if (gadget_is_goku (gadget)) {
 		if (USB_ENDPOINT_XFER_INT == type) {
 			/* single buffering is enough */
 			ep = find_ep(gadget, "ep3-bulk");
 			if (ep && ep_matches(gadget, ep, desc, ep_comp))
-				return ep;
+				goto found_ep;
 		} else if (USB_ENDPOINT_XFER_BULK == type
 				&& (USB_DIR_IN & desc->bEndpointAddress)) {
 			/* DMA may be available */
 			ep = find_ep(gadget, "ep2-bulk");
 			if (ep && ep_matches(gadget, ep, desc,
 					      ep_comp))
-				return ep;
+				goto found_ep;
 		}
 
 #ifdef CONFIG_BLACKFIN
@@ -311,18 +311,22 @@
 		} else
 			ep = NULL;
 		if (ep && ep_matches(gadget, ep, desc, ep_comp))
-			return ep;
+			goto found_ep;
 #endif
 	}
 
 	/* Second, look at endpoints until an unclaimed one looks usable */
 	list_for_each_entry (ep, &gadget->ep_list, ep_list) {
 		if (ep_matches(gadget, ep, desc, ep_comp))
-			return ep;
+			goto found_ep;
 	}
 
 	/* Fail */
 	return NULL;
+found_ep:
+	ep->desc = NULL;
+	ep->comp_desc = NULL;
+	return ep;
 }
 
 /**
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 3f88493..d672250a 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -5,7 +5,7 @@
  * Copyright (C) 2008 by David Brownell
  * Copyright (C) 2008 by Nokia Corporation
  * Copyright (C) 2009 by Samsung Electronics
- * Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
+ * Author: Michal Nazarewicz (mina86@mina86.com)
  *
  * This software is distributed under the terms of the GNU General
  * Public License ("GPL") as published by the Free Software Foundation,
@@ -237,6 +237,42 @@
 	NULL,
 };
 
+static struct usb_endpoint_descriptor acm_ss_in_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_endpoint_descriptor acm_ss_out_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor acm_ss_bulk_comp_desc = {
+	.bLength =              sizeof acm_ss_bulk_comp_desc,
+	.bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
+};
+
+static struct usb_descriptor_header *acm_ss_function[] = {
+	(struct usb_descriptor_header *) &acm_iad_descriptor,
+	(struct usb_descriptor_header *) &acm_control_interface_desc,
+	(struct usb_descriptor_header *) &acm_header_desc,
+	(struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &acm_descriptor,
+	(struct usb_descriptor_header *) &acm_union_desc,
+	(struct usb_descriptor_header *) &acm_hs_notify_desc,
+	(struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
+	(struct usb_descriptor_header *) &acm_data_interface_desc,
+	(struct usb_descriptor_header *) &acm_ss_in_desc,
+	(struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
+	(struct usb_descriptor_header *) &acm_ss_out_desc,
+	(struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
+	NULL,
+};
+
 /* string descriptors: */
 
 #define ACM_CTRL_IDX	0
@@ -643,9 +679,21 @@
 		/* copy descriptors */
 		f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
 	}
+	if (gadget_is_superspeed(c->cdev->gadget)) {
+		acm_ss_in_desc.bEndpointAddress =
+			acm_fs_in_desc.bEndpointAddress;
+		acm_ss_out_desc.bEndpointAddress =
+			acm_fs_out_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->ss_descriptors = usb_copy_descriptors(acm_ss_function);
+		if (!f->ss_descriptors)
+			goto fail;
+	}
 
 	DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
 			acm->port_num,
+			gadget_is_superspeed(c->cdev->gadget) ? "super" :
 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
 			acm->port.in->name, acm->port.out->name,
 			acm->notify->name);
@@ -675,6 +723,8 @@
 
 	if (gadget_is_dualspeed(c->cdev->gadget))
 		usb_free_descriptors(f->hs_descriptors);
+	if (gadget_is_superspeed(c->cdev->gadget))
+		usb_free_descriptors(f->ss_descriptors);
 	usb_free_descriptors(f->descriptors);
 	gs_free_req(acm->notify, acm->notify_req);
 	kfree(acm);
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index 11c07cb..30b908f 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -97,6 +97,20 @@
 
 /* interface descriptor: */
 
+static struct usb_interface_assoc_descriptor
+ecm_iad_descriptor = {
+	.bLength =		sizeof ecm_iad_descriptor,
+	.bDescriptorType =	USB_DT_INTERFACE_ASSOCIATION,
+
+	/* .bFirstInterface =	DYNAMIC, */
+	.bInterfaceCount =	2,	/* control + data */
+	.bFunctionClass =	USB_CLASS_COMM,
+	.bFunctionSubClass =	USB_CDC_SUBCLASS_ETHERNET,
+	.bFunctionProtocol =	USB_CDC_PROTO_NONE,
+	/* .iFunction =		DYNAMIC */
+};
+
+
 static struct usb_interface_descriptor ecm_control_intf = {
 	.bLength =		sizeof ecm_control_intf,
 	.bDescriptorType =	USB_DT_INTERFACE,
@@ -199,6 +213,7 @@
 
 static struct usb_descriptor_header *ecm_fs_function[] = {
 	/* CDC ECM control descriptors */
+	(struct usb_descriptor_header *) &ecm_iad_descriptor,
 	(struct usb_descriptor_header *) &ecm_control_intf,
 	(struct usb_descriptor_header *) &ecm_header_desc,
 	(struct usb_descriptor_header *) &ecm_union_desc,
@@ -247,6 +262,7 @@
 
 static struct usb_descriptor_header *ecm_hs_function[] = {
 	/* CDC ECM control descriptors */
+	(struct usb_descriptor_header *) &ecm_iad_descriptor,
 	(struct usb_descriptor_header *) &ecm_control_intf,
 	(struct usb_descriptor_header *) &ecm_header_desc,
 	(struct usb_descriptor_header *) &ecm_union_desc,
@@ -339,6 +355,7 @@
 	[0].s = "CDC Ethernet Control Model (ECM)",
 	[1].s = NULL /* DYNAMIC */,
 	[2].s = "CDC Ethernet Data",
+	[3].s = "CDC ECM",
 	{  } /* end of list */
 };
 
@@ -674,6 +691,7 @@
 	if (status < 0)
 		goto fail;
 	ecm->ctrl_id = status;
+	ecm_iad_descriptor.bFirstInterface = status;
 
 	ecm_control_intf.bInterfaceNumber = status;
 	ecm_union_desc.bMasterInterface0 = status;
@@ -864,6 +882,13 @@
 			return status;
 		ecm_string_defs[1].id = status;
 		ecm_desc.iMACAddress = status;
+
+		/* IAD label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		ecm_string_defs[3].id = status;
+		ecm_iad_descriptor.iFunction = status;
 	}
 
 	/* allocate and initialize one new instance */
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index f63dc6c..7f445ec 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -2,7 +2,7 @@
  * f_fs.c -- user mode file system API for USB composite function controllers
  *
  * Copyright (C) 2010 Samsung Electronics
- * Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
+ * Author: Michal Nazarewicz <mina86@mina86.com>
  *
  * Based on inode.c (GadgetFS) which was:
  * Copyright (C) 2003-2004 David Brownell
@@ -1258,9 +1258,7 @@
 	if (unlikely(atomic_dec_and_test(&ffs->ref))) {
 		pr_info("%s(): freeing\n", __func__);
 		ffs_data_clear(ffs);
-		BUG_ON(mutex_is_locked(&ffs->mutex) ||
-		       spin_is_locked(&ffs->ev.waitq.lock) ||
-		       waitqueue_active(&ffs->ev.waitq) ||
+		BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
 		       waitqueue_active(&ffs->ep0req_completion.wait));
 		kfree(ffs);
 	}
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index ee8ceec..a371e96 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2003-2008 Alan Stern
  * Copyright (C) 2009 Samsung Electronics
- *                    Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
+ *                    Author: Michal Nazarewicz <mina86@mina86.com>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -304,7 +304,6 @@
 
 static const char fsg_string_interface[] = "Mass Storage";
 
-#define FSG_NO_INTR_EP 1
 #define FSG_NO_DEVICE_STRINGS    1
 #define FSG_NO_OTG               1
 #define FSG_NO_INTR_EP           1
@@ -620,7 +619,7 @@
 
 	switch (ctrl->bRequest) {
 
-	case USB_BULK_RESET_REQUEST:
+	case US_BULK_RESET_REQUEST:
 		if (ctrl->bRequestType !=
 		    (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE))
 			break;
@@ -636,7 +635,7 @@
 		raise_exception(fsg->common, FSG_STATE_RESET);
 		return DELAYED_STATUS;
 
-	case USB_BULK_GET_MAX_LUN_REQUEST:
+	case US_BULK_GET_MAX_LUN:
 		if (ctrl->bRequestType !=
 		    (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE))
 			break;
@@ -1742,7 +1741,7 @@
 	struct fsg_buffhd	*bh;
 	struct bulk_cs_wrap	*csw;
 	int			rc;
-	u8			status = USB_STATUS_PASS;
+	u8			status = US_BULK_STAT_OK;
 	u32			sd, sdinfo = 0;
 
 	/* Wait for the next buffer to become available */
@@ -1763,11 +1762,11 @@
 
 	if (common->phase_error) {
 		DBG(common, "sending phase-error status\n");
-		status = USB_STATUS_PHASE_ERROR;
+		status = US_BULK_STAT_PHASE;
 		sd = SS_INVALID_COMMAND;
 	} else if (sd != SS_NO_SENSE) {
 		DBG(common, "sending command-failure status\n");
-		status = USB_STATUS_FAIL;
+		status = US_BULK_STAT_FAIL;
 		VDBG(common, "  sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
 				"  info x%x\n",
 				SK(sd), ASC(sd), ASCQ(sd), sdinfo);
@@ -1776,12 +1775,12 @@
 	/* Store and send the Bulk-only CSW */
 	csw = (void *)bh->buf;
 
-	csw->Signature = cpu_to_le32(USB_BULK_CS_SIG);
+	csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
 	csw->Tag = common->tag;
 	csw->Residue = cpu_to_le32(common->residue);
 	csw->Status = status;
 
-	bh->inreq->length = USB_BULK_CS_WRAP_LEN;
+	bh->inreq->length = US_BULK_CS_WRAP_LEN;
 	bh->inreq->zero = 0;
 	if (!start_in_transfer(common, bh))
 		/* Don't know what to do if common->fsg is NULL */
@@ -2221,7 +2220,7 @@
 static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
 {
 	struct usb_request	*req = bh->outreq;
-	struct fsg_bulk_cb_wrap	*cbw = req->buf;
+	struct bulk_cb_wrap	*cbw = req->buf;
 	struct fsg_common	*common = fsg->common;
 
 	/* Was this a real packet?  Should it be ignored? */
@@ -2229,9 +2228,9 @@
 		return -EINVAL;
 
 	/* Is the CBW valid? */
-	if (req->actual != USB_BULK_CB_WRAP_LEN ||
+	if (req->actual != US_BULK_CB_WRAP_LEN ||
 			cbw->Signature != cpu_to_le32(
-				USB_BULK_CB_SIG)) {
+				US_BULK_CB_SIGN)) {
 		DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
 				req->actual,
 				le32_to_cpu(cbw->Signature));
@@ -2253,7 +2252,7 @@
 	}
 
 	/* Is the CBW meaningful? */
-	if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG ||
+	if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
 			cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
 		DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
 				"cmdlen %u\n",
@@ -2273,7 +2272,7 @@
 	/* Save the command for later */
 	common->cmnd_size = cbw->Length;
 	memcpy(common->cmnd, cbw->CDB, common->cmnd_size);
-	if (cbw->Flags & USB_BULK_IN_FLAG)
+	if (cbw->Flags & US_BULK_FLAG_IN)
 		common->data_dir = DATA_DIR_TO_HOST;
 	else
 		common->data_dir = DATA_DIR_FROM_HOST;
@@ -2303,7 +2302,7 @@
 	}
 
 	/* Queue a request to read a Bulk-only CBW */
-	set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN);
+	set_bulk_out_req_length(common, bh, US_BULK_CB_WRAP_LEN);
 	if (!start_out_transfer(common, bh))
 		/* Don't know what to do if common->fsg is NULL */
 		return -EIO;
diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c
index 3797b3d..2f7e8f2 100644
--- a/drivers/usb/gadget/f_midi.c
+++ b/drivers/usb/gadget/f_midi.c
@@ -780,7 +780,7 @@
 	midi->out_ep->driver_data = cdev;	/* claim */
 
 	/* allocate temporary function list */
-	midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(midi_function),
+	midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(*midi_function),
 				GFP_KERNEL);
 	if (!midi_function) {
 		status = -ENOMEM;
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 704d1d9..7b1cf18 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -5,7 +5,7 @@
  * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
  * Copyright (C) 2008 Nokia Corporation
  * Copyright (C) 2009 Samsung Electronics
- *                    Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
+ *                    Author: Michal Nazarewicz (mina86@mina86.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
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index cf33a8d..07197d6 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -99,6 +99,34 @@
 	NULL,
 };
 
+static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc __initdata = {
+	.bLength =              sizeof gser_ss_bulk_comp_desc,
+	.bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
+};
+
+static struct usb_descriptor_header *gser_ss_function[] __initdata = {
+	(struct usb_descriptor_header *) &gser_interface_desc,
+	(struct usb_descriptor_header *) &gser_ss_in_desc,
+	(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
+	(struct usb_descriptor_header *) &gser_ss_out_desc,
+	(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
+	NULL,
+};
+
 /* string descriptors: */
 
 static struct usb_string gser_string_defs[] = {
@@ -201,9 +229,21 @@
 		/* copy descriptors, and track endpoint copies */
 		f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
 	}
+	if (gadget_is_superspeed(c->cdev->gadget)) {
+		gser_ss_in_desc.bEndpointAddress =
+			gser_fs_in_desc.bEndpointAddress;
+		gser_ss_out_desc.bEndpointAddress =
+			gser_fs_out_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->ss_descriptors = usb_copy_descriptors(gser_ss_function);
+		if (!f->ss_descriptors)
+			goto fail;
+	}
 
 	DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
 			gser->port_num,
+			gadget_is_superspeed(c->cdev->gadget) ? "super" :
 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
 			gser->port.in->name, gser->port.out->name);
 	return 0;
@@ -225,6 +265,8 @@
 {
 	if (gadget_is_dualspeed(c->cdev->gadget))
 		usb_free_descriptors(f->hs_descriptors);
+	if (gadget_is_superspeed(c->cdev->gadget))
+		usb_free_descriptors(f->ss_descriptors);
 	usb_free_descriptors(f->descriptors);
 	kfree(func_to_gser(f));
 }
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
index c154064..21ab474 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/f_subset.c
@@ -74,7 +74,7 @@
 
 /* interface descriptor: */
 
-static struct usb_interface_descriptor subset_data_intf __initdata = {
+static struct usb_interface_descriptor subset_data_intf = {
 	.bLength =		sizeof subset_data_intf,
 	.bDescriptorType =	USB_DT_INTERFACE,
 
@@ -87,7 +87,7 @@
 	/* .iInterface = DYNAMIC */
 };
 
-static struct usb_cdc_header_desc mdlm_header_desc __initdata = {
+static struct usb_cdc_header_desc mdlm_header_desc = {
 	.bLength =		sizeof mdlm_header_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
@@ -95,7 +95,7 @@
 	.bcdCDC =		cpu_to_le16(0x0110),
 };
 
-static struct usb_cdc_mdlm_desc mdlm_desc __initdata = {
+static struct usb_cdc_mdlm_desc mdlm_desc = {
 	.bLength =		sizeof mdlm_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_MDLM_TYPE,
@@ -111,7 +111,7 @@
  * can't really use its struct.  All we do here is say that we're using
  * the submode of "SAFE" which directly matches the CDC Subset.
  */
-static u8 mdlm_detail_desc[] __initdata = {
+static u8 mdlm_detail_desc[] = {
 	6,
 	USB_DT_CS_INTERFACE,
 	USB_CDC_MDLM_DETAIL_TYPE,
@@ -121,7 +121,7 @@
 	0,	/* network data capabilities ("raw" encapsulation) */
 };
 
-static struct usb_cdc_ether_desc ether_desc __initdata = {
+static struct usb_cdc_ether_desc ether_desc = {
 	.bLength =		sizeof ether_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_ETHERNET_TYPE,
@@ -136,7 +136,7 @@
 
 /* full speed support: */
 
-static struct usb_endpoint_descriptor fs_subset_in_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -144,7 +144,7 @@
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor fs_subset_out_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -152,7 +152,7 @@
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_descriptor_header *fs_eth_function[] __initdata = {
+static struct usb_descriptor_header *fs_eth_function[] = {
 	(struct usb_descriptor_header *) &subset_data_intf,
 	(struct usb_descriptor_header *) &mdlm_header_desc,
 	(struct usb_descriptor_header *) &mdlm_desc,
@@ -165,7 +165,7 @@
 
 /* high speed support: */
 
-static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -173,7 +173,7 @@
 	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -181,7 +181,7 @@
 	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
-static struct usb_descriptor_header *hs_eth_function[] __initdata = {
+static struct usb_descriptor_header *hs_eth_function[] = {
 	(struct usb_descriptor_header *) &subset_data_intf,
 	(struct usb_descriptor_header *) &mdlm_header_desc,
 	(struct usb_descriptor_header *) &mdlm_desc,
@@ -194,7 +194,7 @@
 
 /* super speed support: */
 
-static struct usb_endpoint_descriptor ss_subset_in_desc __initdata = {
+static struct usb_endpoint_descriptor ss_subset_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -202,7 +202,7 @@
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 
-static struct usb_endpoint_descriptor ss_subset_out_desc __initdata = {
+static struct usb_endpoint_descriptor ss_subset_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -210,7 +210,7 @@
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 
-static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc __initdata = {
+static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc = {
 	.bLength =		sizeof ss_subset_bulk_comp_desc,
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 
@@ -219,7 +219,7 @@
 	/* .bmAttributes =	0, */
 };
 
-static struct usb_descriptor_header *ss_eth_function[] __initdata = {
+static struct usb_descriptor_header *ss_eth_function[] = {
 	(struct usb_descriptor_header *) &subset_data_intf,
 	(struct usb_descriptor_header *) &mdlm_header_desc,
 	(struct usb_descriptor_header *) &mdlm_desc,
@@ -290,7 +290,7 @@
 
 /* serial function driver setup/binding */
 
-static int __init
+static int
 geth_bind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct usb_composite_dev *cdev = c->cdev;
@@ -404,7 +404,7 @@
  * Caller must have called @gether_setup().  Caller is also responsible
  * for calling @gether_cleanup() before module unload.
  */
-int __init geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 {
 	struct f_gether	*geth;
 	int		status;
diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_uac1.c
similarity index 97%
rename from drivers/usb/gadget/f_audio.c
rename to drivers/usb/gadget/f_uac1.c
index ec7ffcd..1a5dcd5 100644
--- a/drivers/usb/gadget/f_audio.c
+++ b/drivers/usb/gadget/f_uac1.c
@@ -14,7 +14,7 @@
 #include <linux/device.h>
 #include <linux/atomic.h>
 
-#include "u_audio.h"
+#include "u_uac1.h"
 
 #define OUT_EP_MAX_PACKET_SIZE	200
 static int req_buf_size = OUT_EP_MAX_PACKET_SIZE;
@@ -216,29 +216,6 @@
 	NULL,
 };
 
-/* string IDs are assigned dynamically */
-
-#define STRING_MANUFACTURER_IDX		0
-#define STRING_PRODUCT_IDX		1
-
-static char manufacturer[50];
-
-static struct usb_string strings_dev[] = {
-	[STRING_MANUFACTURER_IDX].s = manufacturer,
-	[STRING_PRODUCT_IDX].s = DRIVER_DESC,
-	{  } /* end of list */
-};
-
-static struct usb_gadget_strings stringtab_dev = {
-	.language	= 0x0409,	/* en-us */
-	.strings	= strings_dev,
-};
-
-static struct usb_gadget_strings *audio_strings[] = {
-	&stringtab_dev,
-	NULL,
-};
-
 /*
  * This function is an ALSA sound card following USB Audio Class Spec 1.0.
  */
diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c
new file mode 100644
index 0000000..e7cc4de
--- /dev/null
+++ b/drivers/usb/gadget/f_uac2.c
@@ -0,0 +1,1449 @@
+/*
+ * f_uac2.c -- USB Audio Class 2.0 Function
+ *
+ * Copyright (C) 2011
+ *    Yadwinder Singh (yadi.brar01@gmail.com)
+ *    Jaswinder Singh (jaswinder.singh@linaro.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/usb/audio.h>
+#include <linux/usb/audio-v2.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+/* Playback(USB-IN) Default Stereo - Fl/Fr */
+static int p_chmask = 0x3;
+module_param(p_chmask, uint, S_IRUGO);
+MODULE_PARM_DESC(p_chmask, "Playback Channel Mask");
+
+/* Playback Default 48 KHz */
+static int p_srate = 48000;
+module_param(p_srate, uint, S_IRUGO);
+MODULE_PARM_DESC(p_srate, "Playback Sampling Rate");
+
+/* Playback Default 16bits/sample */
+static int p_ssize = 2;
+module_param(p_ssize, uint, S_IRUGO);
+MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)");
+
+/* Capture(USB-OUT) Default Stereo - Fl/Fr */
+static int c_chmask = 0x3;
+module_param(c_chmask, uint, S_IRUGO);
+MODULE_PARM_DESC(c_chmask, "Capture Channel Mask");
+
+/* Capture Default 64 KHz */
+static int c_srate = 64000;
+module_param(c_srate, uint, S_IRUGO);
+MODULE_PARM_DESC(c_srate, "Capture Sampling Rate");
+
+/* Capture Default 16bits/sample */
+static int c_ssize = 2;
+module_param(c_ssize, uint, S_IRUGO);
+MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
+
+#define DMA_ADDR_INVALID	(~(dma_addr_t)0)
+
+#define ALT_SET(x, a)	do {(x) &= ~0xff; (x) |= (a); } while (0)
+#define ALT_GET(x)	((x) & 0xff)
+#define INTF_SET(x, i)	do {(x) &= 0xff; (x) |= ((i) << 8); } while (0)
+#define INTF_GET(x)	((x >> 8) & 0xff)
+
+/* Keep everyone on toes */
+#define USB_XFERS	2
+
+/*
+ * The driver implements a simple UAC_2 topology.
+ * USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture
+ * ALSA_Playback -> IT_2 -> OT_4 -> USB-IN
+ * Capture and Playback sampling rates are independently
+ *  controlled by two clock sources :
+ *    CLK_5 := c_srate, and CLK_6 := p_srate
+ */
+#define USB_OUT_IT_ID	1
+#define IO_IN_IT_ID	2
+#define IO_OUT_OT_ID	3
+#define USB_IN_OT_ID	4
+#define USB_OUT_CLK_ID	5
+#define USB_IN_CLK_ID	6
+
+#define CONTROL_ABSENT	0
+#define CONTROL_RDONLY	1
+#define CONTROL_RDWR	3
+
+#define CLK_FREQ_CTRL	0
+#define CLK_VLD_CTRL	2
+
+#define COPY_CTRL	0
+#define CONN_CTRL	2
+#define OVRLD_CTRL	4
+#define CLSTR_CTRL	6
+#define UNFLW_CTRL	8
+#define OVFLW_CTRL	10
+
+const char *uac2_name = "snd_uac2";
+
+struct uac2_req {
+	struct uac2_rtd_params *pp; /* parent param */
+	struct usb_request *req;
+};
+
+struct uac2_rtd_params {
+	bool ep_enabled; /* if the ep is enabled */
+	/* Size of the ring buffer */
+	size_t dma_bytes;
+	unsigned char *dma_area;
+
+	struct snd_pcm_substream *ss;
+
+	/* Ring buffer */
+	ssize_t hw_ptr;
+
+	void *rbuf;
+
+	size_t period_size;
+
+	unsigned max_psize;
+	struct uac2_req ureq[USB_XFERS];
+
+	spinlock_t lock;
+};
+
+struct snd_uac2_chip {
+	struct platform_device pdev;
+	struct platform_driver pdrv;
+
+	struct uac2_rtd_params p_prm;
+	struct uac2_rtd_params c_prm;
+
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+};
+
+#define BUFF_SIZE_MAX	(PAGE_SIZE * 16)
+#define PRD_SIZE_MAX	PAGE_SIZE
+#define MIN_PERIODS	4
+
+static struct snd_pcm_hardware uac2_pcm_hardware = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER
+		 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
+		 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+	.rates = SNDRV_PCM_RATE_CONTINUOUS,
+	.periods_max = BUFF_SIZE_MAX / PRD_SIZE_MAX,
+	.buffer_bytes_max = BUFF_SIZE_MAX,
+	.period_bytes_max = PRD_SIZE_MAX,
+	.periods_min = MIN_PERIODS,
+};
+
+struct audio_dev {
+	/* Currently active {Interface[15:8] | AltSettings[7:0]} */
+	__u16 ac_alt, as_out_alt, as_in_alt;
+
+	struct usb_ep *in_ep, *out_ep;
+	struct usb_function func;
+
+	/* The ALSA Sound Card it represents on the USB-Client side */
+	struct snd_uac2_chip uac2;
+};
+
+static struct audio_dev *agdev_g;
+
+static inline
+struct audio_dev *func_to_agdev(struct usb_function *f)
+{
+	return container_of(f, struct audio_dev, func);
+}
+
+static inline
+struct audio_dev *uac2_to_agdev(struct snd_uac2_chip *u)
+{
+	return container_of(u, struct audio_dev, uac2);
+}
+
+static inline
+struct snd_uac2_chip *pdev_to_uac2(struct platform_device *p)
+{
+	return container_of(p, struct snd_uac2_chip, pdev);
+}
+
+static inline
+struct snd_uac2_chip *prm_to_uac2(struct uac2_rtd_params *r)
+{
+	struct snd_uac2_chip *uac2 = container_of(r,
+					struct snd_uac2_chip, c_prm);
+
+	if (&uac2->c_prm != r)
+		uac2 = container_of(r, struct snd_uac2_chip, p_prm);
+
+	return uac2;
+}
+
+static inline
+uint num_channels(uint chanmask)
+{
+	uint num = 0;
+
+	while (chanmask) {
+		num += (chanmask & 1);
+		chanmask >>= 1;
+	}
+
+	return num;
+}
+
+static void
+agdev_iso_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	unsigned pending;
+	unsigned long flags;
+	bool update_alsa = false;
+	unsigned char *src, *dst;
+	int status = req->status;
+	struct uac2_req *ur = req->context;
+	struct snd_pcm_substream *substream;
+	struct uac2_rtd_params *prm = ur->pp;
+	struct snd_uac2_chip *uac2 = prm_to_uac2(prm);
+
+	/* i/f shutting down */
+	if (!prm->ep_enabled)
+		return;
+
+	/*
+	 * We can't really do much about bad xfers.
+	 * Afterall, the ISOCH xfers could fail legitimately.
+	 */
+	if (status)
+		pr_debug("%s: iso_complete status(%d) %d/%d\n",
+			__func__, status, req->actual, req->length);
+
+	substream = prm->ss;
+
+	/* Do nothing if ALSA isn't active */
+	if (!substream)
+		goto exit;
+
+	spin_lock_irqsave(&prm->lock, flags);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		src = prm->dma_area + prm->hw_ptr;
+		req->actual = req->length;
+		dst = req->buf;
+	} else {
+		dst = prm->dma_area + prm->hw_ptr;
+		src = req->buf;
+	}
+
+	pending = prm->hw_ptr % prm->period_size;
+	pending += req->actual;
+	if (pending >= prm->period_size)
+		update_alsa = true;
+
+	prm->hw_ptr = (prm->hw_ptr + req->actual) % prm->dma_bytes;
+
+	spin_unlock_irqrestore(&prm->lock, flags);
+
+	/* Pack USB load in ALSA ring buffer */
+	memcpy(dst, src, req->actual);
+exit:
+	if (usb_ep_queue(ep, req, GFP_ATOMIC))
+		dev_err(&uac2->pdev.dev, "%d Error!\n", __LINE__);
+
+	if (update_alsa)
+		snd_pcm_period_elapsed(substream);
+
+	return;
+}
+
+static int
+uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
+	struct audio_dev *agdev = uac2_to_agdev(uac2);
+	struct uac2_rtd_params *prm;
+	unsigned long flags;
+	struct usb_ep *ep;
+	int err = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		ep = agdev->in_ep;
+		prm = &uac2->p_prm;
+	} else {
+		ep = agdev->out_ep;
+		prm = &uac2->c_prm;
+	}
+
+	spin_lock_irqsave(&prm->lock, flags);
+
+	/* Reset */
+	prm->hw_ptr = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		prm->ss = substream;
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		prm->ss = NULL;
+		break;
+	default:
+		err = -EINVAL;
+	}
+
+	spin_unlock_irqrestore(&prm->lock, flags);
+
+	/* Clear buffer after Play stops */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss)
+		memset(prm->rbuf, 0, prm->max_psize * USB_XFERS);
+
+	return err;
+}
+
+static snd_pcm_uframes_t uac2_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
+	struct uac2_rtd_params *prm;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		prm = &uac2->p_prm;
+	else
+		prm = &uac2->c_prm;
+
+	return bytes_to_frames(substream->runtime, prm->hw_ptr);
+}
+
+static int uac2_pcm_hw_params(struct snd_pcm_substream *substream,
+			       struct snd_pcm_hw_params *hw_params)
+{
+	struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
+	struct uac2_rtd_params *prm;
+	int err;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		prm = &uac2->p_prm;
+	else
+		prm = &uac2->c_prm;
+
+	err = snd_pcm_lib_malloc_pages(substream,
+					params_buffer_bytes(hw_params));
+	if (err >= 0) {
+		prm->dma_bytes = substream->runtime->dma_bytes;
+		prm->dma_area = substream->runtime->dma_area;
+		prm->period_size = params_period_bytes(hw_params);
+	}
+
+	return err;
+}
+
+static int uac2_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
+	struct uac2_rtd_params *prm;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		prm = &uac2->p_prm;
+	else
+		prm = &uac2->c_prm;
+
+	prm->dma_area = NULL;
+	prm->dma_bytes = 0;
+	prm->period_size = 0;
+
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static int uac2_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	runtime->hw = uac2_pcm_hardware;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		spin_lock_init(&uac2->p_prm.lock);
+		runtime->hw.rate_min = p_srate;
+		runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! p_ssize ! */
+		runtime->hw.channels_min = num_channels(p_chmask);
+		runtime->hw.period_bytes_min = 2 * uac2->p_prm.max_psize
+						/ runtime->hw.periods_min;
+	} else {
+		spin_lock_init(&uac2->c_prm.lock);
+		runtime->hw.rate_min = c_srate;
+		runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! c_ssize ! */
+		runtime->hw.channels_min = num_channels(c_chmask);
+		runtime->hw.period_bytes_min = 2 * uac2->c_prm.max_psize
+						/ runtime->hw.periods_min;
+	}
+
+	runtime->hw.rate_max = runtime->hw.rate_min;
+	runtime->hw.channels_max = runtime->hw.channels_min;
+
+	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+
+	return 0;
+}
+
+/* ALSA cries without these function pointers */
+static int uac2_pcm_null(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+static struct snd_pcm_ops uac2_pcm_ops = {
+	.open = uac2_pcm_open,
+	.close = uac2_pcm_null,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = uac2_pcm_hw_params,
+	.hw_free = uac2_pcm_hw_free,
+	.trigger = uac2_pcm_trigger,
+	.pointer = uac2_pcm_pointer,
+	.prepare = uac2_pcm_null,
+};
+
+static int __devinit snd_uac2_probe(struct platform_device *pdev)
+{
+	struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev);
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+	int err;
+
+	/* Choose any slot, with no id */
+	err = snd_card_create(-1, NULL, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
+
+	uac2->card = card;
+
+	/*
+	 * Create first PCM device
+	 * Create a substream only for non-zero channel streams
+	 */
+	err = snd_pcm_new(uac2->card, "UAC2 PCM", 0,
+			       p_chmask ? 1 : 0, c_chmask ? 1 : 0, &pcm);
+	if (err < 0)
+		goto snd_fail;
+
+	strcpy(pcm->name, "UAC2 PCM");
+	pcm->private_data = uac2;
+
+	uac2->pcm = pcm;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac2_pcm_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac2_pcm_ops);
+
+	strcpy(card->driver, "UAC2_Gadget");
+	strcpy(card->shortname, "UAC2_Gadget");
+	sprintf(card->longname, "UAC2_Gadget %i", pdev->id);
+
+	snd_card_set_dev(card, &pdev->dev);
+
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+		snd_dma_continuous_data(GFP_KERNEL), 0, BUFF_SIZE_MAX);
+
+	err = snd_card_register(card);
+	if (!err) {
+		platform_set_drvdata(pdev, card);
+		return 0;
+	}
+
+snd_fail:
+	snd_card_free(card);
+
+	uac2->pcm = NULL;
+	uac2->card = NULL;
+
+	return err;
+}
+
+static int __devexit snd_uac2_remove(struct platform_device *pdev)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (card)
+		return snd_card_free(card);
+
+	return 0;
+}
+
+static int alsa_uac2_init(struct audio_dev *agdev)
+{
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	int err;
+
+	uac2->pdrv.probe = snd_uac2_probe;
+	uac2->pdrv.remove = snd_uac2_remove;
+	uac2->pdrv.driver.name = uac2_name;
+
+	uac2->pdev.id = 0;
+	uac2->pdev.name = uac2_name;
+
+	/* Register snd_uac2 driver */
+	err = platform_driver_register(&uac2->pdrv);
+	if (err)
+		return err;
+
+	/* Register snd_uac2 device */
+	err = platform_device_register(&uac2->pdev);
+	if (err)
+		platform_driver_unregister(&uac2->pdrv);
+
+	return err;
+}
+
+static void alsa_uac2_exit(struct audio_dev *agdev)
+{
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+
+	platform_driver_unregister(&uac2->pdrv);
+	platform_device_unregister(&uac2->pdev);
+}
+
+
+/* --------- USB Function Interface ------------- */
+
+enum {
+	STR_ASSOC,
+	STR_IF_CTRL,
+	STR_CLKSRC_IN,
+	STR_CLKSRC_OUT,
+	STR_USB_IT,
+	STR_IO_IT,
+	STR_USB_OT,
+	STR_IO_OT,
+	STR_AS_OUT_ALT0,
+	STR_AS_OUT_ALT1,
+	STR_AS_IN_ALT0,
+	STR_AS_IN_ALT1,
+};
+
+static const char ifassoc[] = "Source/Sink";
+static const char ifctrl[] = "Topology Control";
+static char clksrc_in[8];
+static char clksrc_out[8];
+static const char usb_it[] = "USBH Out";
+static const char io_it[] = "USBD Out";
+static const char usb_ot[] = "USBH In";
+static const char io_ot[] = "USBD In";
+static const char out_alt0[] = "Playback Inactive";
+static const char out_alt1[] = "Playback Active";
+static const char in_alt0[] = "Capture Inactive";
+static const char in_alt1[] = "Capture Active";
+
+static struct usb_string strings_fn[] = {
+	[STR_ASSOC].s = ifassoc,
+	[STR_IF_CTRL].s = ifctrl,
+	[STR_CLKSRC_IN].s = clksrc_in,
+	[STR_CLKSRC_OUT].s = clksrc_out,
+	[STR_USB_IT].s = usb_it,
+	[STR_IO_IT].s = io_it,
+	[STR_USB_OT].s = usb_ot,
+	[STR_IO_OT].s = io_ot,
+	[STR_AS_OUT_ALT0].s = out_alt0,
+	[STR_AS_OUT_ALT1].s = out_alt1,
+	[STR_AS_IN_ALT0].s = in_alt0,
+	[STR_AS_IN_ALT1].s = in_alt1,
+	{ },
+};
+
+static struct usb_gadget_strings str_fn = {
+	.language = 0x0409,	/* en-us */
+	.strings = strings_fn,
+};
+
+static struct usb_gadget_strings *fn_strings[] = {
+	&str_fn,
+	NULL,
+};
+
+static struct usb_qualifier_descriptor devqual_desc = {
+	.bLength = sizeof devqual_desc,
+	.bDescriptorType = USB_DT_DEVICE_QUALIFIER,
+
+	.bcdUSB = cpu_to_le16(0x200),
+	.bDeviceClass = USB_CLASS_MISC,
+	.bDeviceSubClass = 0x02,
+	.bDeviceProtocol = 0x01,
+	.bNumConfigurations = 1,
+	.bRESERVED = 0,
+};
+
+static struct usb_interface_assoc_descriptor iad_desc = {
+	.bLength = sizeof iad_desc,
+	.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+
+	.bFirstInterface = 0,
+	.bInterfaceCount = 3,
+	.bFunctionClass = USB_CLASS_AUDIO,
+	.bFunctionSubClass = UAC2_FUNCTION_SUBCLASS_UNDEFINED,
+	.bFunctionProtocol = UAC_VERSION_2,
+};
+
+/* Audio Control Interface */
+static struct usb_interface_descriptor std_ac_if_desc = {
+	.bLength = sizeof std_ac_if_desc,
+	.bDescriptorType = USB_DT_INTERFACE,
+
+	.bAlternateSetting = 0,
+	.bNumEndpoints = 0,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
+	.bInterfaceProtocol = UAC_VERSION_2,
+};
+
+/* Clock source for IN traffic */
+struct uac_clock_source_descriptor in_clk_src_desc = {
+	.bLength = sizeof in_clk_src_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC2_CLOCK_SOURCE,
+	.bClockID = USB_IN_CLK_ID,
+	.bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED,
+	.bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL),
+	.bAssocTerminal = 0,
+};
+
+/* Clock source for OUT traffic */
+struct uac_clock_source_descriptor out_clk_src_desc = {
+	.bLength = sizeof out_clk_src_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC2_CLOCK_SOURCE,
+	.bClockID = USB_OUT_CLK_ID,
+	.bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED,
+	.bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL),
+	.bAssocTerminal = 0,
+};
+
+/* Input Terminal for USB_OUT */
+struct uac2_input_terminal_descriptor usb_out_it_desc = {
+	.bLength = sizeof usb_out_it_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_INPUT_TERMINAL,
+	.bTerminalID = USB_OUT_IT_ID,
+	.wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING),
+	.bAssocTerminal = 0,
+	.bCSourceID = USB_OUT_CLK_ID,
+	.iChannelNames = 0,
+	.bmControls = (CONTROL_RDWR << COPY_CTRL),
+};
+
+/* Input Terminal for I/O-In */
+struct uac2_input_terminal_descriptor io_in_it_desc = {
+	.bLength = sizeof io_in_it_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_INPUT_TERMINAL,
+	.bTerminalID = IO_IN_IT_ID,
+	.wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_UNDEFINED),
+	.bAssocTerminal = 0,
+	.bCSourceID = USB_IN_CLK_ID,
+	.iChannelNames = 0,
+	.bmControls = (CONTROL_RDWR << COPY_CTRL),
+};
+
+/* Ouput Terminal for USB_IN */
+struct uac2_output_terminal_descriptor usb_in_ot_desc = {
+	.bLength = sizeof usb_in_ot_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
+	.bTerminalID = USB_IN_OT_ID,
+	.wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING),
+	.bAssocTerminal = 0,
+	.bSourceID = IO_IN_IT_ID,
+	.bCSourceID = USB_IN_CLK_ID,
+	.bmControls = (CONTROL_RDWR << COPY_CTRL),
+};
+
+/* Ouput Terminal for I/O-Out */
+struct uac2_output_terminal_descriptor io_out_ot_desc = {
+	.bLength = sizeof io_out_ot_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
+	.bTerminalID = IO_OUT_OT_ID,
+	.wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_UNDEFINED),
+	.bAssocTerminal = 0,
+	.bSourceID = USB_OUT_IT_ID,
+	.bCSourceID = USB_OUT_CLK_ID,
+	.bmControls = (CONTROL_RDWR << COPY_CTRL),
+};
+
+struct uac2_ac_header_descriptor ac_hdr_desc = {
+	.bLength = sizeof ac_hdr_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_MS_HEADER,
+	.bcdADC = cpu_to_le16(0x200),
+	.bCategory = UAC2_FUNCTION_IO_BOX,
+	.wTotalLength = sizeof in_clk_src_desc + sizeof out_clk_src_desc
+			 + sizeof usb_out_it_desc + sizeof io_in_it_desc
+			+ sizeof usb_in_ot_desc + sizeof io_out_ot_desc,
+	.bmControls = 0,
+};
+
+/* Audio Streaming OUT Interface - Alt0 */
+static struct usb_interface_descriptor std_as_out_if0_desc = {
+	.bLength = sizeof std_as_out_if0_desc,
+	.bDescriptorType = USB_DT_INTERFACE,
+
+	.bAlternateSetting = 0,
+	.bNumEndpoints = 0,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+	.bInterfaceProtocol = UAC_VERSION_2,
+};
+
+/* Audio Streaming OUT Interface - Alt1 */
+static struct usb_interface_descriptor std_as_out_if1_desc = {
+	.bLength = sizeof std_as_out_if1_desc,
+	.bDescriptorType = USB_DT_INTERFACE,
+
+	.bAlternateSetting = 1,
+	.bNumEndpoints = 1,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+	.bInterfaceProtocol = UAC_VERSION_2,
+};
+
+/* Audio Stream OUT Intface Desc */
+struct uac2_as_header_descriptor as_out_hdr_desc = {
+	.bLength = sizeof as_out_hdr_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_AS_GENERAL,
+	.bTerminalLink = USB_OUT_IT_ID,
+	.bmControls = 0,
+	.bFormatType = UAC_FORMAT_TYPE_I,
+	.bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM),
+	.iChannelNames = 0,
+};
+
+/* Audio USB_OUT Format */
+struct uac2_format_type_i_descriptor as_out_fmt1_desc = {
+	.bLength = sizeof as_out_fmt1_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+	.bDescriptorSubtype = UAC_FORMAT_TYPE,
+	.bFormatType = UAC_FORMAT_TYPE_I,
+};
+
+/* STD AS ISO OUT Endpoint */
+struct usb_endpoint_descriptor fs_epout_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	.bEndpointAddress = USB_DIR_OUT,
+	.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+	.bInterval = 1,
+};
+
+struct usb_endpoint_descriptor hs_epout_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+	.bInterval = 4,
+};
+
+/* CS AS ISO OUT Endpoint */
+static struct uac2_iso_endpoint_descriptor as_iso_out_desc = {
+	.bLength = sizeof as_iso_out_desc,
+	.bDescriptorType = USB_DT_CS_ENDPOINT,
+
+	.bDescriptorSubtype = UAC_EP_GENERAL,
+	.bmAttributes = 0,
+	.bmControls = 0,
+	.bLockDelayUnits = 0,
+	.wLockDelay = 0,
+};
+
+/* Audio Streaming IN Interface - Alt0 */
+static struct usb_interface_descriptor std_as_in_if0_desc = {
+	.bLength = sizeof std_as_in_if0_desc,
+	.bDescriptorType = USB_DT_INTERFACE,
+
+	.bAlternateSetting = 0,
+	.bNumEndpoints = 0,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+	.bInterfaceProtocol = UAC_VERSION_2,
+};
+
+/* Audio Streaming IN Interface - Alt1 */
+static struct usb_interface_descriptor std_as_in_if1_desc = {
+	.bLength = sizeof std_as_in_if1_desc,
+	.bDescriptorType = USB_DT_INTERFACE,
+
+	.bAlternateSetting = 1,
+	.bNumEndpoints = 1,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+	.bInterfaceProtocol = UAC_VERSION_2,
+};
+
+/* Audio Stream IN Intface Desc */
+struct uac2_as_header_descriptor as_in_hdr_desc = {
+	.bLength = sizeof as_in_hdr_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+
+	.bDescriptorSubtype = UAC_AS_GENERAL,
+	.bTerminalLink = USB_IN_OT_ID,
+	.bmControls = 0,
+	.bFormatType = UAC_FORMAT_TYPE_I,
+	.bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM),
+	.iChannelNames = 0,
+};
+
+/* Audio USB_IN Format */
+struct uac2_format_type_i_descriptor as_in_fmt1_desc = {
+	.bLength = sizeof as_in_fmt1_desc,
+	.bDescriptorType = USB_DT_CS_INTERFACE,
+	.bDescriptorSubtype = UAC_FORMAT_TYPE,
+	.bFormatType = UAC_FORMAT_TYPE_I,
+};
+
+/* STD AS ISO IN Endpoint */
+struct usb_endpoint_descriptor fs_epin_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	.bEndpointAddress = USB_DIR_IN,
+	.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+	.bInterval = 1,
+};
+
+struct usb_endpoint_descriptor hs_epin_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+	.bInterval = 4,
+};
+
+/* CS AS ISO IN Endpoint */
+static struct uac2_iso_endpoint_descriptor as_iso_in_desc = {
+	.bLength = sizeof as_iso_in_desc,
+	.bDescriptorType = USB_DT_CS_ENDPOINT,
+
+	.bDescriptorSubtype = UAC_EP_GENERAL,
+	.bmAttributes = 0,
+	.bmControls = 0,
+	.bLockDelayUnits = 0,
+	.wLockDelay = 0,
+};
+
+static struct usb_descriptor_header *fs_audio_desc[] = {
+	(struct usb_descriptor_header *)&iad_desc,
+	(struct usb_descriptor_header *)&std_ac_if_desc,
+
+	(struct usb_descriptor_header *)&ac_hdr_desc,
+	(struct usb_descriptor_header *)&in_clk_src_desc,
+	(struct usb_descriptor_header *)&out_clk_src_desc,
+	(struct usb_descriptor_header *)&usb_out_it_desc,
+	(struct usb_descriptor_header *)&io_in_it_desc,
+	(struct usb_descriptor_header *)&usb_in_ot_desc,
+	(struct usb_descriptor_header *)&io_out_ot_desc,
+
+	(struct usb_descriptor_header *)&std_as_out_if0_desc,
+	(struct usb_descriptor_header *)&std_as_out_if1_desc,
+
+	(struct usb_descriptor_header *)&as_out_hdr_desc,
+	(struct usb_descriptor_header *)&as_out_fmt1_desc,
+	(struct usb_descriptor_header *)&fs_epout_desc,
+	(struct usb_descriptor_header *)&as_iso_out_desc,
+
+	(struct usb_descriptor_header *)&std_as_in_if0_desc,
+	(struct usb_descriptor_header *)&std_as_in_if1_desc,
+
+	(struct usb_descriptor_header *)&as_in_hdr_desc,
+	(struct usb_descriptor_header *)&as_in_fmt1_desc,
+	(struct usb_descriptor_header *)&fs_epin_desc,
+	(struct usb_descriptor_header *)&as_iso_in_desc,
+	NULL,
+};
+
+static struct usb_descriptor_header *hs_audio_desc[] = {
+	(struct usb_descriptor_header *)&iad_desc,
+	(struct usb_descriptor_header *)&std_ac_if_desc,
+
+	(struct usb_descriptor_header *)&ac_hdr_desc,
+	(struct usb_descriptor_header *)&in_clk_src_desc,
+	(struct usb_descriptor_header *)&out_clk_src_desc,
+	(struct usb_descriptor_header *)&usb_out_it_desc,
+	(struct usb_descriptor_header *)&io_in_it_desc,
+	(struct usb_descriptor_header *)&usb_in_ot_desc,
+	(struct usb_descriptor_header *)&io_out_ot_desc,
+
+	(struct usb_descriptor_header *)&std_as_out_if0_desc,
+	(struct usb_descriptor_header *)&std_as_out_if1_desc,
+
+	(struct usb_descriptor_header *)&as_out_hdr_desc,
+	(struct usb_descriptor_header *)&as_out_fmt1_desc,
+	(struct usb_descriptor_header *)&hs_epout_desc,
+	(struct usb_descriptor_header *)&as_iso_out_desc,
+
+	(struct usb_descriptor_header *)&std_as_in_if0_desc,
+	(struct usb_descriptor_header *)&std_as_in_if1_desc,
+
+	(struct usb_descriptor_header *)&as_in_hdr_desc,
+	(struct usb_descriptor_header *)&as_in_fmt1_desc,
+	(struct usb_descriptor_header *)&hs_epin_desc,
+	(struct usb_descriptor_header *)&as_iso_in_desc,
+	NULL,
+};
+
+struct cntrl_cur_lay3 {
+	__u32	dCUR;
+};
+
+struct cntrl_range_lay3 {
+	__u16	wNumSubRanges;
+	__u32	dMIN;
+	__u32	dMAX;
+	__u32	dRES;
+} __packed;
+
+static inline void
+free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
+{
+	struct snd_uac2_chip *uac2 = prm_to_uac2(prm);
+	int i;
+
+	prm->ep_enabled = false;
+
+	for (i = 0; i < USB_XFERS; i++) {
+		if (prm->ureq[i].req) {
+			usb_ep_dequeue(ep, prm->ureq[i].req);
+			usb_ep_free_request(ep, prm->ureq[i].req);
+			prm->ureq[i].req = NULL;
+		}
+	}
+
+	if (usb_ep_disable(ep))
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+}
+
+static int __init
+afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
+{
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	struct usb_composite_dev *cdev = cfg->cdev;
+	struct usb_gadget *gadget = cdev->gadget;
+	struct uac2_rtd_params *prm;
+	int ret;
+
+	ret = usb_interface_id(cfg, fn);
+	if (ret < 0) {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+		return ret;
+	}
+	std_ac_if_desc.bInterfaceNumber = ret;
+	ALT_SET(agdev->ac_alt, 0);
+	INTF_SET(agdev->ac_alt, ret);
+
+	ret = usb_interface_id(cfg, fn);
+	if (ret < 0) {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+		return ret;
+	}
+	std_as_out_if0_desc.bInterfaceNumber = ret;
+	std_as_out_if1_desc.bInterfaceNumber = ret;
+	ALT_SET(agdev->as_out_alt, 0);
+	INTF_SET(agdev->as_out_alt, ret);
+
+	ret = usb_interface_id(cfg, fn);
+	if (ret < 0) {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+		return ret;
+	}
+	std_as_in_if0_desc.bInterfaceNumber = ret;
+	std_as_in_if1_desc.bInterfaceNumber = ret;
+	ALT_SET(agdev->as_in_alt, 0);
+	INTF_SET(agdev->as_in_alt, ret);
+
+	agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
+	if (!agdev->out_ep)
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+	agdev->out_ep->driver_data = agdev;
+
+	agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
+	if (!agdev->in_ep)
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+	agdev->in_ep->driver_data = agdev;
+
+	hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
+	hs_epout_desc.wMaxPacketSize = fs_epout_desc.wMaxPacketSize;
+	hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
+	hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize;
+
+	fn->descriptors = usb_copy_descriptors(fs_audio_desc);
+	if (gadget_is_dualspeed(gadget))
+		fn->hs_descriptors = usb_copy_descriptors(hs_audio_desc);
+
+	prm = &agdev->uac2.c_prm;
+	prm->max_psize = hs_epout_desc.wMaxPacketSize;
+	prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
+	if (!prm->rbuf) {
+		prm->max_psize = 0;
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+	}
+
+	prm = &agdev->uac2.p_prm;
+	prm->max_psize = hs_epin_desc.wMaxPacketSize;
+	prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
+	if (!prm->rbuf) {
+		prm->max_psize = 0;
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+	}
+
+	return alsa_uac2_init(agdev);
+}
+
+static void
+afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)
+{
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct usb_composite_dev *cdev = cfg->cdev;
+	struct usb_gadget *gadget = cdev->gadget;
+	struct uac2_rtd_params *prm;
+
+	alsa_uac2_exit(agdev);
+
+	prm = &agdev->uac2.p_prm;
+	kfree(prm->rbuf);
+
+	prm = &agdev->uac2.c_prm;
+	kfree(prm->rbuf);
+
+	if (gadget_is_dualspeed(gadget))
+		usb_free_descriptors(fn->hs_descriptors);
+	usb_free_descriptors(fn->descriptors);
+
+	if (agdev->in_ep)
+		agdev->in_ep->driver_data = NULL;
+	if (agdev->out_ep)
+		agdev->out_ep->driver_data = NULL;
+}
+
+static int
+afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
+{
+	struct usb_composite_dev *cdev = fn->config->cdev;
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	struct usb_gadget *gadget = cdev->gadget;
+	struct usb_request *req;
+	struct usb_ep *ep;
+	struct uac2_rtd_params *prm;
+	int i;
+
+	/* No i/f has more than 2 alt settings */
+	if (alt > 1) {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	if (intf == INTF_GET(agdev->ac_alt)) {
+		/* Control I/f has only 1 AltSetting - 0 */
+		if (alt) {
+			dev_err(&uac2->pdev.dev,
+				"%s:%d Error!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+		return 0;
+	}
+
+	if (intf == INTF_GET(agdev->as_out_alt)) {
+		ep = agdev->out_ep;
+		prm = &uac2->c_prm;
+		config_ep_by_speed(gadget, fn, ep);
+		ALT_SET(agdev->as_out_alt, alt);
+	} else if (intf == INTF_GET(agdev->as_in_alt)) {
+		ep = agdev->in_ep;
+		prm = &uac2->p_prm;
+		config_ep_by_speed(gadget, fn, ep);
+		ALT_SET(agdev->as_in_alt, alt);
+	} else {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	if (alt == 0) {
+		free_ep(prm, ep);
+		return 0;
+	}
+
+	prm->ep_enabled = true;
+	usb_ep_enable(ep);
+
+	for (i = 0; i < USB_XFERS; i++) {
+		if (prm->ureq[i].req) {
+			if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
+				dev_err(&uac2->pdev.dev, "%d Error!\n",
+					__LINE__);
+			continue;
+		}
+
+		req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+		if (req == NULL) {
+			dev_err(&uac2->pdev.dev,
+				"%s:%d Error!\n", __func__, __LINE__);
+			return -EINVAL;
+		}
+
+		prm->ureq[i].req = req;
+		prm->ureq[i].pp = prm;
+
+		req->zero = 0;
+		req->dma = DMA_ADDR_INVALID;
+		req->context = &prm->ureq[i];
+		req->length = prm->max_psize;
+		req->complete =	agdev_iso_complete;
+		req->buf = prm->rbuf + i * req->length;
+
+		if (usb_ep_queue(ep, req, GFP_ATOMIC))
+			dev_err(&uac2->pdev.dev, "%d Error!\n", __LINE__);
+	}
+
+	return 0;
+}
+
+static int
+afunc_get_alt(struct usb_function *fn, unsigned intf)
+{
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+
+	if (intf == INTF_GET(agdev->ac_alt))
+		return ALT_GET(agdev->ac_alt);
+	else if (intf == INTF_GET(agdev->as_out_alt))
+		return ALT_GET(agdev->as_out_alt);
+	else if (intf == INTF_GET(agdev->as_in_alt))
+		return ALT_GET(agdev->as_in_alt);
+	else
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Invalid Interface %d!\n",
+			__func__, __LINE__, intf);
+
+	return -EINVAL;
+}
+
+static void
+afunc_disable(struct usb_function *fn)
+{
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+
+	free_ep(&uac2->p_prm, agdev->in_ep);
+	ALT_SET(agdev->as_in_alt, 0);
+
+	free_ep(&uac2->c_prm, agdev->out_ep);
+	ALT_SET(agdev->as_out_alt, 0);
+}
+
+static int
+in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+	struct usb_request *req = fn->config->cdev->req;
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	u16 w_length = le16_to_cpu(cr->wLength);
+	u16 w_index = le16_to_cpu(cr->wIndex);
+	u16 w_value = le16_to_cpu(cr->wValue);
+	u8 entity_id = (w_index >> 8) & 0xff;
+	u8 control_selector = w_value >> 8;
+	int value = -EOPNOTSUPP;
+
+	if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) {
+		struct cntrl_cur_lay3 c;
+
+		if (entity_id == USB_IN_CLK_ID)
+			c.dCUR = p_srate;
+		else if (entity_id == USB_OUT_CLK_ID)
+			c.dCUR = c_srate;
+
+		value = min_t(unsigned, w_length, sizeof c);
+		memcpy(req->buf, &c, value);
+	} else if (control_selector == UAC2_CS_CONTROL_CLOCK_VALID) {
+		*(u8 *)req->buf = 1;
+		value = min_t(unsigned, w_length, 1);
+	} else {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d control_selector=%d TODO!\n",
+			__func__, __LINE__, control_selector);
+	}
+
+	return value;
+}
+
+static int
+in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+	struct usb_request *req = fn->config->cdev->req;
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	u16 w_length = le16_to_cpu(cr->wLength);
+	u16 w_index = le16_to_cpu(cr->wIndex);
+	u16 w_value = le16_to_cpu(cr->wValue);
+	u8 entity_id = (w_index >> 8) & 0xff;
+	u8 control_selector = w_value >> 8;
+	struct cntrl_range_lay3 r;
+	int value = -EOPNOTSUPP;
+
+	if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) {
+		if (entity_id == USB_IN_CLK_ID)
+			r.dMIN = p_srate;
+		else if (entity_id == USB_OUT_CLK_ID)
+			r.dMIN = c_srate;
+		else
+			return -EOPNOTSUPP;
+
+		r.dMAX = r.dMIN;
+		r.dRES = 0;
+		r.wNumSubRanges = 1;
+
+		value = min_t(unsigned, w_length, sizeof r);
+		memcpy(req->buf, &r, value);
+	} else {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d control_selector=%d TODO!\n",
+			__func__, __LINE__, control_selector);
+	}
+
+	return value;
+}
+
+static int
+ac_rq_in(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+	if (cr->bRequest == UAC2_CS_CUR)
+		return in_rq_cur(fn, cr);
+	else if (cr->bRequest == UAC2_CS_RANGE)
+		return in_rq_range(fn, cr);
+	else
+		return -EOPNOTSUPP;
+}
+
+static int
+out_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+	u16 w_length = le16_to_cpu(cr->wLength);
+	u16 w_value = le16_to_cpu(cr->wValue);
+	u8 control_selector = w_value >> 8;
+
+	if (control_selector == UAC2_CS_CONTROL_SAM_FREQ)
+		return w_length;
+
+	return -EOPNOTSUPP;
+}
+
+static int
+setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	u16 w_index = le16_to_cpu(cr->wIndex);
+	u8 intf = w_index & 0xff;
+
+	if (intf != INTF_GET(agdev->ac_alt)) {
+		dev_err(&uac2->pdev.dev,
+			"%s:%d Error!\n", __func__, __LINE__);
+		return -EOPNOTSUPP;
+	}
+
+	if (cr->bRequestType & USB_DIR_IN)
+		return ac_rq_in(fn, cr);
+	else if (cr->bRequest == UAC2_CS_CUR)
+		return out_rq_cur(fn, cr);
+
+	return -EOPNOTSUPP;
+}
+
+static int
+afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr)
+{
+	struct usb_composite_dev *cdev = fn->config->cdev;
+	struct audio_dev *agdev = func_to_agdev(fn);
+	struct snd_uac2_chip *uac2 = &agdev->uac2;
+	struct usb_request *req = cdev->req;
+	u16 w_length = le16_to_cpu(cr->wLength);
+	int value = -EOPNOTSUPP;
+
+	/* Only Class specific requests are supposed to reach here */
+	if ((cr->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS)
+		return -EOPNOTSUPP;
+
+	if ((cr->bRequestType & USB_RECIP_MASK) == USB_RECIP_INTERFACE)
+		value = setup_rq_inf(fn, cr);
+	else
+		dev_err(&uac2->pdev.dev, "%s:%d Error!\n", __func__, __LINE__);
+
+	if (value >= 0) {
+		req->length = value;
+		req->zero = value < w_length;
+		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0) {
+			dev_err(&uac2->pdev.dev,
+				"%s:%d Error!\n", __func__, __LINE__);
+			req->status = 0;
+		}
+	}
+
+	return value;
+}
+
+static int audio_bind_config(struct usb_configuration *cfg)
+{
+	int id, res;
+
+	agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL);
+	if (agdev_g == NULL) {
+		printk(KERN_ERR "Unable to allocate audio gadget\n");
+		return -ENOMEM;
+	}
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_ASSOC].id = id;
+	iad_desc.iFunction = id,
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_IF_CTRL].id = id;
+	std_ac_if_desc.iInterface = id,
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_CLKSRC_IN].id = id;
+	in_clk_src_desc.iClockSource = id,
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_CLKSRC_OUT].id = id;
+	out_clk_src_desc.iClockSource = id,
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_USB_IT].id = id;
+	usb_out_it_desc.iTerminal = id,
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_IO_IT].id = id;
+	io_in_it_desc.iTerminal = id;
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_USB_OT].id = id;
+	usb_in_ot_desc.iTerminal = id;
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_IO_OT].id = id;
+	io_out_ot_desc.iTerminal = id;
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_AS_OUT_ALT0].id = id;
+	std_as_out_if0_desc.iInterface = id;
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_AS_OUT_ALT1].id = id;
+	std_as_out_if1_desc.iInterface = id;
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_AS_IN_ALT0].id = id;
+	std_as_in_if0_desc.iInterface = id;
+
+	id = usb_string_id(cfg->cdev);
+	if (id < 0)
+		return id;
+
+	strings_fn[STR_AS_IN_ALT1].id = id;
+	std_as_in_if1_desc.iInterface = id;
+
+	agdev_g->func.name = "uac2_func";
+	agdev_g->func.strings = fn_strings;
+	agdev_g->func.bind = afunc_bind;
+	agdev_g->func.unbind = afunc_unbind;
+	agdev_g->func.set_alt = afunc_set_alt;
+	agdev_g->func.get_alt = afunc_get_alt;
+	agdev_g->func.disable = afunc_disable;
+	agdev_g->func.setup = afunc_setup;
+
+	/* Initialize the configurable parameters */
+	usb_out_it_desc.bNrChannels = num_channels(c_chmask);
+	usb_out_it_desc.bmChannelConfig = cpu_to_le32(c_chmask);
+	io_in_it_desc.bNrChannels = num_channels(p_chmask);
+	io_in_it_desc.bmChannelConfig = cpu_to_le32(p_chmask);
+	as_out_hdr_desc.bNrChannels = num_channels(c_chmask);
+	as_out_hdr_desc.bmChannelConfig = cpu_to_le32(c_chmask);
+	as_in_hdr_desc.bNrChannels = num_channels(p_chmask);
+	as_in_hdr_desc.bmChannelConfig = cpu_to_le32(p_chmask);
+	as_out_fmt1_desc.bSubslotSize = c_ssize;
+	as_out_fmt1_desc.bBitResolution = c_ssize * 8;
+	as_in_fmt1_desc.bSubslotSize = p_ssize;
+	as_in_fmt1_desc.bBitResolution = p_ssize * 8;
+
+	snprintf(clksrc_in, sizeof(clksrc_in), "%uHz", p_srate);
+	snprintf(clksrc_out, sizeof(clksrc_out), "%uHz", c_srate);
+
+	res = usb_add_function(cfg, &agdev_g->func);
+	if (res < 0)
+		kfree(agdev_g);
+
+	return res;
+}
+
+static void
+uac2_unbind_config(struct usb_configuration *cfg)
+{
+	kfree(agdev_g);
+	agdev_g = NULL;
+}
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 47766f0..4fac569 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -855,7 +855,7 @@
 	if (transport_is_bbb()) {
 		switch (ctrl->bRequest) {
 
-		case USB_BULK_RESET_REQUEST:
+		case US_BULK_RESET_REQUEST:
 			if (ctrl->bRequestType != (USB_DIR_OUT |
 					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
 				break;
@@ -871,7 +871,7 @@
 			value = DELAYED_STATUS;
 			break;
 
-		case USB_BULK_GET_MAX_LUN_REQUEST:
+		case US_BULK_GET_MAX_LUN:
 			if (ctrl->bRequestType != (USB_DIR_IN |
 					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
 				break;
@@ -2125,7 +2125,7 @@
 	struct fsg_lun		*curlun = fsg->curlun;
 	struct fsg_buffhd	*bh;
 	int			rc;
-	u8			status = USB_STATUS_PASS;
+	u8			status = US_BULK_STAT_OK;
 	u32			sd, sdinfo = 0;
 
 	/* Wait for the next buffer to become available */
@@ -2146,11 +2146,11 @@
 
 	if (fsg->phase_error) {
 		DBG(fsg, "sending phase-error status\n");
-		status = USB_STATUS_PHASE_ERROR;
+		status = US_BULK_STAT_PHASE;
 		sd = SS_INVALID_COMMAND;
 	} else if (sd != SS_NO_SENSE) {
 		DBG(fsg, "sending command-failure status\n");
-		status = USB_STATUS_FAIL;
+		status = US_BULK_STAT_FAIL;
 		VDBG(fsg, "  sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
 				"  info x%x\n",
 				SK(sd), ASC(sd), ASCQ(sd), sdinfo);
@@ -2160,12 +2160,12 @@
 		struct bulk_cs_wrap	*csw = bh->buf;
 
 		/* Store and send the Bulk-only CSW */
-		csw->Signature = cpu_to_le32(USB_BULK_CS_SIG);
+		csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
 		csw->Tag = fsg->tag;
 		csw->Residue = cpu_to_le32(fsg->residue);
 		csw->Status = status;
 
-		bh->inreq->length = USB_BULK_CS_WRAP_LEN;
+		bh->inreq->length = US_BULK_CS_WRAP_LEN;
 		bh->inreq->zero = 0;
 		start_transfer(fsg, fsg->bulk_in, bh->inreq,
 				&bh->inreq_busy, &bh->state);
@@ -2609,16 +2609,16 @@
 static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
 {
 	struct usb_request		*req = bh->outreq;
-	struct fsg_bulk_cb_wrap	*cbw = req->buf;
+	struct bulk_cb_wrap	*cbw = req->buf;
 
 	/* Was this a real packet?  Should it be ignored? */
 	if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
 		return -EINVAL;
 
 	/* Is the CBW valid? */
-	if (req->actual != USB_BULK_CB_WRAP_LEN ||
+	if (req->actual != US_BULK_CB_WRAP_LEN ||
 			cbw->Signature != cpu_to_le32(
-				USB_BULK_CB_SIG)) {
+				US_BULK_CB_SIGN)) {
 		DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
 				req->actual,
 				le32_to_cpu(cbw->Signature));
@@ -2638,7 +2638,7 @@
 	}
 
 	/* Is the CBW meaningful? */
-	if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG ||
+	if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
 			cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
 		DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
 				"cmdlen %u\n",
@@ -2656,7 +2656,7 @@
 	/* Save the command for later */
 	fsg->cmnd_size = cbw->Length;
 	memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);
-	if (cbw->Flags & USB_BULK_IN_FLAG)
+	if (cbw->Flags & US_BULK_FLAG_IN)
 		fsg->data_dir = DATA_DIR_TO_HOST;
 	else
 		fsg->data_dir = DATA_DIR_FROM_HOST;
@@ -2685,7 +2685,7 @@
 		}
 
 		/* Queue a request to read a Bulk-only CBW */
-		set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN);
+		set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN);
 		start_transfer(fsg, fsg->bulk_out, bh->outreq,
 				&bh->outreq_busy, &bh->state);
 
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index b95697c..877a2c4 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -1638,6 +1638,7 @@
 	/* Nuke all pending requests (does flush) */
 	nuke(ep, -ESHUTDOWN);
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	ep->tx_req = NULL;
 	qe_ep_reset(udc, ep->epnum);
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index b04712f..b30e21f 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -659,6 +659,7 @@
 	nuke(ep, -ESHUTDOWN);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	spin_unlock_irqrestore(&udc->lock, flags);
 
@@ -768,7 +769,7 @@
  * @is_last: return flag if it is the last dTD of the request
  * return: pointer to the built dTD */
 static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
-		dma_addr_t *dma, int *is_last)
+		dma_addr_t *dma, int *is_last, gfp_t gfp_flags)
 {
 	u32 swap_temp;
 	struct ep_td_struct *dtd;
@@ -777,7 +778,7 @@
 	*length = min(req->req.length - req->req.actual,
 			(unsigned)EP_MAX_LENGTH_TRANSFER);
 
-	dtd = dma_pool_alloc(udc_controller->td_pool, GFP_KERNEL, dma);
+	dtd = dma_pool_alloc(udc_controller->td_pool, gfp_flags, dma);
 	if (dtd == NULL)
 		return dtd;
 
@@ -827,7 +828,7 @@
 }
 
 /* Generate dtd chain for a request */
-static int fsl_req_to_dtd(struct fsl_req *req)
+static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags)
 {
 	unsigned	count;
 	int		is_last;
@@ -836,7 +837,7 @@
 	dma_addr_t dma;
 
 	do {
-		dtd = fsl_build_dtd(req, &count, &dma, &is_last);
+		dtd = fsl_build_dtd(req, &count, &dma, &is_last, gfp_flags);
 		if (dtd == NULL)
 			return -ENOMEM;
 
@@ -910,13 +911,11 @@
 	req->req.actual = 0;
 	req->dtd_count = 0;
 
-	spin_lock_irqsave(&udc->lock, flags);
-
 	/* build dtds and push them to device queue */
-	if (!fsl_req_to_dtd(req)) {
+	if (!fsl_req_to_dtd(req, gfp_flags)) {
+		spin_lock_irqsave(&udc->lock, flags);
 		fsl_queue_td(ep, req);
 	} else {
-		spin_unlock_irqrestore(&udc->lock, flags);
 		return -ENOMEM;
 	}
 
@@ -1217,7 +1216,7 @@
 
 	udc = container_of(gadget, struct fsl_udc, gadget);
 	if (udc->transceiver)
-		return otg_set_power(udc->transceiver, mA);
+		return usb_phy_set_power(udc->transceiver, mA);
 	return -ENOTSUPP;
 }
 
@@ -1295,7 +1294,7 @@
 			ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 	req->mapped = 1;
 
-	if (fsl_req_to_dtd(req) == 0)
+	if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
 		fsl_queue_td(ep, req);
 	else
 		return -ENOMEM;
@@ -1379,7 +1378,7 @@
 	req->mapped = 1;
 
 	/* prime the data phase */
-	if ((fsl_req_to_dtd(req) == 0))
+	if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
 		fsl_queue_td(ep, req);
 	else			/* no mem */
 		goto stall;
@@ -1966,7 +1965,8 @@
 
 		/* connect to bus through transceiver */
 		if (udc_controller->transceiver) {
-			retval = otg_set_peripheral(udc_controller->transceiver,
+			retval = otg_set_peripheral(
+					udc_controller->transceiver->otg,
 						    &udc_controller->gadget);
 			if (retval < 0) {
 				ERR("can't bind to transceiver\n");
@@ -2006,7 +2006,7 @@
 		return -EINVAL;
 
 	if (udc_controller->transceiver)
-		otg_set_peripheral(udc_controller->transceiver, NULL);
+		otg_set_peripheral(udc_controller->transceiver->otg, NULL);
 
 	/* stop DR, disable intr */
 	dr_controller_stop(udc_controller);
@@ -2430,7 +2430,7 @@
 
 #ifdef CONFIG_USB_OTG
 	if (pdata->operating_mode == FSL_USB2_DR_OTG) {
-		udc_controller->transceiver = otg_get_transceiver();
+		udc_controller->transceiver = usb_get_transceiver();
 		if (!udc_controller->transceiver) {
 			ERR("Can't find OTG driver!\n");
 			ret = -ENODEV;
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index f781f5d..e651469 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -471,7 +471,7 @@
 
 	struct usb_ctrlrequest local_setup_buff;
 	spinlock_t lock;
-	struct otg_transceiver *transceiver;
+	struct usb_phy *transceiver;
 	unsigned softconnect:1;
 	unsigned vbus_active:1;
 	unsigned stopped:1;
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index 0519d77..331cd67 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -2,7 +2,7 @@
  * g_ffs.c -- user mode file system API for USB composite function controllers
  *
  * Copyright (C) 2010 Samsung Electronics
- * Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
+ * Author: Michal Nazarewicz <mina86@mina86.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
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 5af70fc..e1dfd32 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -235,6 +235,7 @@
 
 	ep->ep.maxpacket = MAX_FIFO_SIZE;
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	ep->irqs = 0;
 	ep->dma = 0;
@@ -310,12 +311,9 @@
 		status = req->req.status;
 
 	dev = ep->dev;
-	if (req->mapped) {
-		pci_unmap_single(dev->pdev, req->req.dma, req->req.length,
-			ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	}
+
+	if (ep->dma)
+		usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
 
 #ifndef USB_TRACE
 	if (status && status != -ESHUTDOWN)
@@ -736,10 +734,11 @@
 		return -EBUSY;
 
 	/* set up dma mapping in case the caller didn't */
-	if (ep->dma && _req->dma == DMA_ADDR_INVALID) {
-		_req->dma = pci_map_single(dev->pdev, _req->buf, _req->length,
-			ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->mapped = 1;
+	if (ep->dma) {
+		status = usb_gadget_map_request(&dev->gadget, &req->req,
+				ep->is_in);
+		if (status)
+			return status;
 	}
 
 #ifdef USB_TRACE
diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c
index f888c3e..3493adf 100644
--- a/drivers/usb/gadget/hid.c
+++ b/drivers/usb/gadget/hid.c
@@ -60,9 +60,9 @@
 	/* .bDeviceClass =		USB_CLASS_COMM, */
 	/* .bDeviceSubClass =	0, */
 	/* .bDeviceProtocol =	0, */
-	.bDeviceClass =		0xEF,
-	.bDeviceSubClass =	2,
-	.bDeviceProtocol =	1,
+	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
+	.bDeviceSubClass =	0,
+	.bDeviceProtocol =	0,
 	/* .bMaxPacketSize0 = f(hardware) */
 
 	/* Vendor and product id can be overridden by module parameters.  */
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index ae04266..4f18a0e 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1043,6 +1043,8 @@
 // FIXME don't call this with the spinlock held ...
 				if (copy_to_user (buf, dev->req->buf, len))
 					retval = -EFAULT;
+				else
+					retval = len;
 				clean_req (dev->gadget->ep0, dev->req);
 				/* NOTE userspace can't yet choose to stall */
 			}
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
index e2293c1..edd52d9 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -401,16 +401,7 @@
 		dma_pool_free(dev->dtd_pool, curr_dtd, curr_dtd->dtd_dma);
 	}
 
-	if (req->mapped) {
-		dma_unmap_single(&dev->pdev->dev,
-			req->req.dma, req->req.length,
-			is_in(ep) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	} else
-		dma_sync_single_for_cpu(&dev->pdev->dev, req->req.dma,
-				req->req.length,
-				is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	usb_gadget_unmap_request(&dev->gadget, &req->req, is_in(ep));
 
 	if (status != -ESHUTDOWN)
 		dev_dbg(&dev->pdev->dev,
@@ -487,6 +478,7 @@
 	nuke(ep, -ESHUTDOWN);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
 	spin_unlock_irqrestore(&dev->lock, flags);
@@ -749,7 +741,8 @@
 	struct langwell_ep	*ep;
 	struct langwell_udc	*dev;
 	unsigned long		flags;
-	int			is_iso = 0, zlflag = 0;
+	int			is_iso = 0;
+	int			ret;
 
 	/* always require a cpu-view buffer */
 	req = container_of(_req, struct langwell_request, req);
@@ -776,33 +769,10 @@
 	if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))
 		return -ESHUTDOWN;
 
-	/* set up dma mapping in case the caller didn't */
-	if (_req->dma == DMA_ADDR_INVALID) {
-		/* WORKAROUND: WARN_ON(size == 0) */
-		if (_req->length == 0) {
-			dev_vdbg(&dev->pdev->dev, "req->length: 0->1\n");
-			zlflag = 1;
-			_req->length++;
-		}
-
-		_req->dma = dma_map_single(&dev->pdev->dev,
-				_req->buf, _req->length,
-				is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		if (zlflag && (_req->length == 1)) {
-			dev_vdbg(&dev->pdev->dev, "req->length: 1->0\n");
-			zlflag = 0;
-			_req->length = 0;
-		}
-
-		req->mapped = 1;
-		dev_vdbg(&dev->pdev->dev, "req->mapped = 1\n");
-	} else {
-		dma_sync_single_for_device(&dev->pdev->dev,
-				_req->dma, _req->length,
-				is_in(ep) ?  DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->mapped = 0;
-		dev_vdbg(&dev->pdev->dev, "req->mapped = 0\n");
-	}
+	/* set up dma mapping */
+	ret = usb_gadget_map_request(&dev->gadget, &req->req, is_in(ep));
+	if (ret)
+		return ret;
 
 	dev_dbg(&dev->pdev->dev,
 			"%s queue req %p, len %u, buf %p, dma 0x%08x\n",
@@ -1261,9 +1231,9 @@
 	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (dev->transceiver) {
-		dev_vdbg(&dev->pdev->dev, "otg_set_power\n");
+		dev_vdbg(&dev->pdev->dev, "usb_phy_set_power\n");
 		dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
-		return otg_set_power(dev->transceiver, mA);
+		return usb_phy_set_power(dev->transceiver, mA);
 	}
 
 	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
@@ -1906,7 +1876,7 @@
 
 	/* unbind OTG transceiver */
 	if (dev->transceiver)
-		(void)otg_set_peripheral(dev->transceiver, 0);
+		(void)otg_set_peripheral(dev->transceiver->otg, 0);
 
 	/* disable interrupt and set controller to stop state */
 	langwell_udc_stop(dev);
diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h
index d6e78ac..8c8087a 100644
--- a/drivers/usb/gadget/langwell_udc.h
+++ b/drivers/usb/gadget/langwell_udc.h
@@ -162,7 +162,7 @@
 	spinlock_t		lock;	/* device lock */
 	struct langwell_ep	*ep;
 	struct usb_gadget_driver	*driver;
-	struct otg_transceiver	*transceiver;
+	struct usb_phy		*transceiver;
 	u8			dev_addr;
 	u32			usb_state;
 	u32			resume_state;
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index e24f72f..1f376eb 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/mass_storage.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2003-2008 Alan Stern
  * Copyright (C) 2009 Samsung Electronics
- *                    Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
+ *                    Author: Michal Nazarewicz <mina86@mina86.com>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 7e7f515..c37fb33 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -4,7 +4,7 @@
  * Copyright (C) 2008 David Brownell
  * Copyright (C) 2008 Nokia Corporation
  * Copyright (C) 2009 Samsung Electronics
- * Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
+ * Author: Michal Nazarewicz (mina86@mina86.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
diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h
index 34aadfa..e2be951 100644
--- a/drivers/usb/gadget/mv_udc.h
+++ b/drivers/usb/gadget/mv_udc.h
@@ -217,7 +217,7 @@
 	struct work_struct	vbus_work;
 	struct workqueue_struct *qwork;
 
-	struct otg_transceiver	*transceiver;
+	struct usb_phy		*transceiver;
 
 	struct mv_usb_platform_data     *pdata;
 
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index f97e737..19bbe80 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -608,6 +608,7 @@
 	nuke(ep, -ESHUTDOWN);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
 	spin_unlock_irqrestore(&udc->lock, flags);
@@ -771,8 +772,7 @@
 		udc->ep0_state = DATA_STATE_XMIT;
 
 	/* irq handler advances the queue */
-	if (req != NULL)
-		list_add_tail(&req->queue, &ep->queue);
+	list_add_tail(&req->queue, &ep->queue);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 	return 0;
@@ -1384,7 +1384,8 @@
 	}
 
 	if (udc->transceiver) {
-		retval = otg_set_peripheral(udc->transceiver, &udc->gadget);
+		retval = otg_set_peripheral(udc->transceiver->otg,
+					&udc->gadget);
 		if (retval) {
 			dev_err(&udc->dev->dev,
 				"unable to register peripheral to otg\n");
@@ -2181,7 +2182,7 @@
 
 #ifdef CONFIG_USB_OTG_UTILS
 	if (pdata->mode == MV_USB_MODE_OTG)
-		udc->transceiver = otg_get_transceiver();
+		udc->transceiver = usb_get_transceiver();
 #endif
 
 	udc->clknum = pdata->clknum;
diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
index 7322d29..01ae56f 100644
--- a/drivers/usb/gadget/net2272.c
+++ b/drivers/usb/gadget/net2272.c
@@ -385,12 +385,9 @@
 		status = req->req.status;
 
 	dev = ep->dev;
-	if (use_dma && req->mapped) {
-		dma_unmap_single(dev->dev, req->req.dma, req->req.length,
-			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	}
+	if (use_dma && ep->dma)
+		usb_gadget_unmap_request(&dev->gadget, &req->req,
+				ep->is_in);
 
 	if (status && status != -ESHUTDOWN)
 		dev_vdbg(dev->dev, "complete %s req %p stat %d len %u/%u buf %p\n",
@@ -850,10 +847,11 @@
 		return -ESHUTDOWN;
 
 	/* set up dma mapping in case the caller didn't */
-	if (use_dma && ep->dma && _req->dma == DMA_ADDR_INVALID) {
-		_req->dma = dma_map_single(dev->dev, _req->buf, _req->length,
-			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->mapped = 1;
+	if (use_dma && ep->dma) {
+		status = usb_gadget_map_request(&dev->gadget, _req,
+				ep->is_in);
+		if (status)
+			return status;
 	}
 
 	dev_vdbg(dev->dev, "%s queue req %p, len %d buf %p dma %08llx %s\n",
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index cdedd13..a5ccabc 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -806,12 +806,8 @@
 		status = req->req.status;
 
 	dev = ep->dev;
-	if (req->mapped) {
-		pci_unmap_single (dev->pdev, req->req.dma, req->req.length,
-			ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	}
+	if (ep->dma)
+		usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
 
 	if (status && status != -ESHUTDOWN)
 		VDEBUG (dev, "complete %s req %p stat %d len %u/%u\n",
@@ -857,10 +853,13 @@
 		return -EOPNOTSUPP;
 
 	/* set up dma mapping in case the caller didn't */
-	if (ep->dma && _req->dma == DMA_ADDR_INVALID) {
-		_req->dma = pci_map_single (dev->pdev, _req->buf, _req->length,
-			ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		req->mapped = 1;
+	if (ep->dma) {
+		int ret;
+
+		ret = usb_gadget_map_request(&dev->gadget, _req,
+				ep->is_in);
+		if (ret)
+			return ret;
 	}
 
 #if 0
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 576cd85..b44830d 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -251,6 +251,7 @@
 
 	spin_lock_irqsave(&ep->udc->lock, flags);
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	nuke (ep, -ESHUTDOWN);
 	ep->ep.maxpacket = ep->maxpacket;
 	ep->has_dma = 0;
@@ -1213,7 +1214,7 @@
 	/* NOTE:  non-OTG systems may use SRP TOO... */
 	} else if (!(udc->devstat & UDC_ATT)) {
 		if (udc->transceiver)
-			retval = otg_start_srp(udc->transceiver);
+			retval = otg_start_srp(udc->transceiver->otg);
 	}
 	spin_unlock_irqrestore(&udc->lock, flags);
 
@@ -1345,7 +1346,7 @@
 
 	udc = container_of(gadget, struct omap_udc, gadget);
 	if (udc->transceiver)
-		return otg_set_power(udc->transceiver, mA);
+		return usb_phy_set_power(udc->transceiver, mA);
 	return -EOPNOTSUPP;
 }
 
@@ -1839,11 +1840,13 @@
 					spin_lock(&udc->lock);
 				}
 				if (udc->transceiver)
-					otg_set_suspend(udc->transceiver, 1);
+					usb_phy_set_suspend(
+							udc->transceiver, 1);
 			} else {
 				VDBG("resume\n");
 				if (udc->transceiver)
-					otg_set_suspend(udc->transceiver, 0);
+					usb_phy_set_suspend(
+							udc->transceiver, 0);
 				if (udc->gadget.speed == USB_SPEED_FULL
 						&& udc->driver->resume) {
 					spin_unlock(&udc->lock);
@@ -2154,7 +2157,8 @@
 
 	/* connect to bus through transceiver */
 	if (udc->transceiver) {
-		status = otg_set_peripheral(udc->transceiver, &udc->gadget);
+		status = otg_set_peripheral(udc->transceiver->otg,
+						&udc->gadget);
 		if (status < 0) {
 			ERR("can't bind to transceiver\n");
 			if (driver->unbind) {
@@ -2200,7 +2204,7 @@
 		omap_vbus_session(&udc->gadget, 0);
 
 	if (udc->transceiver)
-		(void) otg_set_peripheral(udc->transceiver, NULL);
+		(void) otg_set_peripheral(udc->transceiver->otg, NULL);
 	else
 		pullup_disable(udc);
 
@@ -2650,7 +2654,7 @@
 }
 
 static int __init
-omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv)
+omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
 {
 	unsigned	tmp, buf;
 
@@ -2790,7 +2794,7 @@
 {
 	int			status = -ENODEV;
 	int			hmc;
-	struct otg_transceiver	*xceiv = NULL;
+	struct usb_phy		*xceiv = NULL;
 	const char		*type = NULL;
 	struct omap_usb_config	*config = pdev->dev.platform_data;
 	struct clk		*dc_clk;
@@ -2863,7 +2867,7 @@
 		 * use it.  Except for OTG, we don't _need_ to talk to one;
 		 * but not having one probably means no VBUS detection.
 		 */
-		xceiv = otg_get_transceiver();
+		xceiv = usb_get_transceiver();
 		if (xceiv)
 			type = xceiv->label;
 		else if (config->otg) {
@@ -3009,7 +3013,7 @@
 
 cleanup0:
 	if (xceiv)
-		otg_put_transceiver(xceiv);
+		usb_put_transceiver(xceiv);
 
 	if (cpu_is_omap16xx() || cpu_is_omap24xx() || cpu_is_omap7xx()) {
 		clk_disable(hhc_clk);
@@ -3039,7 +3043,7 @@
 
 	pullup_disable(udc);
 	if (udc->transceiver) {
-		otg_put_transceiver(udc->transceiver);
+		usb_put_transceiver(udc->transceiver);
 		udc->transceiver = NULL;
 	}
 	omap_writew(0, UDC_SYSCON1);
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
index 29edc51..59d3b22 100644
--- a/drivers/usb/gadget/omap_udc.h
+++ b/drivers/usb/gadget/omap_udc.h
@@ -164,7 +164,7 @@
 	struct omap_ep			ep[32];
 	u16				devstat;
 	u16				clr_halt;
-	struct otg_transceiver		*transceiver;
+	struct usb_phy			*transceiver;
 	struct list_head		iso;
 	unsigned			softconnect:1;
 	unsigned			vbus_active:1;
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index a3fcaae..6530706 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -15,6 +15,14 @@
 #include <linux/interrupt.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+
+/* GPIO port for VBUS detecting */
+static int vbus_gpio_port = -1;		/* GPIO port number (-1:Not used) */
+
+#define PCH_VBUS_PERIOD		3000	/* VBUS polling period (msec) */
+#define PCH_VBUS_INTERVAL	10	/* VBUS polling interval (msec) */
 
 /* Address offset of Registers */
 #define UDC_EP_REG_SHIFT	0x20	/* Offset to next EP */
@@ -296,6 +304,21 @@
 };
 
 /**
+ * struct pch_vbus_gpio_data - Structure holding GPIO informaton
+ *					for detecting VBUS
+ * @port:		gpio port number
+ * @intr:		gpio interrupt number
+ * @irq_work_fall	Structure for WorkQueue
+ * @irq_work_rise	Structure for WorkQueue
+ */
+struct pch_vbus_gpio_data {
+	int			port;
+	int			intr;
+	struct work_struct	irq_work_fall;
+	struct work_struct	irq_work_rise;
+};
+
+/**
  * struct pch_udc_dev - Structure holding complete information
  *			of the PCH USB device
  * @gadget:		gadget driver data
@@ -311,6 +334,7 @@
  * @registered:		driver regsitered with system
  * @suspended:		driver in suspended state
  * @connected:		gadget driver associated
+ * @vbus_session:	required vbus_session state
  * @set_cfg_not_acked:	pending acknowledgement 4 setup
  * @waiting_zlp_ack:	pending acknowledgement 4 ZLP
  * @data_requests:	DMA pool for data requests
@@ -322,6 +346,7 @@
  * @base_addr:		for mapped device memory
  * @irq:		IRQ line for the device
  * @cfg_data:		current cfg, intf, and alt in use
+ * @vbus_gpio:		GPIO informaton for detecting VBUS
  */
 struct pch_udc_dev {
 	struct usb_gadget		gadget;
@@ -337,6 +362,7 @@
 			registered:1,
 			suspended:1,
 			connected:1,
+			vbus_session:1,
 			set_cfg_not_acked:1,
 			waiting_zlp_ack:1;
 	struct pci_pool		*data_requests;
@@ -347,7 +373,8 @@
 	unsigned long			phys_addr;
 	void __iomem			*base_addr;
 	unsigned			irq;
-	struct pch_udc_cfg_data	cfg_data;
+	struct pch_udc_cfg_data		cfg_data;
+	struct pch_vbus_gpio_data	vbus_gpio;
 };
 
 #define PCH_UDC_PCI_BAR			1
@@ -554,6 +581,29 @@
 }
 
 /**
+ * pch_udc_reconnect() - This API initializes usb device controller,
+ *						and clear the disconnect status.
+ * @dev:		Reference to pch_udc_regs structure
+ */
+static void pch_udc_init(struct pch_udc_dev *dev);
+static void pch_udc_reconnect(struct pch_udc_dev *dev)
+{
+	pch_udc_init(dev);
+
+	/* enable device interrupts */
+	/* pch_udc_enable_interrupts() */
+	pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR,
+			UDC_DEVINT_UR | UDC_DEVINT_ENUM);
+
+	/* Clear the disconnect */
+	pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+	pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD);
+	mdelay(1);
+	/* Resume USB signalling */
+	pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+}
+
+/**
  * pch_udc_vbus_session() - set or clearr the disconnect status.
  * @dev:	Reference to pch_udc_regs structure
  * @is_active:	Parameter specifying the action
@@ -563,10 +613,18 @@
 static inline void pch_udc_vbus_session(struct pch_udc_dev *dev,
 					  int is_active)
 {
-	if (is_active)
-		pch_udc_clear_disconnect(dev);
-	else
+	if (is_active) {
+		pch_udc_reconnect(dev);
+		dev->vbus_session = 1;
+	} else {
+		if (dev->driver && dev->driver->disconnect) {
+			spin_unlock(&dev->lock);
+			dev->driver->disconnect(&dev->gadget);
+			spin_lock(&dev->lock);
+		}
 		pch_udc_set_disconnect(dev);
+		dev->vbus_session = 0;
+	}
 }
 
 /**
@@ -1126,7 +1184,17 @@
 	if (!gadget)
 		return -EINVAL;
 	dev = container_of(gadget, struct pch_udc_dev, gadget);
-	pch_udc_vbus_session(dev, is_on);
+	if (is_on) {
+		pch_udc_reconnect(dev);
+	} else {
+		if (dev->driver && dev->driver->disconnect) {
+			spin_unlock(&dev->lock);
+			dev->driver->disconnect(&dev->gadget);
+			spin_lock(&dev->lock);
+		}
+		pch_udc_set_disconnect(dev);
+	}
+
 	return 0;
 }
 
@@ -1183,6 +1251,188 @@
 };
 
 /**
+ * pch_vbus_gpio_get_value() - This API gets value of GPIO port as VBUS status.
+ * @dev:	Reference to the driver structure
+ *
+ * Return value:
+ *	1: VBUS is high
+ *	0: VBUS is low
+ *     -1: It is not enable to detect VBUS using GPIO
+ */
+static int pch_vbus_gpio_get_value(struct pch_udc_dev *dev)
+{
+	int vbus = 0;
+
+	if (dev->vbus_gpio.port)
+		vbus = gpio_get_value(dev->vbus_gpio.port) ? 1 : 0;
+	else
+		vbus = -1;
+
+	return vbus;
+}
+
+/**
+ * pch_vbus_gpio_work_fall() - This API keeps watch on VBUS becoming Low.
+ *                             If VBUS is Low, disconnect is processed
+ * @irq_work:	Structure for WorkQueue
+ *
+ */
+static void pch_vbus_gpio_work_fall(struct work_struct *irq_work)
+{
+	struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work,
+		struct pch_vbus_gpio_data, irq_work_fall);
+	struct pch_udc_dev *dev =
+		container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio);
+	int vbus_saved = -1;
+	int vbus;
+	int count;
+
+	if (!dev->vbus_gpio.port)
+		return;
+
+	for (count = 0; count < (PCH_VBUS_PERIOD / PCH_VBUS_INTERVAL);
+		count++) {
+		vbus = pch_vbus_gpio_get_value(dev);
+
+		if ((vbus_saved == vbus) && (vbus == 0)) {
+			dev_dbg(&dev->pdev->dev, "VBUS fell");
+			if (dev->driver
+				&& dev->driver->disconnect) {
+				dev->driver->disconnect(
+					&dev->gadget);
+			}
+			if (dev->vbus_gpio.intr)
+				pch_udc_init(dev);
+			else
+				pch_udc_reconnect(dev);
+			return;
+		}
+		vbus_saved = vbus;
+		mdelay(PCH_VBUS_INTERVAL);
+	}
+}
+
+/**
+ * pch_vbus_gpio_work_rise() - This API checks VBUS is High.
+ *                             If VBUS is High, connect is processed
+ * @irq_work:	Structure for WorkQueue
+ *
+ */
+static void pch_vbus_gpio_work_rise(struct work_struct *irq_work)
+{
+	struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work,
+		struct pch_vbus_gpio_data, irq_work_rise);
+	struct pch_udc_dev *dev =
+		container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio);
+	int vbus;
+
+	if (!dev->vbus_gpio.port)
+		return;
+
+	mdelay(PCH_VBUS_INTERVAL);
+	vbus = pch_vbus_gpio_get_value(dev);
+
+	if (vbus == 1) {
+		dev_dbg(&dev->pdev->dev, "VBUS rose");
+		pch_udc_reconnect(dev);
+		return;
+	}
+}
+
+/**
+ * pch_vbus_gpio_irq() - IRQ handler for GPIO intrerrupt for changing VBUS
+ * @irq:	Interrupt request number
+ * @dev:	Reference to the device structure
+ *
+ * Return codes:
+ *	0: Success
+ *	-EINVAL: GPIO port is invalid or can't be initialized.
+ */
+static irqreturn_t pch_vbus_gpio_irq(int irq, void *data)
+{
+	struct pch_udc_dev *dev = (struct pch_udc_dev *)data;
+
+	if (!dev->vbus_gpio.port || !dev->vbus_gpio.intr)
+		return IRQ_NONE;
+
+	if (pch_vbus_gpio_get_value(dev))
+		schedule_work(&dev->vbus_gpio.irq_work_rise);
+	else
+		schedule_work(&dev->vbus_gpio.irq_work_fall);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * pch_vbus_gpio_init() - This API initializes GPIO port detecting VBUS.
+ * @dev:	Reference to the driver structure
+ * @vbus_gpio	Number of GPIO port to detect gpio
+ *
+ * Return codes:
+ *	0: Success
+ *	-EINVAL: GPIO port is invalid or can't be initialized.
+ */
+static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port)
+{
+	int err;
+	int irq_num = 0;
+
+	dev->vbus_gpio.port = 0;
+	dev->vbus_gpio.intr = 0;
+
+	if (vbus_gpio_port <= -1)
+		return -EINVAL;
+
+	err = gpio_is_valid(vbus_gpio_port);
+	if (!err) {
+		pr_err("%s: gpio port %d is invalid\n",
+			__func__, vbus_gpio_port);
+		return -EINVAL;
+	}
+
+	err = gpio_request(vbus_gpio_port, "pch_vbus");
+	if (err) {
+		pr_err("%s: can't request gpio port %d, err: %d\n",
+			__func__, vbus_gpio_port, err);
+		return -EINVAL;
+	}
+
+	dev->vbus_gpio.port = vbus_gpio_port;
+	gpio_direction_input(vbus_gpio_port);
+	INIT_WORK(&dev->vbus_gpio.irq_work_fall, pch_vbus_gpio_work_fall);
+
+	irq_num = gpio_to_irq(vbus_gpio_port);
+	if (irq_num > 0) {
+		irq_set_irq_type(irq_num, IRQ_TYPE_EDGE_BOTH);
+		err = request_irq(irq_num, pch_vbus_gpio_irq, 0,
+			"vbus_detect", dev);
+		if (!err) {
+			dev->vbus_gpio.intr = irq_num;
+			INIT_WORK(&dev->vbus_gpio.irq_work_rise,
+				pch_vbus_gpio_work_rise);
+		} else {
+			pr_err("%s: can't request irq %d, err: %d\n",
+				__func__, irq_num, err);
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * pch_vbus_gpio_free() - This API frees resources of GPIO port
+ * @dev:	Reference to the driver structure
+ */
+static void pch_vbus_gpio_free(struct pch_udc_dev *dev)
+{
+	if (dev->vbus_gpio.intr)
+		free_irq(dev->vbus_gpio.intr, dev);
+
+	if (dev->vbus_gpio.port)
+		gpio_free(dev->vbus_gpio.port);
+}
+
+/**
  * complete_req() - This API is invoked from the driver when processing
  *			of a request is complete
  * @ep:		Reference to the endpoint structure
@@ -1493,6 +1743,7 @@
 	pch_udc_ep_disable(ep);
 	pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	INIT_LIST_HEAD(&ep->queue);
 	spin_unlock_irqrestore(&ep->dev->lock, iflags);
 	return 0;
@@ -2335,8 +2586,11 @@
 		/* Complete request queue */
 		empty_req_queue(ep);
 	}
-	if (dev->driver && dev->driver->disconnect)
+	if (dev->driver && dev->driver->disconnect) {
+		spin_unlock(&dev->lock);
 		dev->driver->disconnect(&dev->gadget);
+		spin_lock(&dev->lock);
+	}
 }
 
 /**
@@ -2371,6 +2625,11 @@
 	pch_udc_set_dma(dev, DMA_DIR_TX);
 	pch_udc_set_dma(dev, DMA_DIR_RX);
 	pch_udc_ep_set_rrdy(&(dev->ep[UDC_EP0OUT_IDX]));
+
+	/* enable device interrupts */
+	pch_udc_enable_interrupts(dev, UDC_DEVINT_UR | UDC_DEVINT_US |
+					UDC_DEVINT_ES | UDC_DEVINT_ENUM |
+					UDC_DEVINT_SI | UDC_DEVINT_SC);
 }
 
 /**
@@ -2459,12 +2718,18 @@
  */
 static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
 {
+	int vbus;
+
 	/* USB Reset Interrupt */
-	if (dev_intr & UDC_DEVINT_UR)
+	if (dev_intr & UDC_DEVINT_UR) {
 		pch_udc_svc_ur_interrupt(dev);
+		dev_dbg(&dev->pdev->dev, "USB_RESET\n");
+	}
 	/* Enumeration Done Interrupt */
-	if (dev_intr & UDC_DEVINT_ENUM)
+	if (dev_intr & UDC_DEVINT_ENUM) {
 		pch_udc_svc_enum_interrupt(dev);
+		dev_dbg(&dev->pdev->dev, "USB_ENUM\n");
+	}
 	/* Set Interface Interrupt */
 	if (dev_intr & UDC_DEVINT_SI)
 		pch_udc_svc_intf_interrupt(dev);
@@ -2472,8 +2737,30 @@
 	if (dev_intr & UDC_DEVINT_SC)
 		pch_udc_svc_cfg_interrupt(dev);
 	/* USB Suspend interrupt */
-	if (dev_intr & UDC_DEVINT_US)
+	if (dev_intr & UDC_DEVINT_US) {
+		if (dev->driver
+			&& dev->driver->suspend) {
+			spin_unlock(&dev->lock);
+			dev->driver->suspend(&dev->gadget);
+			spin_lock(&dev->lock);
+		}
+
+		vbus = pch_vbus_gpio_get_value(dev);
+		if ((dev->vbus_session == 0)
+			&& (vbus != 1)) {
+			if (dev->driver && dev->driver->disconnect) {
+				spin_unlock(&dev->lock);
+				dev->driver->disconnect(&dev->gadget);
+				spin_lock(&dev->lock);
+			}
+			pch_udc_reconnect(dev);
+		} else if ((dev->vbus_session == 0)
+			&& (vbus == 1)
+			&& !dev->vbus_gpio.intr)
+			schedule_work(&dev->vbus_gpio.irq_work_fall);
+
 		dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n");
+	}
 	/* Clear the SOF interrupt, if enabled */
 	if (dev_intr & UDC_DEVINT_SOF)
 		dev_dbg(&dev->pdev->dev, "SOF\n");
@@ -2499,6 +2786,14 @@
 	dev_intr = pch_udc_read_device_interrupts(dev);
 	ep_intr = pch_udc_read_ep_interrupts(dev);
 
+	/* For a hot plug, this find that the controller is hung up. */
+	if (dev_intr == ep_intr)
+		if (dev_intr == pch_udc_readl(dev, UDC_DEVCFG_ADDR)) {
+			dev_dbg(&dev->pdev->dev, "UDC: Hung up\n");
+			/* The controller is reset */
+			pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
+			return IRQ_HANDLED;
+		}
 	if (dev_intr)
 		/* Clear device interrupts */
 		pch_udc_write_device_interrupts(dev, dev_intr);
@@ -2625,6 +2920,7 @@
 {
 	pch_udc_init(dev);
 	pch_udc_pcd_reinit(dev);
+	pch_vbus_gpio_init(dev, vbus_gpio_port);
 	return 0;
 }
 
@@ -2725,7 +3021,8 @@
 	pch_udc_setup_ep0(dev);
 
 	/* clear SD */
-	pch_udc_clear_disconnect(dev);
+	if ((pch_vbus_gpio_get_value(dev) != 0) || !dev->vbus_gpio.intr)
+		pch_udc_clear_disconnect(dev);
 
 	dev->connected = 1;
 	return 0;
@@ -2803,6 +3100,8 @@
 				 UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE);
 	kfree(dev->ep0out_buf);
 
+	pch_vbus_gpio_free(dev);
+
 	pch_udc_exit(dev);
 
 	if (dev->irq_registered)
@@ -2912,8 +3211,10 @@
 	}
 	pch_udc = dev;
 	/* initialize the hardware */
-	if (pch_udc_pcd_init(dev))
+	if (pch_udc_pcd_init(dev)) {
+		retval = -ENODEV;
 		goto finished;
+	}
 	if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME,
 			dev)) {
 		dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__,
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index dd47063..1b33634 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -283,6 +283,7 @@
 	pxa25x_ep_fifo_flush (_ep);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
 	local_irq_restore(flags);
@@ -995,7 +996,7 @@
 	udc = container_of(_gadget, struct pxa25x_udc, gadget);
 
 	if (udc->transceiver)
-		return otg_set_power(udc->transceiver, mA);
+		return usb_phy_set_power(udc->transceiver, mA);
 	return -EOPNOTSUPP;
 }
 
@@ -1192,6 +1193,7 @@
 			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
 
 		ep->desc = NULL;
+		ep->ep.desc = NULL;
 		ep->stopped = 0;
 		INIT_LIST_HEAD (&ep->queue);
 		ep->pio_irqs = 0;
@@ -1301,7 +1303,8 @@
 
 	/* connect to bus through transceiver */
 	if (dev->transceiver) {
-		retval = otg_set_peripheral(dev->transceiver, &dev->gadget);
+		retval = otg_set_peripheral(dev->transceiver->otg,
+						&dev->gadget);
 		if (retval) {
 			DMSG("can't bind to transceiver\n");
 			if (driver->unbind)
@@ -1360,7 +1363,7 @@
 	local_irq_enable();
 
 	if (dev->transceiver)
-		(void) otg_set_peripheral(dev->transceiver, NULL);
+		(void) otg_set_peripheral(dev->transceiver->otg, NULL);
 
 	driver->unbind(&dev->gadget);
 	dev->gadget.dev.driver = NULL;
@@ -2159,7 +2162,7 @@
 	dev->dev = &pdev->dev;
 	dev->mach = pdev->dev.platform_data;
 
-	dev->transceiver = otg_get_transceiver();
+	dev->transceiver = usb_get_transceiver();
 
 	if (gpio_is_valid(dev->mach->gpio_pullup)) {
 		if ((retval = gpio_request(dev->mach->gpio_pullup,
@@ -2238,7 +2241,7 @@
 		gpio_free(dev->mach->gpio_pullup);
  err_gpio_pullup:
 	if (dev->transceiver) {
-		otg_put_transceiver(dev->transceiver);
+		usb_put_transceiver(dev->transceiver);
 		dev->transceiver = NULL;
 	}
 	clk_put(dev->clk);
@@ -2280,7 +2283,7 @@
 	clk_put(dev->clk);
 
 	if (dev->transceiver) {
-		otg_put_transceiver(dev->transceiver);
+		usb_put_transceiver(dev->transceiver);
 		dev->transceiver = NULL;
 	}
 
diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h
index 8eaf4e4..893e917 100644
--- a/drivers/usb/gadget/pxa25x_udc.h
+++ b/drivers/usb/gadget/pxa25x_udc.h
@@ -119,7 +119,7 @@
 	struct device				*dev;
 	struct clk				*clk;
 	struct pxa2xx_udc_mach_info		*mach;
-	struct otg_transceiver			*transceiver;
+	struct usb_phy				*transceiver;
 	u64					dma_mask;
 	struct pxa25x_ep			ep [PXA_UDC_NUM_ENDPOINTS];
 
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index f4c44eb..98acb3a 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -1666,7 +1666,7 @@
 
 	udc = to_gadget_udc(_gadget);
 	if (udc->transceiver)
-		return otg_set_power(udc->transceiver, mA);
+		return usb_phy_set_power(udc->transceiver, mA);
 	return -EOPNOTSUPP;
 }
 
@@ -1835,7 +1835,8 @@
 		driver->driver.name);
 
 	if (udc->transceiver) {
-		retval = otg_set_peripheral(udc->transceiver, &udc->gadget);
+		retval = otg_set_peripheral(udc->transceiver->otg,
+						&udc->gadget);
 		if (retval) {
 			dev_err(udc->dev, "can't bind to transceiver\n");
 			goto transceiver_fail;
@@ -1908,7 +1909,7 @@
 		 driver->driver.name);
 
 	if (udc->transceiver)
-		return otg_set_peripheral(udc->transceiver, NULL);
+		return otg_set_peripheral(udc->transceiver->otg, NULL);
 	return 0;
 }
 
@@ -2463,7 +2464,7 @@
 
 	udc->dev = &pdev->dev;
 	udc->mach = pdev->dev.platform_data;
-	udc->transceiver = otg_get_transceiver();
+	udc->transceiver = usb_get_transceiver();
 
 	gpio = udc->mach->gpio_pullup;
 	if (gpio_is_valid(gpio)) {
@@ -2542,7 +2543,7 @@
 	if (gpio_is_valid(gpio))
 		gpio_free(gpio);
 
-	otg_put_transceiver(udc->transceiver);
+	usb_put_transceiver(udc->transceiver);
 
 	udc->transceiver = NULL;
 	platform_set_drvdata(_dev, NULL);
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h
index 7f4e8f4..a1d268c 100644
--- a/drivers/usb/gadget/pxa27x_udc.h
+++ b/drivers/usb/gadget/pxa27x_udc.h
@@ -447,7 +447,7 @@
 	struct usb_gadget_driver		*driver;
 	struct device				*dev;
 	struct pxa2xx_udc_mach_info		*mach;
-	struct otg_transceiver			*transceiver;
+	struct usb_phy				*transceiver;
 
 	enum ep0_state				ep0state;
 	struct udc_stats			stats;
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index f5b8d21..c4401e7 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -663,11 +663,7 @@
 	ep->fifoctr = D0FIFOCTR;
 
 	/* dma mapping */
-	req->req.dma = dma_map_single(r8a66597_to_dev(ep->r8a66597),
-				req->req.buf, req->req.length,
-				dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-
-	return 0;
+	return usb_gadget_map_request(&r8a66597->gadget, &req->req, dma->dir);
 }
 
 static void sudmac_free_channel(struct r8a66597 *r8a66597,
@@ -677,9 +673,7 @@
 	if (!r8a66597_is_sudmac(r8a66597))
 		return;
 
-	dma_unmap_single(r8a66597_to_dev(ep->r8a66597),
-			 req->req.dma, req->req.length,
-			 ep->dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	usb_gadget_unmap_request(&r8a66597->gadget, &req->req, ep->dma->dir);
 
 	r8a66597_bclr(r8a66597, DREQE, ep->fifosel);
 	r8a66597_change_curpipe(r8a66597, 0, 0, ep->fifosel);
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index df8661d..cef9b82 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -30,6 +30,7 @@
 #include <linux/prefetch.h>
 #include <linux/platform_data/s3c-hsudc.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
 
 #include <mach/regs-s3c2443-clock.h>
 
@@ -145,7 +146,7 @@
 	struct usb_gadget_driver *driver;
 	struct device *dev;
 	struct s3c24xx_hsudc_platdata *pd;
-	struct otg_transceiver *transceiver;
+	struct usb_phy *transceiver;
 	struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsudc_supply_names)];
 	spinlock_t lock;
 	void __iomem *regs;
@@ -759,7 +760,7 @@
 	unsigned long flags;
 	u32 ecr = 0;
 
-	hsep = container_of(_ep, struct s3c_hsudc_ep, ep);
+	hsep = our_ep(_ep);
 	if (!_ep || !desc || hsep->desc || _ep->name == ep0name
 		|| desc->bDescriptorType != USB_DT_ENDPOINT
 		|| hsep->bEndpointAddress != desc->bEndpointAddress
@@ -816,6 +817,7 @@
 	s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN);
 
 	hsep->desc = 0;
+	hsep->ep.desc = NULL;
 	hsep->stopped = 1;
 
 	spin_unlock_irqrestore(&hsudc->lock, flags);
@@ -853,7 +855,7 @@
 {
 	struct s3c_hsudc_req *hsreq;
 
-	hsreq = container_of(_req, struct s3c_hsudc_req, req);
+	hsreq = our_req(_req);
 	WARN_ON(!list_empty(&hsreq->queue));
 	kfree(hsreq);
 }
@@ -876,12 +878,12 @@
 	u32 offset;
 	u32 csr;
 
-	hsreq = container_of(_req, struct s3c_hsudc_req, req);
+	hsreq = our_req(_req);
 	if ((!_req || !_req->complete || !_req->buf ||
 		!list_empty(&hsreq->queue)))
 		return -EINVAL;
 
-	hsep = container_of(_ep, struct s3c_hsudc_ep, ep);
+	hsep = our_ep(_ep);
 	hsudc = hsep->dev;
 	if (!hsudc->driver || hsudc->gadget.speed == USB_SPEED_UNKNOWN)
 		return -ESHUTDOWN;
@@ -935,7 +937,7 @@
 	struct s3c_hsudc_req *hsreq;
 	unsigned long flags;
 
-	hsep = container_of(_ep, struct s3c_hsudc_ep, ep);
+	hsep = our_ep(_ep);
 	if (!_ep || hsep->ep.name == ep0name)
 		return -EINVAL;
 
@@ -1005,6 +1007,7 @@
 	hsep->ep.ops = &s3c_hsudc_ep_ops;
 	hsep->fifo = hsudc->regs + S3C_BR(epnum);
 	hsep->desc = 0;
+	hsep->ep.desc = NULL;
 	hsep->stopped = 0;
 	hsep->wedge = 0;
 
@@ -1166,7 +1169,8 @@
 
 	/* connect to bus through transceiver */
 	if (hsudc->transceiver) {
-		ret = otg_set_peripheral(hsudc->transceiver, &hsudc->gadget);
+		ret = otg_set_peripheral(hsudc->transceiver->otg,
+					&hsudc->gadget);
 		if (ret) {
 			dev_err(hsudc->dev, "%s: can't bind to transceiver\n",
 					hsudc->gadget.name);
@@ -1178,6 +1182,9 @@
 	dev_info(hsudc->dev, "bound driver %s\n", driver->driver.name);
 
 	s3c_hsudc_reconfig(hsudc);
+
+	pm_runtime_get_sync(hsudc->dev);
+
 	s3c_hsudc_init_phy();
 	if (hsudc->pd->gpio_init)
 		hsudc->pd->gpio_init();
@@ -1208,13 +1215,16 @@
 	hsudc->gadget.dev.driver = NULL;
 	hsudc->gadget.speed = USB_SPEED_UNKNOWN;
 	s3c_hsudc_uninit_phy();
+
+	pm_runtime_put(hsudc->dev);
+
 	if (hsudc->pd->gpio_uninit)
 		hsudc->pd->gpio_uninit();
 	s3c_hsudc_stop_activity(hsudc);
 	spin_unlock_irqrestore(&hsudc->lock, flags);
 
 	if (hsudc->transceiver)
-		(void) otg_set_peripheral(hsudc->transceiver, NULL);
+		(void) otg_set_peripheral(hsudc->transceiver->otg, NULL);
 
 	disable_irq(hsudc->irq);
 
@@ -1243,7 +1253,7 @@
 		return -ENODEV;
 
 	if (hsudc->transceiver)
-		return otg_set_power(hsudc->transceiver, mA);
+		return usb_phy_set_power(hsudc->transceiver, mA);
 
 	return -EOPNOTSUPP;
 }
@@ -1275,7 +1285,7 @@
 	hsudc->dev = dev;
 	hsudc->pd = pdev->dev.platform_data;
 
-	hsudc->transceiver = otg_get_transceiver();
+	hsudc->transceiver = usb_get_transceiver();
 
 	for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++)
 		hsudc->supplies[i].supply = s3c_hsudc_supply_names[i];
@@ -1362,6 +1372,8 @@
 	if (ret)
 		goto err_add_udc;
 
+	pm_runtime_enable(dev);
+
 	return 0;
 err_add_udc:
 	device_unregister(&hsudc->gadget.dev);
@@ -1377,7 +1389,7 @@
 	release_mem_region(res->start, resource_size(res));
 err_res:
 	if (hsudc->transceiver)
-		otg_put_transceiver(hsudc->transceiver);
+		usb_put_transceiver(hsudc->transceiver);
 
 	regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
 err_supplies:
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 3f87cb9..ab9c65e 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1148,6 +1148,7 @@
 	dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->halted = 1;
 
 	s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN);
@@ -1630,6 +1631,7 @@
 
 		ep->dev = dev;
 		ep->desc = NULL;
+		ep->ep.desc = NULL;
 		ep->halted = 0;
 		INIT_LIST_HEAD (&ep->queue);
 	}
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index ad9e5b2..665c074 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -242,7 +242,7 @@
 	.name		= "g_serial",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.max_speed	= USB_SPEED_HIGH,
+	.max_speed	= USB_SPEED_SUPER,
 };
 
 static int __init init(void)
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 85ea14e..8081ca3 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2003-2008 Alan Stern
  * Copyeight (C) 2009 Samsung Electronics
- * Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
+ * Author: Michal Nazarewicz (mina86@mina86.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
@@ -145,48 +145,8 @@
 
 #endif /* DUMP_MSGS */
 
-
-
-
-
 /*-------------------------------------------------------------------------*/
 
-/* Bulk-only data structures */
-
-/* Command Block Wrapper */
-struct fsg_bulk_cb_wrap {
-	__le32	Signature;		/* Contains 'USBC' */
-	u32	Tag;			/* Unique per command id */
-	__le32	DataTransferLength;	/* Size of the data */
-	u8	Flags;			/* Direction in bit 7 */
-	u8	Lun;			/* LUN (normally 0) */
-	u8	Length;			/* Of the CDB, <= MAX_COMMAND_SIZE */
-	u8	CDB[16];		/* Command Data Block */
-};
-
-#define USB_BULK_CB_WRAP_LEN	31
-#define USB_BULK_CB_SIG		0x43425355	/* Spells out USBC */
-#define USB_BULK_IN_FLAG	0x80
-
-/* Command Status Wrapper */
-struct bulk_cs_wrap {
-	__le32	Signature;		/* Should = 'USBS' */
-	u32	Tag;			/* Same as original command */
-	__le32	Residue;		/* Amount not transferred */
-	u8	Status;			/* See below */
-};
-
-#define USB_BULK_CS_WRAP_LEN	13
-#define USB_BULK_CS_SIG		0x53425355	/* Spells out 'USBS' */
-#define USB_STATUS_PASS		0
-#define USB_STATUS_FAIL		1
-#define USB_STATUS_PHASE_ERROR	2
-
-/* Bulk-only class specific requests */
-#define USB_BULK_RESET_REQUEST		0xff
-#define USB_BULK_GET_MAX_LUN_REQUEST	0xfe
-
-
 /* CBI Interrupt data structure */
 struct interrupt_data {
 	u8	bType;
diff --git a/drivers/usb/gadget/u_audio.c b/drivers/usb/gadget/u_uac1.c
similarity index 98%
rename from drivers/usb/gadget/u_audio.c
rename to drivers/usb/gadget/u_uac1.c
index 59ffe1e..af98989 100644
--- a/drivers/usb/gadget/u_audio.c
+++ b/drivers/usb/gadget/u_uac1.c
@@ -1,5 +1,5 @@
 /*
- * u_audio.c -- ALSA audio utilities for Gadget stack
+ * u_uac1.c -- ALSA audio utilities for Gadget stack
  *
  * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
  * Copyright (C) 2008 Analog Devices, Inc
@@ -17,7 +17,7 @@
 #include <linux/random.h>
 #include <linux/syscalls.h>
 
-#include "u_audio.h"
+#include "u_uac1.h"
 
 /*
  * This component encapsulates the ALSA devices for USB audio gadget
diff --git a/drivers/usb/gadget/u_audio.h b/drivers/usb/gadget/u_uac1.h
similarity index 94%
rename from drivers/usb/gadget/u_audio.h
rename to drivers/usb/gadget/u_uac1.h
index 08ffce3..18c2e72 100644
--- a/drivers/usb/gadget/u_audio.h
+++ b/drivers/usb/gadget/u_uac1.h
@@ -1,5 +1,5 @@
 /*
- * u_audio.h -- interface to USB gadget "ALSA AUDIO" utilities
+ * u_uac1.h -- interface to USB gadget "ALSA AUDIO" utilities
  *
  * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
  * Copyright (C) 2008 Analog Devices, Inc
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index 0b0d12c..56da49f 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -22,6 +22,7 @@
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/err.h>
+#include <linux/dma-mapping.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
@@ -49,6 +50,57 @@
 
 /* ------------------------------------------------------------------------- */
 
+int usb_gadget_map_request(struct usb_gadget *gadget,
+		struct usb_request *req, int is_in)
+{
+	if (req->length == 0)
+		return 0;
+
+	if (req->num_sgs) {
+		int     mapped;
+
+		mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs,
+				is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		if (mapped == 0) {
+			dev_err(&gadget->dev, "failed to map SGs\n");
+			return -EFAULT;
+		}
+
+		req->num_mapped_sgs = mapped;
+	} else {
+		req->dma = dma_map_single(&gadget->dev, req->buf, req->length,
+				is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
+		if (dma_mapping_error(&gadget->dev, req->dma)) {
+			dev_err(&gadget->dev, "failed to map buffer\n");
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_map_request);
+
+void usb_gadget_unmap_request(struct usb_gadget *gadget,
+		struct usb_request *req, int is_in)
+{
+	if (req->length == 0)
+		return;
+
+	if (req->num_mapped_sgs) {
+		dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs,
+				is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
+		req->num_mapped_sgs = 0;
+	} else {
+		dma_unmap_single(&gadget->dev, req->dma, req->length,
+				is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	}
+}
+EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
+
+/* ------------------------------------------------------------------------- */
+
 /**
  * usb_gadget_start - tells usb device controller to start up
  * @gadget: The gadget we want to get started
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 353cdd4..f788eb8 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -27,6 +27,10 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called xhci-hcd.
 
+config USB_XHCI_PLATFORM
+	tristate
+	depends on USB_XHCI_HCD
+
 config USB_XHCI_HCD_DEBUGGING
 	bool "Debugging for the xHCI host controller"
 	depends on USB_XHCI_HCD
@@ -196,7 +200,7 @@
 
 config USB_EHCI_MV
 	bool "EHCI support for Marvell on-chip controller"
-	depends on USB_EHCI_HCD
+	depends on USB_EHCI_HCD && (ARCH_PXA || ARCH_MMP)
 	select USB_EHCI_ROOT_HUB_TT
 	---help---
 	  Enables support for Marvell (including PXA and MMP series) on-chip
@@ -218,11 +222,15 @@
 	  support.
 
 config USB_EHCI_ATH79
-	bool "EHCI support for AR7XXX/AR9XXX SoCs"
+	bool "EHCI support for AR7XXX/AR9XXX SoCs (DEPRECATED)"
 	depends on USB_EHCI_HCD && (SOC_AR71XX || SOC_AR724X || SOC_AR913X || SOC_AR933X)
 	select USB_EHCI_ROOT_HUB_TT
+	select USB_EHCI_HCD_PLATFORM
 	default y
 	---help---
+	  This option is deprecated now and the driver was removed, use
+	  USB_EHCI_HCD_PLATFORM instead.
+
 	  Enables support for the built-in EHCI controller present
 	  on the Atheros AR7XXX/AR9XXX SoCs.
 
@@ -312,10 +320,14 @@
 	  OMAP3 and later chips.
 
 config USB_OHCI_ATH79
-	bool "USB OHCI support for the Atheros AR71XX/AR7240 SoCs"
+	bool "USB OHCI support for the Atheros AR71XX/AR7240 SoCs (DEPRECATED)"
 	depends on USB_OHCI_HCD && (SOC_AR71XX || SOC_AR724X)
+	select USB_OHCI_HCD_PLATFORM
 	default y
 	help
+	  This option is deprecated now and the driver was removed, use
+	  USB_OHCI_HCD_PLATFORM instead.
+
 	  Enables support for the built-in OHCI controller present on the
 	  Atheros AR71XX/AR7240 SoCs.
 
@@ -393,6 +405,26 @@
 	  Enable support for the CNS3XXX SOC's on-chip OHCI controller.
 	  It is needed for low-speed USB 1.0 device support.
 
+config USB_OHCI_HCD_PLATFORM
+	bool "Generic OHCI driver for a platform device"
+	depends on USB_OHCI_HCD && EXPERIMENTAL
+	default n
+	---help---
+	  Adds an OHCI host driver for a generic platform device, which
+	  provieds a memory space and an irq.
+
+	  If unsure, say N.
+
+config USB_EHCI_HCD_PLATFORM
+	bool "Generic EHCI driver for a platform device"
+	depends on USB_EHCI_HCD && EXPERIMENTAL
+	default n
+	---help---
+	  Adds an EHCI host driver for a generic platform device, which
+	  provieds a memory space and an irq.
+
+	  If unsure, say N.
+
 config USB_OHCI_BIG_ENDIAN_DESC
 	bool
 	depends on USB_OHCI_HCD
@@ -606,10 +638,3 @@
 config USB_OCTEON2_COMMON
 	bool
 	default y if USB_OCTEON_EHCI || USB_OCTEON_OHCI
-
-config USB_PXA168_EHCI
-	bool "Marvell PXA168 on-chip EHCI HCD support"
-	depends on USB_EHCI_HCD && ARCH_MMP
-	help
-	  Enable support for Marvell PXA168 SoC's on-chip EHCI
-	  host controller
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 7ca290f..0982bcc 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -15,6 +15,10 @@
 xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o
 xhci-hcd-$(CONFIG_PCI)	+= xhci-pci.o
 
+ifneq ($(CONFIG_USB_XHCI_PLATFORM), )
+	xhci-hcd-y		+= xhci-plat.o
+endif
+
 obj-$(CONFIG_USB_WHCI_HCD)	+= whci/
 
 obj-$(CONFIG_PCI)		+= pci-quirks.o
diff --git a/drivers/usb/host/ehci-ath79.c b/drivers/usb/host/ehci-ath79.c
deleted file mode 100644
index f1424f9..0000000
--- a/drivers/usb/host/ehci-ath79.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- *  Bus Glue for Atheros AR7XXX/AR9XXX built-in EHCI controller.
- *
- *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- *
- *  Parts of this file are based on Atheros' 2.6.15 BSP
- *	Copyright (C) 2007 Atheros Communications, Inc.
- *
- *  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/platform_device.h>
-
-enum {
-	EHCI_ATH79_IP_V1 = 0,
-	EHCI_ATH79_IP_V2,
-};
-
-static const struct platform_device_id ehci_ath79_id_table[] = {
-	{
-		.name		= "ar71xx-ehci",
-		.driver_data	= EHCI_ATH79_IP_V1,
-	},
-	{
-		.name		= "ar724x-ehci",
-		.driver_data	= EHCI_ATH79_IP_V2,
-	},
-	{
-		.name		= "ar913x-ehci",
-		.driver_data	= EHCI_ATH79_IP_V2,
-	},
-	{
-		.name		= "ar933x-ehci",
-		.driver_data	= EHCI_ATH79_IP_V2,
-	},
-	{
-		/* terminating entry */
-	},
-};
-
-MODULE_DEVICE_TABLE(platform, ehci_ath79_id_table);
-
-static int ehci_ath79_init(struct usb_hcd *hcd)
-{
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	struct platform_device *pdev = to_platform_device(hcd->self.controller);
-	const struct platform_device_id *id;
-	int ret;
-
-	id = platform_get_device_id(pdev);
-	if (!id) {
-		dev_err(hcd->self.controller, "missing device id\n");
-		return -EINVAL;
-	}
-
-	switch (id->driver_data) {
-	case EHCI_ATH79_IP_V1:
-		ehci->has_synopsys_hc_bug = 1;
-
-		ehci->caps = hcd->regs;
-		ehci->regs = hcd->regs +
-			HC_LENGTH(ehci,
-				  ehci_readl(ehci, &ehci->caps->hc_capbase));
-		break;
-
-	case EHCI_ATH79_IP_V2:
-		hcd->has_tt = 1;
-
-		ehci->caps = hcd->regs + 0x100;
-		ehci->regs = hcd->regs + 0x100 +
-			HC_LENGTH(ehci,
-				  ehci_readl(ehci, &ehci->caps->hc_capbase));
-		break;
-
-	default:
-		BUG();
-	}
-
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-	ehci->sbrn = 0x20;
-
-	ehci_reset(ehci);
-
-	ret = ehci_init(hcd);
-	if (ret)
-		return ret;
-
-	ehci_port_power(ehci, 0);
-
-	return 0;
-}
-
-static const struct hc_driver ehci_ath79_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "Atheros built-in EHCI controller",
-	.hcd_priv_size		= sizeof(struct ehci_hcd),
-	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
-
-	.reset			= ehci_ath79_init,
-	.start			= ehci_run,
-	.stop			= ehci_stop,
-	.shutdown		= ehci_shutdown,
-
-	.urb_enqueue		= ehci_urb_enqueue,
-	.urb_dequeue		= ehci_urb_dequeue,
-	.endpoint_disable	= ehci_endpoint_disable,
-	.endpoint_reset		= ehci_endpoint_reset,
-
-	.get_frame_number	= ehci_get_frame,
-
-	.hub_status_data	= ehci_hub_status_data,
-	.hub_control		= ehci_hub_control,
-
-	.relinquish_port	= ehci_relinquish_port,
-	.port_handed_over	= ehci_port_handed_over,
-
-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
-static int ehci_ath79_probe(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd;
-	struct resource *res;
-	int irq;
-	int ret;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dev_dbg(&pdev->dev, "no IRQ specified\n");
-		return -ENODEV;
-	}
-	irq = res->start;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_dbg(&pdev->dev, "no base address specified\n");
-		return -ENODEV;
-	}
-
-	hcd = usb_create_hcd(&ehci_ath79_hc_driver, &pdev->dev,
-			     dev_name(&pdev->dev));
-	if (!hcd)
-		return -ENOMEM;
-
-	hcd->rsrc_start	= res->start;
-	hcd->rsrc_len	= resource_size(res);
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		dev_dbg(&pdev->dev, "controller already in use\n");
-		ret = -EBUSY;
-		goto err_put_hcd;
-	}
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		dev_dbg(&pdev->dev, "error mapping memory\n");
-		ret = -EFAULT;
-		goto err_release_region;
-	}
-
-	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
-	if (ret)
-		goto err_iounmap;
-
-	return 0;
-
-err_iounmap:
-	iounmap(hcd->regs);
-
-err_release_region:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err_put_hcd:
-	usb_put_hcd(hcd);
-	return ret;
-}
-
-static int ehci_ath79_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-
-	return 0;
-}
-
-static struct platform_driver ehci_ath79_driver = {
-	.probe		= ehci_ath79_probe,
-	.remove		= ehci_ath79_remove,
-	.id_table	= ehci_ath79_id_table,
-	.driver = {
-		.owner	= THIS_MODULE,
-		.name	= "ath79-ehci",
-	}
-};
-
-MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ath79-ehci");
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index d6d74d2..fd9109d 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -107,7 +107,7 @@
 			HCC_PER_PORT_CHANGE_EVENT(params) ? " ppce" : "",
 			HCC_HW_PREFETCH(params) ? " hw prefetch" : "",
 			HCC_32FRAME_PERIODIC_LIST(params) ?
-				" 32 peridic list" : "");
+				" 32 periodic list" : "");
 	}
 }
 #else
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index b556a72..3e73451 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -142,12 +142,12 @@
 	if (pdata->operating_mode == FSL_USB2_DR_OTG) {
 		struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 
-		ehci->transceiver = otg_get_transceiver();
+		ehci->transceiver = usb_get_transceiver();
 		dev_dbg(&pdev->dev, "hcd=0x%p  ehci=0x%p, transceiver=0x%p\n",
 			hcd, ehci, ehci->transceiver);
 
 		if (ehci->transceiver) {
-			retval = otg_set_host(ehci->transceiver,
+			retval = otg_set_host(ehci->transceiver->otg,
 					      &ehci_to_hcd(ehci)->self);
 			if (retval) {
 				if (ehci->transceiver)
@@ -194,7 +194,7 @@
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 
 	if (ehci->transceiver) {
-		otg_set_host(ehci->transceiver, NULL);
+		otg_set_host(ehci->transceiver->otg, NULL);
 		put_device(ehci->transceiver->dev);
 	}
 
@@ -216,6 +216,8 @@
 			       unsigned int port_offset)
 {
 	u32 portsc;
+	struct usb_hcd *hcd = ehci_to_hcd(ehci);
+	void __iomem *non_ehci = hcd->regs;
 
 	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
 	portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
@@ -231,6 +233,8 @@
 		portsc |= PORT_PTS_PTW;
 		/* fall through */
 	case FSL_USB2_PHY_UTMI:
+		/* enable UTMI PHY */
+		setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN);
 		portsc |= PORT_PTS_UTMI;
 		break;
 	case FSL_USB2_PHY_NONE:
@@ -252,22 +256,19 @@
 	if (pdata->have_sysif_regs) {
 		temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
 		out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
-		out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
+
+		/*
+		* Turn on cache snooping hardware, since some PowerPC platforms
+		* wholly rely on hardware to deal with cache coherent
+		*/
+
+		/* Setup Snooping for all the 4GB space */
+		/* SNOOP1 starts from 0x0, size 2G */
+		out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB);
+		/* SNOOP2 starts from 0x80000000, size 2G */
+		out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
 	}
 
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
-	/*
-	 * Turn on cache snooping hardware, since some PowerPC platforms
-	 * wholly rely on hardware to deal with cache coherent
-	 */
-
-	/* Setup Snooping for all the 4GB space */
-	/* SNOOP1 starts from 0x0, size 2G */
-	out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB);
-	/* SNOOP2 starts from 0x80000000, size 2G */
-	out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
-#endif
-
 	if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
 			(pdata->operating_mode == FSL_USB2_DR_OTG))
 		ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
@@ -316,7 +317,9 @@
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	int retval;
 	struct fsl_usb2_platform_data *pdata;
+	struct device *dev;
 
+	dev = hcd->self.controller;
 	pdata = hcd->self.controller->platform_data;
 	ehci->big_endian_desc = pdata->big_endian_desc;
 	ehci->big_endian_mmio = pdata->big_endian_mmio;
@@ -346,6 +349,16 @@
 
 	ehci_reset(ehci);
 
+	if (of_device_is_compatible(dev->parent->of_node,
+				    "fsl,mpc5121-usb2-dr")) {
+		/*
+		 * set SBUSCFG:AHBBRST so that control msgs don't
+		 * fail when doing heavy PATA writes.
+		 */
+		ehci_writel(ehci, SBUSCFG_INCR8,
+			    hcd->regs + FSL_SOC_USB_SBUSCFG);
+	}
+
 	retval = ehci_fsl_reinit(ehci);
 	return retval;
 }
@@ -469,6 +482,8 @@
 	ehci_writel(ehci, ISIPHYCTRL_PXE | ISIPHYCTRL_PHYE,
 		    hcd->regs + FSL_SOC_USB_ISIPHYCTRL);
 
+	ehci_writel(ehci, SBUSCFG_INCR8, hcd->regs + FSL_SOC_USB_SBUSCFG);
+
 	/* restore EHCI registers */
 	ehci_writel(ehci, pdata->pm_command, &ehci->regs->command);
 	ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable);
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index 4918062..863fb0c 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -19,6 +19,8 @@
 #define _EHCI_FSL_H
 
 /* offsets for the non-ehci registers in the FSL SOC USB controller */
+#define FSL_SOC_USB_SBUSCFG	0x90
+#define SBUSCFG_INCR8		0x02	/* INCR8, specified */
 #define FSL_SOC_USB_ULPIVP	0x170
 #define FSL_SOC_USB_PORTSC1	0x184
 #define PORT_PTS_MSK		(3<<30)
@@ -45,5 +47,7 @@
 #define FSL_SOC_USB_PRICTRL	0x40c	/* NOTE: big-endian */
 #define FSL_SOC_USB_SICTRL	0x410	/* NOTE: big-endian */
 #define FSL_SOC_USB_CTRL	0x500	/* NOTE: big-endian */
+#define CTRL_UTMI_PHY_EN	(1<<9)
+#define CTRL_PHY_CLK_VALID	(1 << 17)
 #define SNOOP_SIZE_2GB		0x1e
 #endif				/* _EHCI_FSL_H */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index a007a9f..aede637 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1351,21 +1351,11 @@
 #define PLATFORM_DRIVER		s5p_ehci_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_ATH79
-#include "ehci-ath79.c"
-#define PLATFORM_DRIVER		ehci_ath79_driver
-#endif
-
 #ifdef CONFIG_SPARC_LEON
 #include "ehci-grlib.c"
 #define PLATFORM_DRIVER		ehci_grlib_driver
 #endif
 
-#ifdef CONFIG_USB_PXA168_EHCI
-#include "ehci-pxa168.c"
-#define PLATFORM_DRIVER		ehci_pxa168_driver
-#endif
-
 #ifdef CONFIG_CPU_XLR
 #include "ehci-xls.c"
 #define PLATFORM_DRIVER		ehci_xls_driver
@@ -1376,6 +1366,16 @@
 #define        PLATFORM_DRIVER         ehci_mv_driver
 #endif
 
+#ifdef CONFIG_MACH_LOONGSON1
+#include "ehci-ls1x.c"
+#define PLATFORM_DRIVER		ehci_ls1x_driver
+#endif
+
+#ifdef CONFIG_USB_EHCI_HCD_PLATFORM
+#include "ehci-platform.c"
+#define PLATFORM_DRIVER		ehci_platform_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
     !defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 77bbb23..256fbd4 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -107,7 +107,7 @@
 	ehci->owned_ports = 0;
 }
 
-static int ehci_port_change(struct ehci_hcd *ehci)
+static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci)
 {
 	int i = HCS_N_PORTS(ehci->hcs_params);
 
@@ -727,7 +727,7 @@
 #ifdef CONFIG_USB_OTG
 			if ((hcd->self.otg_port == (wIndex + 1))
 			    && hcd->self.b_hnp_enable) {
-				otg_start_hnp(ehci->transceiver);
+				otg_start_hnp(ehci->transceiver->otg);
 				break;
 			}
 #endif
@@ -1076,7 +1076,8 @@
 	return retval;
 }
 
-static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
+static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
+		int portnum)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 
@@ -1085,7 +1086,8 @@
 	set_owner(ehci, --portnum, PORT_OWNER);
 }
 
-static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum)
+static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd,
+		int portnum)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	u32 __iomem		*reg;
diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c
new file mode 100644
index 0000000..a283e59
--- /dev/null
+++ b/drivers/usb/host/ehci-ls1x.c
@@ -0,0 +1,159 @@
+/*
+ *  Bus Glue for Loongson LS1X built-in EHCI controller.
+ *
+ *  Copyright (c) 2012 Zhang, Keguang <keguang.zhang@gmail.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/platform_device.h>
+
+static int ehci_ls1x_reset(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int ret;
+
+	ehci->caps = hcd->regs;
+
+	ret = ehci_setup(hcd);
+	if (ret)
+		return ret;
+
+	ehci_port_power(ehci, 0);
+
+	return 0;
+}
+
+static const struct hc_driver ehci_ls1x_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "LOONGSON1 EHCI",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq			= ehci_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset			= ehci_ls1x_reset,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number	= ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+};
+
+static int ehci_hcd_ls1x_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res;
+	int irq;
+	int ret;
+
+	pr_debug("initializing loongson1 ehci USB Controller\n");
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Found HC with no IRQ. Check %s setup!\n",
+			dev_name(&pdev->dev));
+		return -ENODEV;
+	}
+	irq = res->start;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Found HC with no register addr. Check %s setup!\n",
+			dev_name(&pdev->dev));
+		return -ENODEV;
+	}
+
+	hcd = usb_create_hcd(&ehci_ls1x_hc_driver, &pdev->dev,
+				dev_name(&pdev->dev));
+	if (!hcd)
+		return -ENOMEM;
+	hcd->rsrc_start	= res->start;
+	hcd->rsrc_len	= resource_size(res);
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		dev_dbg(&pdev->dev, "controller already in use\n");
+		ret = -EBUSY;
+		goto err_put_hcd;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (hcd->regs == NULL) {
+		dev_dbg(&pdev->dev, "error mapping memory\n");
+		ret = -EFAULT;
+		goto err_release_region;
+	}
+
+	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+	if (ret)
+		goto err_iounmap;
+
+	return ret;
+
+err_iounmap:
+	iounmap(hcd->regs);
+err_release_region:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_put_hcd:
+	usb_put_hcd(hcd);
+	return ret;
+}
+
+static int ehci_hcd_ls1x_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+static struct platform_driver ehci_ls1x_driver = {
+	.probe = ehci_hcd_ls1x_probe,
+	.remove = ehci_hcd_ls1x_remove,
+	.shutdown = usb_hcd_platform_shutdown,
+	.driver = {
+		.name = "ls1x-ehci",
+		.owner	= THIS_MODULE,
+	},
+};
+
+MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ls1x-ehci");
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 592d5f7..9803a55 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -32,7 +32,7 @@
 
 #define MSM_USB_BASE (hcd->regs)
 
-static struct otg_transceiver *otg;
+static struct usb_phy *phy;
 
 static int ehci_msm_reset(struct usb_hcd *hcd)
 {
@@ -145,14 +145,14 @@
 	 * powering up VBUS, mapping of registers address space and power
 	 * management.
 	 */
-	otg = otg_get_transceiver();
-	if (!otg) {
+	phy = usb_get_transceiver();
+	if (!phy) {
 		dev_err(&pdev->dev, "unable to find transceiver\n");
 		ret = -ENODEV;
 		goto unmap;
 	}
 
-	ret = otg_set_host(otg, &hcd->self);
+	ret = otg_set_host(phy->otg, &hcd->self);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "unable to register with transceiver\n");
 		goto put_transceiver;
@@ -169,7 +169,7 @@
 	return 0;
 
 put_transceiver:
-	otg_put_transceiver(otg);
+	usb_put_transceiver(phy);
 unmap:
 	iounmap(hcd->regs);
 put_hcd:
@@ -186,8 +186,8 @@
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 
-	otg_set_host(otg, NULL);
-	otg_put_transceiver(otg);
+	otg_set_host(phy->otg, NULL);
+	usb_put_transceiver(phy);
 
 	usb_put_hcd(hcd);
 
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index 52a604f..a936bbc 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -28,7 +28,7 @@
 	void __iomem *cap_regs;
 	void __iomem *op_regs;
 
-	struct otg_transceiver *otg;
+	struct usb_phy *otg;
 
 	struct mv_usb_platform_data *pdata;
 
@@ -253,7 +253,7 @@
 	ehci_mv->mode = pdata->mode;
 	if (ehci_mv->mode == MV_USB_MODE_OTG) {
 #ifdef CONFIG_USB_OTG_UTILS
-		ehci_mv->otg = otg_get_transceiver();
+		ehci_mv->otg = usb_get_transceiver();
 		if (!ehci_mv->otg) {
 			dev_err(&pdev->dev,
 				"unable to find transceiver\n");
@@ -261,7 +261,7 @@
 			goto err_disable_clk;
 		}
 
-		retval = otg_set_host(ehci_mv->otg, &hcd->self);
+		retval = otg_set_host(ehci_mv->otg->otg, &hcd->self);
 		if (retval < 0) {
 			dev_err(&pdev->dev,
 				"unable to register with transceiver\n");
@@ -303,7 +303,7 @@
 #ifdef CONFIG_USB_OTG_UTILS
 err_put_transceiver:
 	if (ehci_mv->otg)
-		otg_put_transceiver(ehci_mv->otg);
+		usb_put_transceiver(ehci_mv->otg);
 #endif
 err_disable_clk:
 	mv_ehci_disable(ehci_mv);
@@ -332,8 +332,8 @@
 		usb_remove_hcd(hcd);
 
 	if (ehci_mv->otg) {
-		otg_set_host(ehci_mv->otg, NULL);
-		otg_put_transceiver(ehci_mv->otg);
+		otg_set_host(ehci_mv->otg->otg, NULL);
+		usb_put_transceiver(ehci_mv->otg);
 	}
 
 	if (ehci_mv->mode == MV_USB_MODE_HOST) {
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index 55978fc..a797d51 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -220,13 +220,13 @@
 	/* Initialize the transceiver */
 	if (pdata->otg) {
 		pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
-		ret = otg_init(pdata->otg);
+		ret = usb_phy_init(pdata->otg);
 		if (ret) {
 			dev_err(dev, "unable to init transceiver, probably missing\n");
 			ret = -ENODEV;
 			goto err_add;
 		}
-		ret = otg_set_vbus(pdata->otg, 1);
+		ret = otg_set_vbus(pdata->otg->otg, 1);
 		if (ret) {
 			dev_err(dev, "unable to enable vbus on transceiver\n");
 			goto err_add;
@@ -247,9 +247,11 @@
 		 * It's in violation of USB specs
 		 */
 		if (machine_is_mx51_efikamx() || machine_is_mx51_efikasb()) {
-			flags = otg_io_read(pdata->otg, ULPI_OTG_CTRL);
+			flags = usb_phy_io_read(pdata->otg,
+							ULPI_OTG_CTRL);
 			flags |= ULPI_OTG_CTRL_CHRGVBUS;
-			ret = otg_io_write(pdata->otg, flags, ULPI_OTG_CTRL);
+			ret = usb_phy_io_write(pdata->otg, flags,
+							ULPI_OTG_CTRL);
 			if (ret) {
 				dev_err(dev, "unable to set CHRVBUS\n");
 				goto err_add;
@@ -297,7 +299,7 @@
 		pdata->exit(pdev);
 
 	if (pdata->otg)
-		otg_shutdown(pdata->otg);
+		usb_phy_shutdown(pdata->otg);
 
 	usb_remove_hcd(hcd);
 	iounmap(hcd->regs);
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
new file mode 100644
index 0000000..d238b4e2
--- /dev/null
+++ b/drivers/usb/host/ehci-platform.c
@@ -0,0 +1,198 @@
+/*
+ * Generic platform ehci driver
+ *
+ * Copyright 2007 Steven Brown <sbrown@cortland.com>
+ * Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Derived from the ohci-ssb driver
+ * Copyright 2007 Michael Buesch <m@bues.ch>
+ *
+ * Derived from the EHCI-PCI driver
+ * Copyright (c) 2000-2004 by David Brownell
+ *
+ * Derived from the ohci-pci driver
+ * Copyright 1999 Roman Weissgaerber
+ * Copyright 2000-2002 David Brownell
+ * Copyright 1999 Linus Torvalds
+ * Copyright 1999 Gregory P. Smith
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+#include <linux/platform_device.h>
+#include <linux/usb/ehci_pdriver.h>
+
+static int ehci_platform_reset(struct usb_hcd *hcd)
+{
+	struct platform_device *pdev = to_platform_device(hcd->self.controller);
+	struct usb_ehci_pdata *pdata = pdev->dev.platform_data;
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval;
+
+	hcd->has_tt = pdata->has_tt;
+	ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
+	ehci->big_endian_desc = pdata->big_endian_desc;
+	ehci->big_endian_mmio = pdata->big_endian_mmio;
+
+	ehci->caps = hcd->regs + pdata->caps_offset;
+	retval = ehci_setup(hcd);
+	if (retval)
+		return retval;
+
+	if (pdata->port_power_on)
+		ehci_port_power(ehci, 1);
+	if (pdata->port_power_off)
+		ehci_port_power(ehci, 0);
+
+	return 0;
+}
+
+static const struct hc_driver ehci_platform_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "Generic Platform EHCI Controller",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+
+	.irq			= ehci_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+
+	.reset			= ehci_platform_reset,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+
+	.get_frame_number	= ehci_get_frame,
+
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+#if defined(CONFIG_PM)
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+#endif
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+
+	.update_device		= ehci_update_device,
+
+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+};
+
+static int __devinit ehci_platform_probe(struct platform_device *dev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res_mem;
+	int irq;
+	int err = -ENOMEM;
+
+	BUG_ON(!dev->dev.platform_data);
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		pr_err("no irq provieded");
+		return irq;
+	}
+	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res_mem) {
+		pr_err("no memory recourse provieded");
+		return -ENXIO;
+	}
+
+	hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
+			     dev_name(&dev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	hcd->rsrc_start = res_mem->start;
+	hcd->rsrc_len = resource_size(res_mem);
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		pr_err("controller already in use");
+		err = -EBUSY;
+		goto err_put_hcd;
+	}
+
+	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs)
+		goto err_release_region;
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (err)
+		goto err_iounmap;
+
+	platform_set_drvdata(dev, hcd);
+
+	return err;
+
+err_iounmap:
+	iounmap(hcd->regs);
+err_release_region:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_put_hcd:
+	usb_put_hcd(hcd);
+	return err;
+}
+
+static int __devexit ehci_platform_remove(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	platform_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int ehci_platform_suspend(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	bool wakeup = device_may_wakeup(dev);
+
+	ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), wakeup);
+	return 0;
+}
+
+static int ehci_platform_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+	ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
+	return 0;
+}
+
+#else /* !CONFIG_PM */
+#define ehci_platform_suspend	NULL
+#define ehci_platform_resume	NULL
+#endif /* CONFIG_PM */
+
+static const struct platform_device_id ehci_platform_table[] = {
+	{ "ehci-platform", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, ehci_platform_table);
+
+static const struct dev_pm_ops ehci_platform_pm_ops = {
+	.suspend	= ehci_platform_suspend,
+	.resume		= ehci_platform_resume,
+};
+
+static struct platform_driver ehci_platform_driver = {
+	.id_table	= ehci_platform_table,
+	.probe		= ehci_platform_probe,
+	.remove		= __devexit_p(ehci_platform_remove),
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "ehci-platform",
+		.pm	= &ehci_platform_pm_ops,
+	}
+};
diff --git a/drivers/usb/host/ehci-pxa168.c b/drivers/usb/host/ehci-pxa168.c
deleted file mode 100644
index 8d0e7a2..0000000
--- a/drivers/usb/host/ehci-pxa168.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * drivers/usb/host/ehci-pxa168.c
- *
- * Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
- *
- * Based on drivers/usb/host/ehci-orion.c
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <mach/pxa168.h>
-
-#define USB_PHY_CTRL_REG 0x4
-#define USB_PHY_PLL_REG  0x8
-#define USB_PHY_TX_REG   0xc
-
-#define FBDIV_SHIFT      4
-
-#define ICP_SHIFT        12
-#define ICP_15            2
-#define ICP_20            3
-#define ICP_25            4
-
-#define KVCO_SHIFT       15
-
-#define PLLCALI12_SHIFT  25
-#define CALI12_VDD        0
-#define CALI12_09         1
-#define CALI12_10         2
-#define CALI12_11         3
-
-#define PLLVDD12_SHIFT   27
-#define VDD12_VDD         0
-#define VDD12_10          1
-#define VDD12_11          2
-#define VDD12_12          3
-
-#define PLLVDD18_SHIFT   29
-#define VDD18_19          0
-#define VDD18_20          1
-#define VDD18_21          2
-#define VDD18_22          3
-
-
-#define PLL_READY        (1 << 23)
-#define VCOCAL_START     (1 << 21)
-#define REG_RCAL_START   (1 << 12)
-
-struct pxa168_usb_drv_data {
-	struct ehci_hcd ehci;
-	struct clk	*pxa168_usb_clk;
-	struct resource	*usb_phy_res;
-	void __iomem	*usb_phy_reg_base;
-};
-
-static int ehci_pxa168_setup(struct usb_hcd *hcd)
-{
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int retval;
-
-	ehci_reset(ehci);
-	retval = ehci_halt(ehci);
-	if (retval)
-		return retval;
-
-	/*
-	 * data structure init
-	 */
-	retval = ehci_init(hcd);
-	if (retval)
-		return retval;
-
-	hcd->has_tt = 1;
-
-	ehci_port_power(ehci, 0);
-
-	return retval;
-}
-
-static const struct hc_driver ehci_pxa168_hc_driver = {
-	.description = hcd_name,
-	.product_desc = "Marvell PXA168 EHCI",
-	.hcd_priv_size = sizeof(struct pxa168_usb_drv_data),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq = ehci_irq,
-	.flags = HCD_MEMORY | HCD_USB2,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset = ehci_pxa168_setup,
-	.start = ehci_run,
-	.stop = ehci_stop,
-	.shutdown = ehci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue = ehci_urb_enqueue,
-	.urb_dequeue = ehci_urb_dequeue,
-	.endpoint_disable = ehci_endpoint_disable,
-	.endpoint_reset = ehci_endpoint_reset,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number = ehci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data = ehci_hub_status_data,
-	.hub_control = ehci_hub_control,
-	.bus_suspend = ehci_bus_suspend,
-	.bus_resume = ehci_bus_resume,
-	.relinquish_port = ehci_relinquish_port,
-	.port_handed_over = ehci_port_handed_over,
-
-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
-static int pxa168_usb_phy_init(struct platform_device *pdev)
-{
-	struct resource *res;
-	void __iomem *usb_phy_reg_base;
-	struct pxa168_usb_pdata *pdata;
-	struct pxa168_usb_drv_data *drv_data;
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-	unsigned long reg_val;
-	int pll_retry_cont = 10000, err = 0;
-
-	drv_data = (struct pxa168_usb_drv_data *)hcd->hcd_priv;
-	pdata = (struct pxa168_usb_pdata *)pdev->dev.platform_data;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (!res) {
-		dev_err(&pdev->dev,
-			"Found HC with no PHY register addr. Check %s setup!\n",
-			dev_name(&pdev->dev));
-		return -ENODEV;
-	}
-
-	if (!request_mem_region(res->start, resource_size(res),
-				ehci_pxa168_hc_driver.description)) {
-		dev_dbg(&pdev->dev, "controller already in use\n");
-		return -EBUSY;
-	}
-
-	usb_phy_reg_base = ioremap(res->start, resource_size(res));
-	if (usb_phy_reg_base == NULL) {
-		dev_dbg(&pdev->dev, "error mapping memory\n");
-		err = -EFAULT;
-		goto err1;
-	}
-	drv_data->usb_phy_reg_base = usb_phy_reg_base;
-	drv_data->usb_phy_res = res;
-
-	/* If someone wants to init USB phy in board specific way */
-	if (pdata && pdata->phy_init)
-		return pdata->phy_init(usb_phy_reg_base);
-
-	/* Power up the PHY and PLL */
-	writel(readl(usb_phy_reg_base + USB_PHY_CTRL_REG) | 0x3,
-		usb_phy_reg_base + USB_PHY_CTRL_REG);
-
-	/* Configure PHY PLL */
-	reg_val = readl(usb_phy_reg_base + USB_PHY_PLL_REG) & ~(0x7e03ffff);
-	reg_val |= (VDD18_22 << PLLVDD18_SHIFT | VDD12_12 << PLLVDD12_SHIFT |
-		CALI12_11 << PLLCALI12_SHIFT | 3 << KVCO_SHIFT |
-		ICP_15 << ICP_SHIFT | 0xee << FBDIV_SHIFT | 0xb);
-	writel(reg_val, usb_phy_reg_base + USB_PHY_PLL_REG);
-
-	/* Make sure PHY PLL is ready */
-	while (!(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & PLL_READY)) {
-		if (!(pll_retry_cont--)) {
-			dev_dbg(&pdev->dev, "USB PHY PLL not ready\n");
-			err = -EIO;
-			goto err2;
-		}
-	}
-
-	/* Toggle VCOCAL_START bit of U2PLL for PLL calibration */
-	udelay(200);
-	writel(readl(usb_phy_reg_base + USB_PHY_PLL_REG) | VCOCAL_START,
-		usb_phy_reg_base + USB_PHY_PLL_REG);
-	udelay(40);
-	writel(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & ~VCOCAL_START,
-		usb_phy_reg_base + USB_PHY_PLL_REG);
-
-	/* Toggle REG_RCAL_START bit of U2PTX for impedance calibration */
-	udelay(400);
-	writel(readl(usb_phy_reg_base + USB_PHY_TX_REG) | REG_RCAL_START,
-		usb_phy_reg_base + USB_PHY_TX_REG);
-	udelay(40);
-	writel(readl(usb_phy_reg_base + USB_PHY_TX_REG) & ~REG_RCAL_START,
-		usb_phy_reg_base + USB_PHY_TX_REG);
-
-	/* Make sure PHY PLL is ready again */
-	pll_retry_cont = 0;
-	while (!(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & PLL_READY)) {
-		if (!(pll_retry_cont--)) {
-			dev_dbg(&pdev->dev, "USB PHY PLL not ready\n");
-			err = -EIO;
-			goto err2;
-		}
-	}
-
-	return 0;
-err2:
-	iounmap(usb_phy_reg_base);
-err1:
-	release_mem_region(res->start, resource_size(res));
-	return err;
-}
-
-static int __devinit ehci_pxa168_drv_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	struct usb_hcd *hcd;
-	struct ehci_hcd *ehci;
-	struct pxa168_usb_drv_data *drv_data;
-	void __iomem *regs;
-	int irq, err = 0;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	pr_debug("Initializing pxa168-SoC USB Host Controller\n");
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0) {
-		dev_err(&pdev->dev,
-			"Found HC with no IRQ. Check %s setup!\n",
-			dev_name(&pdev->dev));
-		err = -ENODEV;
-		goto err1;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev,
-			"Found HC with no register addr. Check %s setup!\n",
-			dev_name(&pdev->dev));
-		err = -ENODEV;
-		goto err1;
-	}
-
-	if (!request_mem_region(res->start, resource_size(res),
-				ehci_pxa168_hc_driver.description)) {
-		dev_dbg(&pdev->dev, "controller already in use\n");
-		err = -EBUSY;
-		goto err1;
-	}
-
-	regs = ioremap(res->start, resource_size(res));
-	if (regs == NULL) {
-		dev_dbg(&pdev->dev, "error mapping memory\n");
-		err = -EFAULT;
-		goto err2;
-	}
-
-	hcd = usb_create_hcd(&ehci_pxa168_hc_driver,
-			&pdev->dev, dev_name(&pdev->dev));
-	if (!hcd) {
-		err = -ENOMEM;
-		goto err3;
-	}
-
-	drv_data = (struct pxa168_usb_drv_data *)hcd->hcd_priv;
-
-	/* Enable USB clock */
-	drv_data->pxa168_usb_clk = clk_get(&pdev->dev, "PXA168-USBCLK");
-	if (IS_ERR(drv_data->pxa168_usb_clk)) {
-		dev_err(&pdev->dev, "Couldn't get USB clock\n");
-		err = PTR_ERR(drv_data->pxa168_usb_clk);
-		goto err4;
-	}
-	clk_enable(drv_data->pxa168_usb_clk);
-
-	err = pxa168_usb_phy_init(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "USB PHY initialization failed\n");
-		goto err5;
-	}
-
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-	hcd->regs = regs;
-
-	ehci = hcd_to_ehci(hcd);
-	ehci->caps = hcd->regs + 0x100;
-	ehci->regs = hcd->regs + 0x100 +
-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-	hcd->has_tt = 1;
-	ehci->sbrn = 0x20;
-
-	err = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED);
-	if (err)
-		goto err5;
-
-	return 0;
-
-err5:
-	clk_disable(drv_data->pxa168_usb_clk);
-	clk_put(drv_data->pxa168_usb_clk);
-err4:
-	usb_put_hcd(hcd);
-err3:
-	iounmap(regs);
-err2:
-	release_mem_region(res->start, resource_size(res));
-err1:
-	dev_err(&pdev->dev, "init %s fail, %d\n",
-		dev_name(&pdev->dev), err);
-
-	return err;
-}
-
-static int __exit ehci_pxa168_drv_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-	struct pxa168_usb_drv_data *drv_data =
-		(struct pxa168_usb_drv_data *)hcd->hcd_priv;
-
-	usb_remove_hcd(hcd);
-
-	/* Power down PHY & PLL */
-	writel(readl(drv_data->usb_phy_reg_base + USB_PHY_CTRL_REG) & (~0x3),
-		drv_data->usb_phy_reg_base + USB_PHY_CTRL_REG);
-
-	clk_disable(drv_data->pxa168_usb_clk);
-	clk_put(drv_data->pxa168_usb_clk);
-
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-
-	iounmap(drv_data->usb_phy_reg_base);
-	release_mem_region(drv_data->usb_phy_res->start,
-			resource_size(drv_data->usb_phy_res));
-
-	usb_put_hcd(hcd);
-
-	return 0;
-}
-
-MODULE_ALIAS("platform:pxa168-ehci");
-
-static struct platform_driver ehci_pxa168_driver = {
-	.probe		= ehci_pxa168_drv_probe,
-	.remove		= __exit_p(ehci_pxa168_drv_remove),
-	.shutdown	= usb_hcd_platform_shutdown,
-	.driver.name	= "pxa168-ehci",
-};
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
index 293f741..f098e2a 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-s5p.c
@@ -17,6 +17,15 @@
 #include <plat/ehci.h>
 #include <plat/usb-phy.h>
 
+#define EHCI_INSNREG00(base)			(base + 0x90)
+#define EHCI_INSNREG00_ENA_INCR16		(0x1 << 25)
+#define EHCI_INSNREG00_ENA_INCR8		(0x1 << 24)
+#define EHCI_INSNREG00_ENA_INCR4		(0x1 << 23)
+#define EHCI_INSNREG00_ENA_INCRX_ALIGN		(0x1 << 22)
+#define EHCI_INSNREG00_ENABLE_DMA_BURST	\
+	(EHCI_INSNREG00_ENA_INCR16 | EHCI_INSNREG00_ENA_INCR8 |	\
+	 EHCI_INSNREG00_ENA_INCR4 | EHCI_INSNREG00_ENA_INCRX_ALIGN)
+
 struct s5p_ehci_hcd {
 	struct device *dev;
 	struct usb_hcd *hcd;
@@ -128,6 +137,9 @@
 	ehci->regs = hcd->regs +
 		HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
 
+	/* DMA burst Enable */
+	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
+
 	dbg_hcs_params(ehci, "reset");
 	dbg_hcc_params(ehci, "reset");
 
@@ -234,6 +246,9 @@
 	if (pdata && pdata->phy_init)
 		pdata->phy_init(pdev, S5P_USB_PHY_HOST);
 
+	/* DMA burst Enable */
+	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
+
 	if (time_before(jiffies, ehci->next_statechange))
 		msleep(100);
 
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index b115b0b..6e92855 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -11,8 +11,10 @@
 * more details.
 */
 
-#include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
 
 struct spear_ehci {
 	struct ehci_hcd ehci;
@@ -90,6 +92,82 @@
 	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 
+#ifdef CONFIG_PM
+static int ehci_spear_drv_suspend(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	unsigned long flags;
+	int rc = 0;
+
+	if (time_before(jiffies, ehci->next_statechange))
+		msleep(10);
+
+	/*
+	 * Root hub was already suspended. Disable irq emission and mark HW
+	 * unaccessible. The PM and USB cores make sure that the root hub is
+	 * either suspended or stopped.
+	 */
+	spin_lock_irqsave(&ehci->lock, flags);
+	ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
+	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+	ehci_readl(ehci, &ehci->regs->intr_enable);
+	spin_unlock_irqrestore(&ehci->lock, flags);
+
+	return rc;
+}
+
+static int ehci_spear_drv_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+	if (time_before(jiffies, ehci->next_statechange))
+		msleep(100);
+
+	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+		int mask = INTR_MASK;
+
+		ehci_prepare_ports_for_controller_resume(ehci);
+
+		if (!hcd->self.root_hub->do_remote_wakeup)
+			mask &= ~STS_PCD;
+
+		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+		ehci_readl(ehci, &ehci->regs->intr_enable);
+		return 0;
+	}
+
+	usb_root_hub_lost_power(hcd->self.root_hub);
+
+	/*
+	 * Else reset, to cope with power loss or flush-to-storage style
+	 * "resume" having let BIOS kick in during reboot.
+	 */
+	ehci_halt(ehci);
+	ehci_reset(ehci);
+
+	/* emptying the schedule aborts any urbs */
+	spin_lock_irq(&ehci->lock);
+	if (ehci->reclaim)
+		end_unlink_async(ehci);
+
+	ehci_work(ehci);
+	spin_unlock_irq(&ehci->lock);
+
+	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+
+	/* here we "know" root ports should always stay powered */
+	ehci_port_power(ehci, 1);
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend,
+		ehci_spear_drv_resume);
+
 static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd ;
@@ -205,7 +283,8 @@
 	.shutdown	= usb_hcd_platform_shutdown,
 	.driver		= {
 		.name = "spear-ehci",
-		.bus = &platform_bus_type
+		.bus = &platform_bus_type,
+		.pm = &ehci_spear_pm_ops,
 	}
 };
 
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index dbc7fe8..3de48a2 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -35,7 +35,7 @@
 	struct tegra_usb_phy *phy;
 	struct clk *clk;
 	struct clk *emc_clk;
-	struct otg_transceiver *transceiver;
+	struct usb_phy *transceiver;
 	int host_resumed;
 	int bus_suspended;
 	int port_resuming;
@@ -733,9 +733,9 @@
 
 #ifdef CONFIG_USB_OTG_UTILS
 	if (pdata->operating_mode == TEGRA_USB_OTG) {
-		tegra->transceiver = otg_get_transceiver();
+		tegra->transceiver = usb_get_transceiver();
 		if (tegra->transceiver)
-			otg_set_host(tegra->transceiver, &hcd->self);
+			otg_set_host(tegra->transceiver->otg, &hcd->self);
 	}
 #endif
 
@@ -750,8 +750,8 @@
 fail:
 #ifdef CONFIG_USB_OTG_UTILS
 	if (tegra->transceiver) {
-		otg_set_host(tegra->transceiver, NULL);
-		otg_put_transceiver(tegra->transceiver);
+		otg_set_host(tegra->transceiver->otg, NULL);
+		usb_put_transceiver(tegra->transceiver);
 	}
 #endif
 	tegra_usb_phy_close(tegra->phy);
@@ -808,8 +808,8 @@
 
 #ifdef CONFIG_USB_OTG_UTILS
 	if (tegra->transceiver) {
-		otg_set_host(tegra->transceiver, NULL);
-		otg_put_transceiver(tegra->transceiver);
+		otg_set_host(tegra->transceiver->otg, NULL);
+		usb_put_transceiver(tegra->transceiver);
 	}
 #endif
 
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 0a5fda7..8f9acbc 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -176,7 +176,7 @@
 	/*
 	 * OTG controllers and transceivers need software interaction
 	 */
-	struct otg_transceiver	*transceiver;
+	struct usb_phy	*transceiver;
 };
 
 /* convert between an HCD pointer and the corresponding EHCI_HCD */
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 7916e56..ab333ac 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -94,7 +94,6 @@
 	pdev->dev.parent = &ofdev->dev;
 
 	pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
-	pdev->dev.dma_mask = &pdev->archdata.dma_mask;
 	*pdev->dev.dma_mask = *ofdev->dev.dma_mask;
 
 	retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
diff --git a/drivers/usb/host/imx21-dbg.c b/drivers/usb/host/imx21-dbg.c
index 6d75334..ec98ece 100644
--- a/drivers/usb/host/imx21-dbg.c
+++ b/drivers/usb/host/imx21-dbg.c
@@ -239,7 +239,7 @@
 		"ETDs allocated: %d/%d (max=%d)\n"
 		"ETDs in use sw: %d\n"
 		"ETDs in use hw: %d\n"
-		"DMEM alocated: %d/%d (max=%d)\n"
+		"DMEM allocated: %d/%d (max=%d)\n"
 		"DMEM blocks: %d\n"
 		"Queued waiting for ETD: %d\n"
 		"Queued waiting for DMEM: %d\n",
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index d91e5f2..9248800 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1569,6 +1569,9 @@
 	int ret = 0;
 	unsigned long irqflags;
 
+	if (usb_disabled())
+		return -ENODEV;
+
 	if (pdev->num_resources < 3) {
 		ret = -ENODEV;
 		goto err1;
@@ -1708,22 +1711,4 @@
 	},
 };
 
-/*-----------------------------------------------------------------*/
-
-static int __init isp116x_init(void)
-{
-	if (usb_disabled())
-		return -ENODEV;
-
-	INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION);
-	return platform_driver_register(&isp116x_driver);
-}
-
-module_init(isp116x_init);
-
-static void __exit isp116x_cleanup(void)
-{
-	platform_driver_unregister(&isp116x_driver);
-}
-
-module_exit(isp116x_cleanup);
+module_platform_driver(isp116x_driver);
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index e5fd8aa..9e63cdf 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2693,6 +2693,9 @@
 	struct resource *irq_res;
 	unsigned int irq_flags = 0;
 
+	if (usb_disabled())
+		return -ENODEV;
+
 	/* basic sanity checks first.  board-specific init logic should
 	 * have initialized this the three resources and probably board
 	 * specific platform_data.  we don't probe for IRQs, and do only
@@ -2864,19 +2867,4 @@
 	},
 };
 
-/*-------------------------------------------------------------------------*/
-
-static int __init isp1362_init(void)
-{
-	if (usb_disabled())
-		return -ENODEV;
-	pr_info("driver %s, %s\n", hcd_name, DRIVER_VERSION);
-	return platform_driver_register(&isp1362_driver);
-}
-module_init(isp1362_init);
-
-static void __exit isp1362_cleanup(void)
-{
-	platform_driver_unregister(&isp1362_driver);
-}
-module_exit(isp1362_cleanup);
+module_platform_driver(isp1362_driver);
diff --git a/drivers/usb/host/ohci-ath79.c b/drivers/usb/host/ohci-ath79.c
deleted file mode 100644
index 18d574d..0000000
--- a/drivers/usb/host/ohci-ath79.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- *  OHCI HCD (Host Controller Driver) for USB.
- *
- *  Bus Glue for Atheros AR71XX/AR724X built-in OHCI controller.
- *
- *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- *
- *  Parts of this file are based on Atheros' 2.6.15 BSP
- *	Copyright (C) 2007 Atheros Communications, Inc.
- *
- *  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/platform_device.h>
-
-static int __devinit ohci_ath79_start(struct usb_hcd *hcd)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
-	int ret;
-
-	ret = ohci_init(ohci);
-	if (ret < 0)
-		return ret;
-
-	ret = ohci_run(ohci);
-	if (ret < 0)
-		goto err;
-
-	return 0;
-
-err:
-	ohci_stop(hcd);
-	return ret;
-}
-
-static const struct hc_driver ohci_ath79_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "Atheros built-in OHCI controller",
-	.hcd_priv_size		= sizeof(struct ohci_hcd),
-
-	.irq			= ohci_irq,
-	.flags			= HCD_USB11 | HCD_MEMORY,
-
-	.start			= ohci_ath79_start,
-	.stop			= ohci_stop,
-	.shutdown		= ohci_shutdown,
-
-	.urb_enqueue		= ohci_urb_enqueue,
-	.urb_dequeue		= ohci_urb_dequeue,
-	.endpoint_disable	= ohci_endpoint_disable,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number	= ohci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data	= ohci_hub_status_data,
-	.hub_control		= ohci_hub_control,
-	.start_port_reset	= ohci_start_port_reset,
-};
-
-static int ohci_ath79_probe(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd;
-	struct resource *res;
-	int irq;
-	int ret;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dev_dbg(&pdev->dev, "no IRQ specified\n");
-		return -ENODEV;
-	}
-	irq = res->start;
-
-	hcd = usb_create_hcd(&ohci_ath79_hc_driver, &pdev->dev,
-			     dev_name(&pdev->dev));
-	if (!hcd)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_dbg(&pdev->dev, "no base address specified\n");
-		ret = -ENODEV;
-		goto err_put_hcd;
-	}
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		dev_dbg(&pdev->dev, "controller already in use\n");
-		ret = -EBUSY;
-		goto err_put_hcd;
-	}
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		dev_dbg(&pdev->dev, "error mapping memory\n");
-		ret = -EFAULT;
-		goto err_release_region;
-	}
-
-	ohci_hcd_init(hcd_to_ohci(hcd));
-
-	ret = usb_add_hcd(hcd, irq, 0);
-	if (ret)
-		goto err_stop_hcd;
-
-	return 0;
-
-err_stop_hcd:
-	iounmap(hcd->regs);
-err_release_region:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err_put_hcd:
-	usb_put_hcd(hcd);
-	return ret;
-}
-
-static int ohci_ath79_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-
-	return 0;
-}
-
-static struct platform_driver ohci_hcd_ath79_driver = {
-	.probe		= ohci_ath79_probe,
-	.remove		= ohci_ath79_remove,
-	.shutdown	= usb_hcd_platform_shutdown,
-	.driver		= {
-		.name	= "ath79-ohci",
-		.owner	= THIS_MODULE,
-	},
-};
-
-MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ath79-ohci");
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index 55aa35a..37bb20e 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -212,12 +212,10 @@
 	 * mark HW unaccessible, bail out if RH has been resumed. Use
 	 * the spinlock to properly synchronize with possible pending
 	 * RH suspend or resume activity.
-	 *
-	 * This is still racy as hcd->state is manipulated outside of
-	 * any locks =P But that will be a different fix.
 	 */
 	spin_lock_irqsave(&ohci->lock, flags);
-	if (hcd->state != HC_STATE_SUSPENDED && hcd->state != HC_STATE_HALT) {
+	if (ohci->rh_state != OHCI_RH_SUSPENDED &&
+			ohci->rh_state != OHCI_RH_HALTED) {
 		rc = -EINVAL;
 		goto fail;
 	}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 34b9edd..cd5e382 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -899,7 +899,7 @@
 	ohci_usb_reset (ohci);
 	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
 	free_irq(hcd->irq, hcd);
-	hcd->irq = -1;
+	hcd->irq = 0;
 
 	if (quirk_zfmicro(ohci))
 		del_timer(&ohci->unlink_watchdog);
@@ -1050,9 +1050,9 @@
 #define PLATFORM_DRIVER		ohci_hcd_at91_driver
 #endif
 
-#ifdef CONFIG_ARCH_PNX4008
-#include "ohci-pnx4008.c"
-#define PLATFORM_DRIVER		usb_hcd_pnx4008_driver
+#if defined(CONFIG_ARCH_PNX4008) || defined(CONFIG_ARCH_LPC32XX)
+#include "ohci-nxp.c"
+#define PLATFORM_DRIVER		usb_hcd_nxp_driver
 #endif
 
 #ifdef CONFIG_ARCH_DAVINCI_DA8XX
@@ -1111,16 +1111,16 @@
 #define PLATFORM_DRIVER		ohci_hcd_cns3xxx_driver
 #endif
 
-#ifdef CONFIG_USB_OHCI_ATH79
-#include "ohci-ath79.c"
-#define PLATFORM_DRIVER		ohci_hcd_ath79_driver
-#endif
-
 #ifdef CONFIG_CPU_XLR
 #include "ohci-xls.c"
 #define PLATFORM_DRIVER		ohci_xls_driver
 #endif
 
+#ifdef CONFIG_USB_OHCI_HCD_PLATFORM
+#include "ohci-platform.c"
+#define PLATFORM_DRIVER		ohci_platform_driver
+#endif
+
 #if	!defined(PCI_DRIVER) &&		\
 	!defined(PLATFORM_DRIVER) &&	\
 	!defined(OMAP1_PLATFORM_DRIVER) &&	\
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
new file mode 100644
index 0000000..6618de1
--- /dev/null
+++ b/drivers/usb/host/ohci-nxp.c
@@ -0,0 +1,528 @@
+/*
+ * driver for NXP USB Host devices
+ *
+ * Currently supported OHCI host devices:
+ * - Philips PNX4008
+ * - NXP LPC32xx
+ *
+ * Authors: Dmitry Chigirev <source@mvista.com>
+ *	    Vitaly Wool <vitalywool@gmail.com>
+ *
+ * register initialization is based on code examples provided by Philips
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * NOTE: This driver does not have suspend/resume functionality
+ * This driver is intended for engineering development purposes only
+ *
+ * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/io.h>
+
+#include <mach/platform.h>
+#include <mach/irqs.h>
+#include <asm/gpio.h>
+
+#define USB_CONFIG_BASE		0x31020000
+#define PWRMAN_BASE		0x40004000
+
+#define USB_CTRL		IO_ADDRESS(PWRMAN_BASE + 0x64)
+
+/* USB_CTRL bit defines */
+#define USB_SLAVE_HCLK_EN	(1 << 24)
+#define USB_HOST_NEED_CLK_EN	(1 << 21)
+
+#define USB_OTG_CLK_CTRL	IO_ADDRESS(USB_CONFIG_BASE + 0xFF4)
+#define USB_OTG_CLK_STAT	IO_ADDRESS(USB_CONFIG_BASE + 0xFF8)
+
+/* USB_OTG_CLK_CTRL bit defines */
+#define AHB_M_CLOCK_ON		(1 << 4)
+#define OTG_CLOCK_ON		(1 << 3)
+#define I2C_CLOCK_ON		(1 << 2)
+#define DEV_CLOCK_ON		(1 << 1)
+#define HOST_CLOCK_ON		(1 << 0)
+
+#define USB_OTG_STAT_CONTROL	IO_ADDRESS(USB_CONFIG_BASE + 0x110)
+
+/* USB_OTG_STAT_CONTROL bit defines */
+#define TRANSPARENT_I2C_EN	(1 << 7)
+#define HOST_EN			(1 << 0)
+
+/* ISP1301 USB transceiver I2C registers */
+#define	ISP1301_MODE_CONTROL_1		0x04	/* u8 read, set, +1 clear */
+
+#define	MC1_SPEED_REG		(1 << 0)
+#define	MC1_SUSPEND_REG		(1 << 1)
+#define	MC1_DAT_SE0		(1 << 2)
+#define	MC1_TRANSPARENT		(1 << 3)
+#define	MC1_BDIS_ACON_EN	(1 << 4)
+#define	MC1_OE_INT_EN		(1 << 5)
+#define	MC1_UART_EN		(1 << 6)
+#define	MC1_MASK		0x7f
+
+#define	ISP1301_MODE_CONTROL_2		0x12	/* u8 read, set, +1 clear */
+
+#define	MC2_GLOBAL_PWR_DN	(1 << 0)
+#define	MC2_SPD_SUSP_CTRL	(1 << 1)
+#define	MC2_BI_DI		(1 << 2)
+#define	MC2_TRANSP_BDIR0	(1 << 3)
+#define	MC2_TRANSP_BDIR1	(1 << 4)
+#define	MC2_AUDIO_EN		(1 << 5)
+#define	MC2_PSW_EN		(1 << 6)
+#define	MC2_EN2V7		(1 << 7)
+
+#define	ISP1301_OTG_CONTROL_1		0x06	/* u8 read, set, +1 clear */
+#	define	OTG1_DP_PULLUP		(1 << 0)
+#	define	OTG1_DM_PULLUP		(1 << 1)
+#	define	OTG1_DP_PULLDOWN	(1 << 2)
+#	define	OTG1_DM_PULLDOWN	(1 << 3)
+#	define	OTG1_ID_PULLDOWN	(1 << 4)
+#	define	OTG1_VBUS_DRV		(1 << 5)
+#	define	OTG1_VBUS_DISCHRG	(1 << 6)
+#	define	OTG1_VBUS_CHRG		(1 << 7)
+#define	ISP1301_OTG_STATUS		0x10	/* u8 readonly */
+#	define	OTG_B_SESS_END		(1 << 6)
+#	define	OTG_B_SESS_VLD		(1 << 7)
+
+#define ISP1301_I2C_ADDR 0x2C
+
+#define ISP1301_I2C_MODE_CONTROL_1 0x4
+#define ISP1301_I2C_MODE_CONTROL_2 0x12
+#define ISP1301_I2C_OTG_CONTROL_1 0x6
+#define ISP1301_I2C_OTG_CONTROL_2 0x10
+#define ISP1301_I2C_INTERRUPT_SOURCE 0x8
+#define ISP1301_I2C_INTERRUPT_LATCH 0xA
+#define ISP1301_I2C_INTERRUPT_FALLING 0xC
+#define ISP1301_I2C_INTERRUPT_RISING 0xE
+#define ISP1301_I2C_REG_CLEAR_ADDR 1
+
+/* On LPC32xx, those are undefined */
+#ifndef start_int_set_falling_edge
+#define start_int_set_falling_edge(irq)
+#define start_int_set_rising_edge(irq)
+#define start_int_ack(irq)
+#define start_int_mask(irq)
+#define start_int_umask(irq)
+#endif
+
+static struct i2c_driver isp1301_driver;
+static struct i2c_client *isp1301_i2c_client;
+
+extern int usb_disabled(void);
+extern int ocpi_enable(void);
+
+static struct clk *usb_clk;
+
+static const unsigned short normal_i2c[] =
+    { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END };
+
+static int isp1301_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	return 0;
+}
+
+static int isp1301_remove(struct i2c_client *client)
+{
+	return 0;
+}
+
+static const struct i2c_device_id isp1301_id[] = {
+	{ "isp1301_nxp", 0 },
+	{ }
+};
+
+static struct i2c_driver isp1301_driver = {
+	.driver = {
+		.name = "isp1301_nxp",
+	},
+	.probe = isp1301_probe,
+	.remove = isp1301_remove,
+	.id_table = isp1301_id,
+};
+
+static void isp1301_configure_pnx4008(void)
+{
+	/* PNX4008 only supports DAT_SE0 USB mode */
+	/* PNX4008 R2A requires setting the MAX603 to output 3.6V */
+	/* Power up externel charge-pump */
+
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_MODE_CONTROL_1, MC1_DAT_SE0 | MC1_SPEED_REG);
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
+		~(MC1_DAT_SE0 | MC1_SPEED_REG));
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_MODE_CONTROL_2,
+		MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL);
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR,
+		~(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL));
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_OTG_CONTROL_1, OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN);
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
+		~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR, 0xFF);
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR,
+		0xFF);
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR,
+		0xFF);
+}
+
+static void isp1301_configure_lpc32xx(void)
+{
+	/* LPC32XX only supports DAT_SE0 USB mode */
+	/* This sequence is important */
+
+	/* Disable transparent UART mode first */
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		(ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR),
+		MC1_UART_EN);
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		(ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR),
+		~MC1_SPEED_REG);
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+				  ISP1301_I2C_MODE_CONTROL_1, MC1_SPEED_REG);
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		  (ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR),
+		  ~0);
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_MODE_CONTROL_2,
+		(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL));
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		(ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_MODE_CONTROL_1, MC1_DAT_SE0);
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_OTG_CONTROL_1,
+		(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		(ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR),
+		(OTG1_DM_PULLUP | OTG1_DP_PULLUP));
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR,
+		~0);
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
+
+	/* Enable usb_need_clk clock after transceiver is initialized */
+	__raw_writel((__raw_readl(USB_CTRL) | (1 << 22)), USB_CTRL);
+
+	printk(KERN_INFO "ISP1301 Vendor ID  : 0x%04x\n",
+	      i2c_smbus_read_word_data(isp1301_i2c_client, 0x00));
+	printk(KERN_INFO "ISP1301 Product ID : 0x%04x\n",
+	      i2c_smbus_read_word_data(isp1301_i2c_client, 0x02));
+	printk(KERN_INFO "ISP1301 Version ID : 0x%04x\n",
+	      i2c_smbus_read_word_data(isp1301_i2c_client, 0x14));
+}
+
+static void isp1301_configure(void)
+{
+	if (machine_is_pnx4008())
+		isp1301_configure_pnx4008();
+	else
+		isp1301_configure_lpc32xx();
+}
+
+static inline void isp1301_vbus_on(void)
+{
+	i2c_smbus_write_byte_data(isp1301_i2c_client, ISP1301_I2C_OTG_CONTROL_1,
+				  OTG1_VBUS_DRV);
+}
+
+static inline void isp1301_vbus_off(void)
+{
+	i2c_smbus_write_byte_data(isp1301_i2c_client,
+		ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
+		OTG1_VBUS_DRV);
+}
+
+static void nxp_start_hc(void)
+{
+	unsigned long tmp = __raw_readl(USB_OTG_STAT_CONTROL) | HOST_EN;
+	__raw_writel(tmp, USB_OTG_STAT_CONTROL);
+	isp1301_vbus_on();
+}
+
+static void nxp_stop_hc(void)
+{
+	unsigned long tmp;
+	isp1301_vbus_off();
+	tmp = __raw_readl(USB_OTG_STAT_CONTROL) & ~HOST_EN;
+	__raw_writel(tmp, USB_OTG_STAT_CONTROL);
+}
+
+static int __devinit ohci_nxp_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	int ret;
+
+	if ((ret = ohci_init(ohci)) < 0)
+		return ret;
+
+	if ((ret = ohci_run(ohci)) < 0) {
+		dev_err(hcd->self.controller, "can't start\n");
+		ohci_stop(hcd);
+		return ret;
+	}
+	return 0;
+}
+
+static const struct hc_driver ohci_nxp_hc_driver = {
+	.description = hcd_name,
+	.product_desc =		"nxp OHCI",
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq = ohci_irq,
+	.flags = HCD_USB11 | HCD_MEMORY,
+
+	.hcd_priv_size =	sizeof(struct ohci_hcd),
+	/*
+	 * basic lifecycle operations
+	 */
+	.start = ohci_nxp_start,
+	.stop = ohci_stop,
+	.shutdown = ohci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue = ohci_urb_enqueue,
+	.urb_dequeue = ohci_urb_dequeue,
+	.endpoint_disable = ohci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number = ohci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data = ohci_hub_status_data,
+	.hub_control = ohci_hub_control,
+#ifdef	CONFIG_PM
+	.bus_suspend = ohci_bus_suspend,
+	.bus_resume = ohci_bus_resume,
+#endif
+	.start_port_reset = ohci_start_port_reset,
+};
+
+#define USB_CLOCK_MASK (AHB_M_CLOCK_ON| OTG_CLOCK_ON | HOST_CLOCK_ON | I2C_CLOCK_ON)
+
+static void nxp_set_usb_bits(void)
+{
+	if (machine_is_pnx4008()) {
+		start_int_set_falling_edge(SE_USB_OTG_ATX_INT_N);
+		start_int_ack(SE_USB_OTG_ATX_INT_N);
+		start_int_umask(SE_USB_OTG_ATX_INT_N);
+
+		start_int_set_rising_edge(SE_USB_OTG_TIMER_INT);
+		start_int_ack(SE_USB_OTG_TIMER_INT);
+		start_int_umask(SE_USB_OTG_TIMER_INT);
+
+		start_int_set_rising_edge(SE_USB_I2C_INT);
+		start_int_ack(SE_USB_I2C_INT);
+		start_int_umask(SE_USB_I2C_INT);
+
+		start_int_set_rising_edge(SE_USB_INT);
+		start_int_ack(SE_USB_INT);
+		start_int_umask(SE_USB_INT);
+
+		start_int_set_rising_edge(SE_USB_NEED_CLK_INT);
+		start_int_ack(SE_USB_NEED_CLK_INT);
+		start_int_umask(SE_USB_NEED_CLK_INT);
+
+		start_int_set_rising_edge(SE_USB_AHB_NEED_CLK_INT);
+		start_int_ack(SE_USB_AHB_NEED_CLK_INT);
+		start_int_umask(SE_USB_AHB_NEED_CLK_INT);
+	}
+}
+
+static void nxp_unset_usb_bits(void)
+{
+	if (machine_is_pnx4008()) {
+		start_int_mask(SE_USB_OTG_ATX_INT_N);
+		start_int_mask(SE_USB_OTG_TIMER_INT);
+		start_int_mask(SE_USB_I2C_INT);
+		start_int_mask(SE_USB_INT);
+		start_int_mask(SE_USB_NEED_CLK_INT);
+		start_int_mask(SE_USB_AHB_NEED_CLK_INT);
+	}
+}
+
+static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = 0;
+	struct ohci_hcd *ohci;
+	const struct hc_driver *driver = &ohci_nxp_hc_driver;
+	struct i2c_adapter *i2c_adap;
+	struct i2c_board_info i2c_info;
+
+	int ret = 0, irq;
+
+	dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (nxp)\n", hcd_name);
+	if (usb_disabled()) {
+		err("USB is disabled");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (pdev->num_resources != 2
+	    || pdev->resource[0].flags != IORESOURCE_MEM
+	    || pdev->resource[1].flags != IORESOURCE_IRQ) {
+		err("Invalid resource configuration");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* Enable AHB slave USB clock, needed for further USB clock control */
+	__raw_writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL);
+
+	ret = i2c_add_driver(&isp1301_driver);
+	if (ret < 0) {
+		err("failed to add ISP1301 driver");
+		goto out;
+	}
+	i2c_adap = i2c_get_adapter(2);
+	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
+	strlcpy(i2c_info.type, "isp1301_nxp", I2C_NAME_SIZE);
+	isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
+						   normal_i2c, NULL);
+	i2c_put_adapter(i2c_adap);
+	if (!isp1301_i2c_client) {
+		err("failed to connect I2C to ISP1301 USB Transceiver");
+		ret = -ENODEV;
+		goto out_i2c_driver;
+	}
+
+	isp1301_configure();
+
+	/* Enable USB PLL */
+	usb_clk = clk_get(&pdev->dev, "ck_pll5");
+	if (IS_ERR(usb_clk)) {
+		err("failed to acquire USB PLL");
+		ret = PTR_ERR(usb_clk);
+		goto out1;
+	}
+
+	ret = clk_enable(usb_clk);
+	if (ret < 0) {
+		err("failed to start USB PLL");
+		goto out2;
+	}
+
+	ret = clk_set_rate(usb_clk, 48000);
+	if (ret < 0) {
+		err("failed to set USB clock rate");
+		goto out3;
+	}
+
+	__raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL);
+
+	/* Set to enable all needed USB clocks */
+	__raw_writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL);
+
+	while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) !=
+	       USB_CLOCK_MASK) ;
+
+	hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev));
+	if (!hcd) {
+		err("Failed to allocate HC buffer");
+		ret = -ENOMEM;
+		goto out3;
+	}
+
+	/* Set all USB bits in the Start Enable register */
+	nxp_set_usb_bits();
+
+	hcd->rsrc_start = pdev->resource[0].start;
+	hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		dev_dbg(&pdev->dev, "request_mem_region failed\n");
+		ret =  -ENOMEM;
+		goto out4;
+	}
+	hcd->regs = (void __iomem *)pdev->resource[0].start;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = -ENXIO;
+		goto out4;
+	}
+
+	nxp_start_hc();
+	platform_set_drvdata(pdev, hcd);
+	ohci = hcd_to_ohci(hcd);
+	ohci_hcd_init(ohci);
+
+	dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
+	ret = usb_add_hcd(hcd, irq, 0);
+	if (ret == 0)
+		return ret;
+
+	nxp_stop_hc();
+out4:
+	nxp_unset_usb_bits();
+	usb_put_hcd(hcd);
+out3:
+	clk_disable(usb_clk);
+out2:
+	clk_put(usb_clk);
+out1:
+	i2c_unregister_device(isp1301_i2c_client);
+	isp1301_i2c_client = NULL;
+out_i2c_driver:
+	i2c_del_driver(&isp1301_driver);
+out:
+	return ret;
+}
+
+static int usb_hcd_nxp_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	nxp_stop_hc();
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	nxp_unset_usb_bits();
+	clk_disable(usb_clk);
+	clk_put(usb_clk);
+	i2c_unregister_device(isp1301_i2c_client);
+	isp1301_i2c_client = NULL;
+	i2c_del_driver(&isp1301_driver);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:usb-ohci");
+
+static struct platform_driver usb_hcd_nxp_driver = {
+	.driver = {
+		.name = "usb-ohci",
+		.owner	= THIS_MODULE,
+	},
+	.probe = usb_hcd_nxp_probe,
+	.remove = usb_hcd_nxp_remove,
+};
+
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index db39686..96451e4 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -171,7 +171,7 @@
 	unsigned long	flags;
 	u32 l;
 
-	otg_start_hnp(ohci->transceiver);
+	otg_start_hnp(ohci->transceiver->otg);
 
 	local_irq_save(flags);
 	ohci->transceiver->state = OTG_STATE_A_SUSPEND;
@@ -210,9 +210,9 @@
 
 #ifdef	CONFIG_USB_OTG
 	if (need_transceiver) {
-		ohci->transceiver = otg_get_transceiver();
+		ohci->transceiver = usb_get_transceiver();
 		if (ohci->transceiver) {
-			int	status = otg_set_host(ohci->transceiver,
+			int	status = otg_set_host(ohci->transceiver->otg,
 						&ohci_to_hcd(ohci)->self);
 			dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n",
 					ohci->transceiver->label, status);
@@ -404,7 +404,7 @@
 
 	usb_remove_hcd(hcd);
 	if (ohci->transceiver) {
-		(void) otg_set_host(ohci->transceiver, 0);
+		(void) otg_set_host(ohci->transceiver->otg, 0);
 		put_device(ohci->transceiver->dev);
 	}
 	if (machine_is_omap_osk())
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
new file mode 100644
index 0000000..ec5c679
--- /dev/null
+++ b/drivers/usb/host/ohci-platform.c
@@ -0,0 +1,194 @@
+/*
+ * Generic platform ohci driver
+ *
+ * Copyright 2007 Michael Buesch <m@bues.ch>
+ * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Derived from the OCHI-SSB driver
+ * Derived from the OHCI-PCI driver
+ * Copyright 1999 Roman Weissgaerber
+ * Copyright 2000-2002 David Brownell
+ * Copyright 1999 Linus Torvalds
+ * Copyright 1999 Gregory P. Smith
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+#include <linux/platform_device.h>
+#include <linux/usb/ohci_pdriver.h>
+
+static int ohci_platform_reset(struct usb_hcd *hcd)
+{
+	struct platform_device *pdev = to_platform_device(hcd->self.controller);
+	struct usb_ohci_pdata *pdata = pdev->dev.platform_data;
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	int err;
+
+	if (pdata->big_endian_desc)
+		ohci->flags |= OHCI_QUIRK_BE_DESC;
+	if (pdata->big_endian_mmio)
+		ohci->flags |= OHCI_QUIRK_BE_MMIO;
+	if (pdata->no_big_frame_no)
+		ohci->flags |= OHCI_QUIRK_FRAME_NO;
+
+	ohci_hcd_init(ohci);
+	err = ohci_init(ohci);
+
+	return err;
+}
+
+static int ohci_platform_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	int err;
+
+	err = ohci_run(ohci);
+	if (err < 0) {
+		ohci_err(ohci, "can't start\n");
+		ohci_stop(hcd);
+	}
+
+	return err;
+}
+
+static const struct hc_driver ohci_platform_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "Generic Platform OHCI Controller",
+	.hcd_priv_size		= sizeof(struct ohci_hcd),
+
+	.irq			= ohci_irq,
+	.flags			= HCD_MEMORY | HCD_USB11,
+
+	.reset			= ohci_platform_reset,
+	.start			= ohci_platform_start,
+	.stop			= ohci_stop,
+	.shutdown		= ohci_shutdown,
+
+	.urb_enqueue		= ohci_urb_enqueue,
+	.urb_dequeue		= ohci_urb_dequeue,
+	.endpoint_disable	= ohci_endpoint_disable,
+
+	.get_frame_number	= ohci_get_frame,
+
+	.hub_status_data	= ohci_hub_status_data,
+	.hub_control		= ohci_hub_control,
+#ifdef	CONFIG_PM
+	.bus_suspend		= ohci_bus_suspend,
+	.bus_resume		= ohci_bus_resume,
+#endif
+
+	.start_port_reset	= ohci_start_port_reset,
+};
+
+static int __devinit ohci_platform_probe(struct platform_device *dev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res_mem;
+	int irq;
+	int err = -ENOMEM;
+
+	BUG_ON(!dev->dev.platform_data);
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		pr_err("no irq provieded");
+		return irq;
+	}
+
+	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res_mem) {
+		pr_err("no memory recourse provieded");
+		return -ENXIO;
+	}
+
+	hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
+			dev_name(&dev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	hcd->rsrc_start = res_mem->start;
+	hcd->rsrc_len = resource_size(res_mem);
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		pr_err("controller already in use");
+		err = -EBUSY;
+		goto err_put_hcd;
+	}
+
+	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs)
+		goto err_release_region;
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (err)
+		goto err_iounmap;
+
+	platform_set_drvdata(dev, hcd);
+
+	return err;
+
+err_iounmap:
+	iounmap(hcd->regs);
+err_release_region:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_put_hcd:
+	usb_put_hcd(hcd);
+	return err;
+}
+
+static int __devexit ohci_platform_remove(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	platform_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int ohci_platform_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static int ohci_platform_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+	ohci_finish_controller_resume(hcd);
+	return 0;
+}
+
+#else /* !CONFIG_PM */
+#define ohci_platform_suspend	NULL
+#define ohci_platform_resume	NULL
+#endif /* CONFIG_PM */
+
+static const struct platform_device_id ohci_platform_table[] = {
+	{ "ohci-platform", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, ohci_platform_table);
+
+static const struct dev_pm_ops ohci_platform_pm_ops = {
+	.suspend	= ohci_platform_suspend,
+	.resume		= ohci_platform_resume,
+};
+
+static struct platform_driver ohci_platform_driver = {
+	.id_table	= ohci_platform_table,
+	.probe		= ohci_platform_probe,
+	.remove		= __devexit_p(ohci_platform_remove),
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "ohci-platform",
+		.pm	= &ohci_platform_pm_ops,
+	}
+};
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
deleted file mode 100644
index 0013db7..0000000
--- a/drivers/usb/host/ohci-pnx4008.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * drivers/usb/host/ohci-pnx4008.c
- *
- * driver for Philips PNX4008 USB Host
- *
- * Authors: Dmitry Chigirev <source@mvista.com>
- *	    Vitaly Wool <vitalywool@gmail.com>
- *
- * register initialization is based on code examples provided by Philips
- * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
- *
- * NOTE: This driver does not have suspend/resume functionality
- * This driver is intended for engineering development purposes only
- *
- * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-
-#include <mach/hardware.h>
-#include <asm/io.h>
-
-#include <mach/platform.h>
-#include <mach/irqs.h>
-#include <asm/gpio.h>
-
-#define USB_CTRL	IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64)
-
-/* USB_CTRL bit defines */
-#define USB_SLAVE_HCLK_EN	(1 << 24)
-#define USB_HOST_NEED_CLK_EN	(1 << 21)
-
-#define USB_OTG_CLK_CTRL	IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF4)
-#define USB_OTG_CLK_STAT	IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF8)
-
-/* USB_OTG_CLK_CTRL bit defines */
-#define AHB_M_CLOCK_ON		(1 << 4)
-#define OTG_CLOCK_ON		(1 << 3)
-#define I2C_CLOCK_ON		(1 << 2)
-#define DEV_CLOCK_ON		(1 << 1)
-#define HOST_CLOCK_ON		(1 << 0)
-
-#define USB_OTG_STAT_CONTROL	IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0x110)
-
-/* USB_OTG_STAT_CONTROL bit defines */
-#define TRANSPARENT_I2C_EN	(1 << 7)
-#define HOST_EN			(1 << 0)
-
-/* ISP1301 USB transceiver I2C registers */
-#define	ISP1301_MODE_CONTROL_1		0x04	/* u8 read, set, +1 clear */
-
-#define	MC1_SPEED_REG		(1 << 0)
-#define	MC1_SUSPEND_REG		(1 << 1)
-#define	MC1_DAT_SE0		(1 << 2)
-#define	MC1_TRANSPARENT		(1 << 3)
-#define	MC1_BDIS_ACON_EN	(1 << 4)
-#define	MC1_OE_INT_EN		(1 << 5)
-#define	MC1_UART_EN		(1 << 6)
-#define	MC1_MASK		0x7f
-
-#define	ISP1301_MODE_CONTROL_2		0x12	/* u8 read, set, +1 clear */
-
-#define	MC2_GLOBAL_PWR_DN	(1 << 0)
-#define	MC2_SPD_SUSP_CTRL	(1 << 1)
-#define	MC2_BI_DI		(1 << 2)
-#define	MC2_TRANSP_BDIR0	(1 << 3)
-#define	MC2_TRANSP_BDIR1	(1 << 4)
-#define	MC2_AUDIO_EN		(1 << 5)
-#define	MC2_PSW_EN		(1 << 6)
-#define	MC2_EN2V7		(1 << 7)
-
-#define	ISP1301_OTG_CONTROL_1		0x06	/* u8 read, set, +1 clear */
-#	define	OTG1_DP_PULLUP		(1 << 0)
-#	define	OTG1_DM_PULLUP		(1 << 1)
-#	define	OTG1_DP_PULLDOWN	(1 << 2)
-#	define	OTG1_DM_PULLDOWN	(1 << 3)
-#	define	OTG1_ID_PULLDOWN	(1 << 4)
-#	define	OTG1_VBUS_DRV		(1 << 5)
-#	define	OTG1_VBUS_DISCHRG	(1 << 6)
-#	define	OTG1_VBUS_CHRG		(1 << 7)
-#define	ISP1301_OTG_STATUS		0x10	/* u8 readonly */
-#	define	OTG_B_SESS_END		(1 << 6)
-#	define	OTG_B_SESS_VLD		(1 << 7)
-
-#define ISP1301_I2C_ADDR 0x2C
-
-#define ISP1301_I2C_MODE_CONTROL_1 0x4
-#define ISP1301_I2C_MODE_CONTROL_2 0x12
-#define ISP1301_I2C_OTG_CONTROL_1 0x6
-#define ISP1301_I2C_OTG_CONTROL_2 0x10
-#define ISP1301_I2C_INTERRUPT_SOURCE 0x8
-#define ISP1301_I2C_INTERRUPT_LATCH 0xA
-#define ISP1301_I2C_INTERRUPT_FALLING 0xC
-#define ISP1301_I2C_INTERRUPT_RISING 0xE
-#define ISP1301_I2C_REG_CLEAR_ADDR 1
-
-static struct i2c_driver isp1301_driver;
-static struct i2c_client *isp1301_i2c_client;
-
-extern int usb_disabled(void);
-extern int ocpi_enable(void);
-
-static struct clk *usb_clk;
-
-static const unsigned short normal_i2c[] =
-    { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END };
-
-static int isp1301_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
-{
-	return 0;
-}
-
-static int isp1301_remove(struct i2c_client *client)
-{
-	return 0;
-}
-
-static const struct i2c_device_id isp1301_id[] = {
-	{ "isp1301_pnx", 0 },
-	{ }
-};
-
-static struct i2c_driver isp1301_driver = {
-	.driver = {
-		.name = "isp1301_pnx",
-	},
-	.probe = isp1301_probe,
-	.remove = isp1301_remove,
-	.id_table = isp1301_id,
-};
-
-static void i2c_write(u8 buf, u8 subaddr)
-{
-	char tmpbuf[2];
-
-	tmpbuf[0] = subaddr;	/*register number */
-	tmpbuf[1] = buf;	/*register data */
-	i2c_master_send(isp1301_i2c_client, &tmpbuf[0], 2);
-}
-
-static void isp1301_configure(void)
-{
-	/* PNX4008 only supports DAT_SE0 USB mode */
-	/* PNX4008 R2A requires setting the MAX603 to output 3.6V */
-	/* Power up externel charge-pump */
-
-	i2c_write(MC1_DAT_SE0 | MC1_SPEED_REG, ISP1301_I2C_MODE_CONTROL_1);
-	i2c_write(~(MC1_DAT_SE0 | MC1_SPEED_REG),
-		  ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
-	i2c_write(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL,
-		  ISP1301_I2C_MODE_CONTROL_2);
-	i2c_write(~(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL),
-		  ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR);
-	i2c_write(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN,
-		  ISP1301_I2C_OTG_CONTROL_1);
-	i2c_write(~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN),
-		  ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
-	i2c_write(0xFF,
-		  ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR);
-	i2c_write(0xFF,
-		  ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR);
-	i2c_write(0xFF,
-		  ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR);
-
-}
-
-static inline void isp1301_vbus_on(void)
-{
-	i2c_write(OTG1_VBUS_DRV, ISP1301_I2C_OTG_CONTROL_1);
-}
-
-static inline void isp1301_vbus_off(void)
-{
-	i2c_write(OTG1_VBUS_DRV,
-		  ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
-}
-
-static void pnx4008_start_hc(void)
-{
-	unsigned long tmp = __raw_readl(USB_OTG_STAT_CONTROL) | HOST_EN;
-	__raw_writel(tmp, USB_OTG_STAT_CONTROL);
-	isp1301_vbus_on();
-}
-
-static void pnx4008_stop_hc(void)
-{
-	unsigned long tmp;
-	isp1301_vbus_off();
-	tmp = __raw_readl(USB_OTG_STAT_CONTROL) & ~HOST_EN;
-	__raw_writel(tmp, USB_OTG_STAT_CONTROL);
-}
-
-static int __devinit ohci_pnx4008_start(struct usb_hcd *hcd)
-{
-	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-	int ret;
-
-	if ((ret = ohci_init(ohci)) < 0)
-		return ret;
-
-	if ((ret = ohci_run(ohci)) < 0) {
-		dev_err(hcd->self.controller, "can't start\n");
-		ohci_stop(hcd);
-		return ret;
-	}
-	return 0;
-}
-
-static const struct hc_driver ohci_pnx4008_hc_driver = {
-	.description = hcd_name,
-	.product_desc =		"pnx4008 OHCI",
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq = ohci_irq,
-	.flags = HCD_USB11 | HCD_MEMORY,
-
-	.hcd_priv_size =	sizeof(struct ohci_hcd),
-	/*
-	 * basic lifecycle operations
-	 */
-	.start = ohci_pnx4008_start,
-	.stop = ohci_stop,
-	.shutdown = ohci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue = ohci_urb_enqueue,
-	.urb_dequeue = ohci_urb_dequeue,
-	.endpoint_disable = ohci_endpoint_disable,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number = ohci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data = ohci_hub_status_data,
-	.hub_control = ohci_hub_control,
-#ifdef	CONFIG_PM
-	.bus_suspend = ohci_bus_suspend,
-	.bus_resume = ohci_bus_resume,
-#endif
-	.start_port_reset = ohci_start_port_reset,
-};
-
-#define USB_CLOCK_MASK (AHB_M_CLOCK_ON| OTG_CLOCK_ON | HOST_CLOCK_ON | I2C_CLOCK_ON)
-
-static void pnx4008_set_usb_bits(void)
-{
-	start_int_set_falling_edge(SE_USB_OTG_ATX_INT_N);
-	start_int_ack(SE_USB_OTG_ATX_INT_N);
-	start_int_umask(SE_USB_OTG_ATX_INT_N);
-
-	start_int_set_rising_edge(SE_USB_OTG_TIMER_INT);
-	start_int_ack(SE_USB_OTG_TIMER_INT);
-	start_int_umask(SE_USB_OTG_TIMER_INT);
-
-	start_int_set_rising_edge(SE_USB_I2C_INT);
-	start_int_ack(SE_USB_I2C_INT);
-	start_int_umask(SE_USB_I2C_INT);
-
-	start_int_set_rising_edge(SE_USB_INT);
-	start_int_ack(SE_USB_INT);
-	start_int_umask(SE_USB_INT);
-
-	start_int_set_rising_edge(SE_USB_NEED_CLK_INT);
-	start_int_ack(SE_USB_NEED_CLK_INT);
-	start_int_umask(SE_USB_NEED_CLK_INT);
-
-	start_int_set_rising_edge(SE_USB_AHB_NEED_CLK_INT);
-	start_int_ack(SE_USB_AHB_NEED_CLK_INT);
-	start_int_umask(SE_USB_AHB_NEED_CLK_INT);
-}
-
-static void pnx4008_unset_usb_bits(void)
-{
-	start_int_mask(SE_USB_OTG_ATX_INT_N);
-	start_int_mask(SE_USB_OTG_TIMER_INT);
-	start_int_mask(SE_USB_I2C_INT);
-	start_int_mask(SE_USB_INT);
-	start_int_mask(SE_USB_NEED_CLK_INT);
-	start_int_mask(SE_USB_AHB_NEED_CLK_INT);
-}
-
-static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = 0;
-	struct ohci_hcd *ohci;
-	const struct hc_driver *driver = &ohci_pnx4008_hc_driver;
-	struct i2c_adapter *i2c_adap;
-	struct i2c_board_info i2c_info;
-
-	int ret = 0, irq;
-
-	dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (pnx4008)\n", hcd_name);
-	if (usb_disabled()) {
-		err("USB is disabled");
-		ret = -ENODEV;
-		goto out;
-	}
-
-	if (pdev->num_resources != 2
-	    || pdev->resource[0].flags != IORESOURCE_MEM
-	    || pdev->resource[1].flags != IORESOURCE_IRQ) {
-		err("Invalid resource configuration");
-		ret = -ENODEV;
-		goto out;
-	}
-
-	/* Enable AHB slave USB clock, needed for further USB clock control */
-	__raw_writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL);
-
-	ret = i2c_add_driver(&isp1301_driver);
-	if (ret < 0) {
-		err("failed to add ISP1301 driver");
-		goto out;
-	}
-	i2c_adap = i2c_get_adapter(2);
-	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
-	strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE);
-	isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
-						   normal_i2c, NULL);
-	i2c_put_adapter(i2c_adap);
-	if (!isp1301_i2c_client) {
-		err("failed to connect I2C to ISP1301 USB Transceiver");
-		ret = -ENODEV;
-		goto out_i2c_driver;
-	}
-
-	isp1301_configure();
-
-	/* Enable USB PLL */
-	usb_clk = clk_get(&pdev->dev, "ck_pll5");
-	if (IS_ERR(usb_clk)) {
-		err("failed to acquire USB PLL");
-		ret = PTR_ERR(usb_clk);
-		goto out1;
-	}
-
-	ret = clk_enable(usb_clk);
-	if (ret < 0) {
-		err("failed to start USB PLL");
-		goto out2;
-	}
-
-	ret = clk_set_rate(usb_clk, 48000);
-	if (ret < 0) {
-		err("failed to set USB clock rate");
-		goto out3;
-	}
-
-	__raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL);
-
-	/* Set to enable all needed USB clocks */
-	__raw_writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL);
-
-	while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) !=
-	       USB_CLOCK_MASK) ;
-
-	hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev));
-	if (!hcd) {
-		err("Failed to allocate HC buffer");
-		ret = -ENOMEM;
-		goto out3;
-	}
-
-	/* Set all USB bits in the Start Enable register */
-	pnx4008_set_usb_bits();
-
-	hcd->rsrc_start = pdev->resource[0].start;
-	hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		dev_dbg(&pdev->dev, "request_mem_region failed\n");
-		ret =  -ENOMEM;
-		goto out4;
-	}
-	hcd->regs = (void __iomem *)pdev->resource[0].start;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		ret = -ENXIO;
-		goto out4;
-	}
-
-	pnx4008_start_hc();
-	platform_set_drvdata(pdev, hcd);
-	ohci = hcd_to_ohci(hcd);
-	ohci_hcd_init(ohci);
-
-	dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
-	ret = usb_add_hcd(hcd, irq, 0);
-	if (ret == 0)
-		return ret;
-
-	pnx4008_stop_hc();
-out4:
-	pnx4008_unset_usb_bits();
-	usb_put_hcd(hcd);
-out3:
-	clk_disable(usb_clk);
-out2:
-	clk_put(usb_clk);
-out1:
-	i2c_unregister_device(isp1301_i2c_client);
-	isp1301_i2c_client = NULL;
-out_i2c_driver:
-	i2c_del_driver(&isp1301_driver);
-out:
-	return ret;
-}
-
-static int usb_hcd_pnx4008_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-	pnx4008_stop_hc();
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-	pnx4008_unset_usb_bits();
-	clk_disable(usb_clk);
-	clk_put(usb_clk);
-	i2c_unregister_device(isp1301_i2c_client);
-	isp1301_i2c_client = NULL;
-	i2c_del_driver(&isp1301_driver);
-
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:usb-ohci");
-
-static struct platform_driver usb_hcd_pnx4008_driver = {
-	.driver = {
-		.name = "usb-ohci",
-		.owner	= THIS_MODULE,
-	},
-	.probe = usb_hcd_pnx4008_probe,
-	.remove = usb_hcd_pnx4008_remove,
-};
-
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 6313e44..c31b281 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -23,6 +23,7 @@
 #include <linux/signal.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <mach/hardware.h>
 #include <mach/ohci.h>
 #include <mach/pxa3xx-u2d.h>
 
@@ -218,7 +219,7 @@
 
 	inf = dev->platform_data;
 
-	clk_enable(ohci->clk);
+	clk_prepare_enable(ohci->clk);
 
 	pxa27x_reset_hc(ohci);
 
@@ -268,7 +269,7 @@
 	__raw_writel(uhccoms, ohci->mmio_base + UHCCOMS);
 	udelay(10);
 
-	clk_disable(ohci->clk);
+	clk_disable_unprepare(ohci->clk);
 }
 
 
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 8ff6f7e..1b19aea 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -376,7 +376,7 @@
 	 * OTG controllers and transceivers need software interaction;
 	 * other external transceivers should be software-transparent
 	 */
-	struct otg_transceiver	*transceiver;
+	struct usb_phy	*transceiver;
 	void (*start_hnp)(struct ohci_hcd *ohci);
 
 	/*
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index e84ca19..2bf1320 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -2428,6 +2428,9 @@
 	int i;
 	unsigned long irq_trigger;
 
+	if (usb_disabled())
+		return -ENODEV;
+
 	if (pdev->dev.dma_mask) {
 		ret = -EINVAL;
 		dev_err(&pdev->dev, "dma not supported\n");
@@ -2552,20 +2555,4 @@
 	},
 };
 
-static int __init r8a66597_init(void)
-{
-	if (usb_disabled())
-		return -ENODEV;
-
-	printk(KERN_INFO KBUILD_MODNAME ": driver %s, %s\n", hcd_name,
-	       DRIVER_VERSION);
-	return platform_driver_register(&r8a66597_driver);
-}
-module_init(r8a66597_init);
-
-static void __exit r8a66597_cleanup(void)
-{
-	platform_driver_unregister(&r8a66597_driver);
-}
-module_exit(r8a66597_cleanup);
-
+module_platform_driver(r8a66597_driver);
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 961d663..2a2cce2 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1632,6 +1632,9 @@
 	u8			tmp, ioaddr = 0;
 	unsigned long		irqflags;
 
+	if (usb_disabled())
+		return -ENODEV;
+
 	/* basic sanity checks first.  board-specific init logic should
 	 * have initialized these three resources and probably board
 	 * specific platform_data.  we don't probe for IRQs, and do only
@@ -1817,20 +1820,4 @@
 };
 EXPORT_SYMBOL(sl811h_driver);
 
-/*-------------------------------------------------------------------------*/
-
-static int __init sl811h_init(void)
-{
-	if (usb_disabled())
-		return -ENODEV;
-
-	INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION);
-	return platform_driver_register(&sl811h_driver);
-}
-module_init(sl811h_init);
-
-static void __exit sl811h_cleanup(void)
-{
-	platform_driver_unregister(&sl811h_driver);
-}
-module_exit(sl811h_cleanup);
+module_platform_driver(sl811h_driver);
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 6b5eb10..e37dea8 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -565,6 +565,9 @@
 	struct dentry __maybe_unused *dentry;
 
 	hcd->uses_new_polling = 1;
+	/* Accept arbitrarily long scatter-gather lists */
+	if (!(hcd->driver->flags & HCD_LOCAL_MEM))
+		hcd->self.sg_tablesize = ~0;
 
 	spin_lock_init(&uhci->lock);
 	setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout,
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 557b6f3..673ad12 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -422,6 +422,32 @@
 	xhci_writel(xhci, temp, port_array[port_id]);
 }
 
+void xhci_set_remote_wake_mask(struct xhci_hcd *xhci,
+		__le32 __iomem **port_array, int port_id, u16 wake_mask)
+{
+	u32 temp;
+
+	temp = xhci_readl(xhci, port_array[port_id]);
+	temp = xhci_port_state_to_neutral(temp);
+
+	if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_CONNECT)
+		temp |= PORT_WKCONN_E;
+	else
+		temp &= ~PORT_WKCONN_E;
+
+	if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT)
+		temp |= PORT_WKDISC_E;
+	else
+		temp &= ~PORT_WKDISC_E;
+
+	if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT)
+		temp |= PORT_WKOC_E;
+	else
+		temp &= ~PORT_WKOC_E;
+
+	xhci_writel(xhci, temp, port_array[port_id]);
+}
+
 /* Test and clear port RWC bit */
 void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
 				int port_id, u32 port_bit)
@@ -448,6 +474,7 @@
 	int slot_id;
 	struct xhci_bus_state *bus_state;
 	u16 link_state = 0;
+	u16 wake_mask = 0;
 
 	max_ports = xhci_get_ports(hcd, &port_array);
 	bus_state = &xhci->bus_state[hcd_index(hcd)];
@@ -593,6 +620,8 @@
 	case SetPortFeature:
 		if (wValue == USB_PORT_FEAT_LINK_STATE)
 			link_state = (wIndex & 0xff00) >> 3;
+		if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK)
+			wake_mask = wIndex & 0xff00;
 		wIndex &= 0xff;
 		if (!wIndex || wIndex > max_ports)
 			goto error;
@@ -703,6 +732,14 @@
 			temp = xhci_readl(xhci, port_array[wIndex]);
 			xhci_dbg(xhci, "set port reset, actual port %d status  = 0x%x\n", wIndex, temp);
 			break;
+		case USB_PORT_FEAT_REMOTE_WAKE_MASK:
+			xhci_set_remote_wake_mask(xhci, port_array,
+					wIndex, wake_mask);
+			temp = xhci_readl(xhci, port_array[wIndex]);
+			xhci_dbg(xhci, "set port remote wake mask, "
+					"actual port %d status  = 0x%x\n",
+					wIndex, temp);
+			break;
 		case USB_PORT_FEAT_BH_PORT_RESET:
 			temp |= PORT_WR;
 			xhci_writel(xhci, temp, port_array[wIndex]);
@@ -883,6 +920,10 @@
 			t2 |= PORT_LINK_STROBE | XDEV_U3;
 			set_bit(port_index, &bus_state->bus_suspended);
 		}
+		/* USB core sets remote wake mask for USB 3.0 hubs,
+		 * including the USB 3.0 roothub, but only if CONFIG_USB_SUSPEND
+		 * is enabled, so also enable remote wake here.
+		 */
 		if (hcd->self.root_hub->do_remote_wakeup) {
 			if (t1 & PORT_CONNECT) {
 				t2 |= PORT_WKOC_E | PORT_WKDISC_E;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 383fc85..cae4c6f 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -34,10 +34,12 @@
  * Section 4.11.1.1:
  * "All components of all Command and Transfer TRBs shall be initialized to '0'"
  */
-static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, gfp_t flags)
+static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci,
+					unsigned int cycle_state, gfp_t flags)
 {
 	struct xhci_segment *seg;
 	dma_addr_t	dma;
+	int		i;
 
 	seg = kzalloc(sizeof *seg, flags);
 	if (!seg)
@@ -50,6 +52,11 @@
 	}
 
 	memset(seg->trbs, 0, SEGMENT_SIZE);
+	/* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */
+	if (cycle_state == 0) {
+		for (i = 0; i < TRBS_PER_SEGMENT; i++)
+			seg->trbs[i].link.control |= TRB_CYCLE;
+	}
 	seg->dma = dma;
 	seg->next = NULL;
 
@@ -65,6 +72,20 @@
 	kfree(seg);
 }
 
+static void xhci_free_segments_for_ring(struct xhci_hcd *xhci,
+				struct xhci_segment *first)
+{
+	struct xhci_segment *seg;
+
+	seg = first->next;
+	while (seg != first) {
+		struct xhci_segment *next = seg->next;
+		xhci_segment_free(xhci, seg);
+		seg = next;
+	}
+	xhci_segment_free(xhci, first);
+}
+
 /*
  * Make the prev segment point to the next segment.
  *
@@ -73,14 +94,14 @@
  * related flags, such as End TRB, Toggle Cycle, and no snoop.
  */
 static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
-		struct xhci_segment *next, bool link_trbs, bool isoc)
+		struct xhci_segment *next, enum xhci_ring_type type)
 {
 	u32 val;
 
 	if (!prev || !next)
 		return;
 	prev->next = next;
-	if (link_trbs) {
+	if (type != TYPE_EVENT) {
 		prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
 			cpu_to_le64(next->dma);
 
@@ -91,35 +112,55 @@
 		/* Always set the chain bit with 0.95 hardware */
 		/* Set chain bit for isoc rings on AMD 0.96 host */
 		if (xhci_link_trb_quirk(xhci) ||
-				(isoc && (xhci->quirks & XHCI_AMD_0x96_HOST)))
+				(type == TYPE_ISOC &&
+				 (xhci->quirks & XHCI_AMD_0x96_HOST)))
 			val |= TRB_CHAIN;
 		prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val);
 	}
 }
 
+/*
+ * Link the ring to the new segments.
+ * Set Toggle Cycle for the new ring if needed.
+ */
+static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring,
+		struct xhci_segment *first, struct xhci_segment *last,
+		unsigned int num_segs)
+{
+	struct xhci_segment *next;
+
+	if (!ring || !first || !last)
+		return;
+
+	next = ring->enq_seg->next;
+	xhci_link_segments(xhci, ring->enq_seg, first, ring->type);
+	xhci_link_segments(xhci, last, next, ring->type);
+	ring->num_segs += num_segs;
+	ring->num_trbs_free += (TRBS_PER_SEGMENT - 1) * num_segs;
+
+	if (ring->type != TYPE_EVENT && ring->enq_seg == ring->last_seg) {
+		ring->last_seg->trbs[TRBS_PER_SEGMENT-1].link.control
+			&= ~cpu_to_le32(LINK_TOGGLE);
+		last->trbs[TRBS_PER_SEGMENT-1].link.control
+			|= cpu_to_le32(LINK_TOGGLE);
+		ring->last_seg = last;
+	}
+}
+
 /* XXX: Do we need the hcd structure in all these functions? */
 void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
 {
-	struct xhci_segment *seg;
-	struct xhci_segment *first_seg;
-
 	if (!ring)
 		return;
-	if (ring->first_seg) {
-		first_seg = ring->first_seg;
-		seg = first_seg->next;
-		while (seg != first_seg) {
-			struct xhci_segment *next = seg->next;
-			xhci_segment_free(xhci, seg);
-			seg = next;
-		}
-		xhci_segment_free(xhci, first_seg);
-		ring->first_seg = NULL;
-	}
+
+	if (ring->first_seg)
+		xhci_free_segments_for_ring(xhci, ring->first_seg);
+
 	kfree(ring);
 }
 
-static void xhci_initialize_ring_info(struct xhci_ring *ring)
+static void xhci_initialize_ring_info(struct xhci_ring *ring,
+					unsigned int cycle_state)
 {
 	/* The ring is empty, so the enqueue pointer == dequeue pointer */
 	ring->enqueue = ring->first_seg->trbs;
@@ -129,11 +170,53 @@
 	/* The ring is initialized to 0. The producer must write 1 to the cycle
 	 * bit to handover ownership of the TRB, so PCS = 1.  The consumer must
 	 * compare CCS to the cycle bit to check ownership, so CCS = 1.
+	 *
+	 * New rings are initialized with cycle state equal to 1; if we are
+	 * handling ring expansion, set the cycle state equal to the old ring.
 	 */
-	ring->cycle_state = 1;
+	ring->cycle_state = cycle_state;
 	/* Not necessary for new rings, but needed for re-initialized rings */
 	ring->enq_updates = 0;
 	ring->deq_updates = 0;
+
+	/*
+	 * Each segment has a link TRB, and leave an extra TRB for SW
+	 * accounting purpose
+	 */
+	ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1;
+}
+
+/* Allocate segments and link them for a ring */
+static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
+		struct xhci_segment **first, struct xhci_segment **last,
+		unsigned int num_segs, unsigned int cycle_state,
+		enum xhci_ring_type type, gfp_t flags)
+{
+	struct xhci_segment *prev;
+
+	prev = xhci_segment_alloc(xhci, cycle_state, flags);
+	if (!prev)
+		return -ENOMEM;
+	num_segs--;
+
+	*first = prev;
+	while (num_segs > 0) {
+		struct xhci_segment	*next;
+
+		next = xhci_segment_alloc(xhci, cycle_state, flags);
+		if (!next) {
+			xhci_free_segments_for_ring(xhci, *first);
+			return -ENOMEM;
+		}
+		xhci_link_segments(xhci, prev, next, type);
+
+		prev = next;
+		num_segs--;
+	}
+	xhci_link_segments(xhci, prev, *first, type);
+	*last = prev;
+
+	return 0;
 }
 
 /**
@@ -144,44 +227,34 @@
  * See section 4.9.1 and figures 15 and 16.
  */
 static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
-		unsigned int num_segs, bool link_trbs, bool isoc, gfp_t flags)
+		unsigned int num_segs, unsigned int cycle_state,
+		enum xhci_ring_type type, gfp_t flags)
 {
 	struct xhci_ring	*ring;
-	struct xhci_segment	*prev;
+	int ret;
 
 	ring = kzalloc(sizeof *(ring), flags);
 	if (!ring)
 		return NULL;
 
+	ring->num_segs = num_segs;
 	INIT_LIST_HEAD(&ring->td_list);
+	ring->type = type;
 	if (num_segs == 0)
 		return ring;
 
-	ring->first_seg = xhci_segment_alloc(xhci, flags);
-	if (!ring->first_seg)
+	ret = xhci_alloc_segments_for_ring(xhci, &ring->first_seg,
+			&ring->last_seg, num_segs, cycle_state, type, flags);
+	if (ret)
 		goto fail;
-	num_segs--;
 
-	prev = ring->first_seg;
-	while (num_segs > 0) {
-		struct xhci_segment	*next;
-
-		next = xhci_segment_alloc(xhci, flags);
-		if (!next)
-			goto fail;
-		xhci_link_segments(xhci, prev, next, link_trbs, isoc);
-
-		prev = next;
-		num_segs--;
-	}
-	xhci_link_segments(xhci, prev, ring->first_seg, link_trbs, isoc);
-
-	if (link_trbs) {
+	/* Only event ring does not use link TRB */
+	if (type != TYPE_EVENT) {
 		/* See section 4.9.2.1 and 6.4.4.1 */
-		prev->trbs[TRBS_PER_SEGMENT-1].link.control |=
+		ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |=
 			cpu_to_le32(LINK_TOGGLE);
 	}
-	xhci_initialize_ring_info(ring);
+	xhci_initialize_ring_info(ring, cycle_state);
 	return ring;
 
 fail:
@@ -217,23 +290,64 @@
  * pointers to the beginning of the ring.
  */
 static void xhci_reinit_cached_ring(struct xhci_hcd *xhci,
-		struct xhci_ring *ring, bool isoc)
+			struct xhci_ring *ring, unsigned int cycle_state,
+			enum xhci_ring_type type)
 {
 	struct xhci_segment	*seg = ring->first_seg;
+	int i;
+
 	do {
 		memset(seg->trbs, 0,
 				sizeof(union xhci_trb)*TRBS_PER_SEGMENT);
+		if (cycle_state == 0) {
+			for (i = 0; i < TRBS_PER_SEGMENT; i++)
+				seg->trbs[i].link.control |= TRB_CYCLE;
+		}
 		/* All endpoint rings have link TRBs */
-		xhci_link_segments(xhci, seg, seg->next, 1, isoc);
+		xhci_link_segments(xhci, seg, seg->next, type);
 		seg = seg->next;
 	} while (seg != ring->first_seg);
-	xhci_initialize_ring_info(ring);
+	ring->type = type;
+	xhci_initialize_ring_info(ring, cycle_state);
 	/* td list should be empty since all URBs have been cancelled,
 	 * but just in case...
 	 */
 	INIT_LIST_HEAD(&ring->td_list);
 }
 
+/*
+ * Expand an existing ring.
+ * Look for a cached ring or allocate a new ring which has same segment numbers
+ * and link the two rings.
+ */
+int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
+				unsigned int num_trbs, gfp_t flags)
+{
+	struct xhci_segment	*first;
+	struct xhci_segment	*last;
+	unsigned int		num_segs;
+	unsigned int		num_segs_needed;
+	int			ret;
+
+	num_segs_needed = (num_trbs + (TRBS_PER_SEGMENT - 1) - 1) /
+				(TRBS_PER_SEGMENT - 1);
+
+	/* Allocate number of segments we needed, or double the ring size */
+	num_segs = ring->num_segs > num_segs_needed ?
+			ring->num_segs : num_segs_needed;
+
+	ret = xhci_alloc_segments_for_ring(xhci, &first, &last,
+			num_segs, ring->cycle_state, ring->type, flags);
+	if (ret)
+		return -ENOMEM;
+
+	xhci_link_rings(xhci, ring, first, last, num_segs);
+	xhci_dbg(xhci, "ring expansion succeed, now has %d segments\n",
+			ring->num_segs);
+
+	return 0;
+}
+
 #define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32)
 
 static struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci,
@@ -528,7 +642,7 @@
 	 */
 	for (cur_stream = 1; cur_stream < num_streams; cur_stream++) {
 		stream_info->stream_rings[cur_stream] =
-			xhci_ring_alloc(xhci, 1, true, false, mem_flags);
+			xhci_ring_alloc(xhci, 2, 1, TYPE_STREAM, mem_flags);
 		cur_ring = stream_info->stream_rings[cur_stream];
 		if (!cur_ring)
 			goto cleanup_rings;
@@ -862,7 +976,7 @@
 	}
 
 	/* Allocate endpoint 0 ring */
-	dev->eps[0].ring = xhci_ring_alloc(xhci, 1, true, false, flags);
+	dev->eps[0].ring = xhci_ring_alloc(xhci, 2, 1, TYPE_CTRL, flags);
 	if (!dev->eps[0].ring)
 		goto fail;
 
@@ -1300,24 +1414,16 @@
 	struct xhci_ring *ep_ring;
 	unsigned int max_packet;
 	unsigned int max_burst;
+	enum xhci_ring_type type;
 	u32 max_esit_payload;
 
 	ep_index = xhci_get_endpoint_index(&ep->desc);
 	ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
 
+	type = usb_endpoint_type(&ep->desc);
 	/* Set up the endpoint ring */
-	/*
-	 * Isochronous endpoint ring needs bigger size because one isoc URB
-	 * carries multiple packets and it will insert multiple tds to the
-	 * ring.
-	 * This should be replaced with dynamic ring resizing in the future.
-	 */
-	if (usb_endpoint_xfer_isoc(&ep->desc))
-		virt_dev->eps[ep_index].new_ring =
-			xhci_ring_alloc(xhci, 8, true, true, mem_flags);
-	else
-		virt_dev->eps[ep_index].new_ring =
-			xhci_ring_alloc(xhci, 1, true, false, mem_flags);
+	virt_dev->eps[ep_index].new_ring =
+		xhci_ring_alloc(xhci, 2, 1, type, mem_flags);
 	if (!virt_dev->eps[ep_index].new_ring) {
 		/* Attempt to use the ring cache */
 		if (virt_dev->num_rings_cached == 0)
@@ -1327,7 +1433,7 @@
 		virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL;
 		virt_dev->num_rings_cached--;
 		xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring,
-			usb_endpoint_xfer_isoc(&ep->desc) ? true : false);
+					1, type);
 	}
 	virt_dev->eps[ep_index].skip = false;
 	ep_ring = virt_dev->eps[ep_index].new_ring;
@@ -2157,7 +2263,7 @@
 	unsigned int	val, val2;
 	u64		val_64;
 	struct xhci_segment	*seg;
-	u32 page_size;
+	u32 page_size, temp;
 	int i;
 
 	page_size = xhci_readl(xhci, &xhci->op_regs->page_size);
@@ -2235,7 +2341,7 @@
 		goto fail;
 
 	/* Set up the command ring to have one segments for now. */
-	xhci->cmd_ring = xhci_ring_alloc(xhci, 1, true, false, flags);
+	xhci->cmd_ring = xhci_ring_alloc(xhci, 1, 1, TYPE_COMMAND, flags);
 	if (!xhci->cmd_ring)
 		goto fail;
 	xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring);
@@ -2266,7 +2372,7 @@
 	 * the event ring segment table (ERST).  Section 4.9.3.
 	 */
 	xhci_dbg(xhci, "// Allocating event ring\n");
-	xhci->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, false, false,
+	xhci->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, 1, TYPE_EVENT,
 						flags);
 	if (!xhci->event_ring)
 		goto fail;
@@ -2340,6 +2446,15 @@
 
 	INIT_LIST_HEAD(&xhci->lpm_failed_devs);
 
+	/* Enable USB 3.0 device notifications for function remote wake, which
+	 * is necessary for allowing USB 3.0 devices to do remote wakeup from
+	 * U3 (device suspend).
+	 */
+	temp = xhci_readl(xhci, &xhci->op_regs->dev_notification);
+	temp &= ~DEV_NOTE_MASK;
+	temp |= DEV_NOTE_FWAKE;
+	xhci_writel(xhci, temp, &xhci->op_regs->dev_notification);
+
 	return 0;
 
 fail:
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
new file mode 100644
index 0000000..689bc18
--- /dev/null
+++ b/drivers/usb/host/xhci-plat.c
@@ -0,0 +1,205 @@
+/*
+ * xhci-plat.c - xHCI host controller driver platform Bus Glue.
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ *
+ * A lot of code borrowed from the Linux xHCI driver.
+ *
+ * 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/platform_device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "xhci.h"
+
+static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
+{
+	/*
+	 * As of now platform drivers don't provide MSI support so we ensure
+	 * here that the generic code does not try to make a pci_dev from our
+	 * dev struct in order to setup MSI
+	 */
+	xhci->quirks |= XHCI_BROKEN_MSI;
+}
+
+/* called during probe() after chip reset completes */
+static int xhci_plat_setup(struct usb_hcd *hcd)
+{
+	return xhci_gen_setup(hcd, xhci_plat_quirks);
+}
+
+static const struct hc_driver xhci_plat_xhci_driver = {
+	.description =		"xhci-hcd",
+	.product_desc =		"xHCI Host Controller",
+	.hcd_priv_size =	sizeof(struct xhci_hcd *),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq =			xhci_irq,
+	.flags =		HCD_MEMORY | HCD_USB3 | HCD_SHARED,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset =		xhci_plat_setup,
+	.start =		xhci_run,
+	.stop =			xhci_stop,
+	.shutdown =		xhci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue =		xhci_urb_enqueue,
+	.urb_dequeue =		xhci_urb_dequeue,
+	.alloc_dev =		xhci_alloc_dev,
+	.free_dev =		xhci_free_dev,
+	.alloc_streams =	xhci_alloc_streams,
+	.free_streams =		xhci_free_streams,
+	.add_endpoint =		xhci_add_endpoint,
+	.drop_endpoint =	xhci_drop_endpoint,
+	.endpoint_reset =	xhci_endpoint_reset,
+	.check_bandwidth =	xhci_check_bandwidth,
+	.reset_bandwidth =	xhci_reset_bandwidth,
+	.address_device =	xhci_address_device,
+	.update_hub_device =	xhci_update_hub_device,
+	.reset_device =		xhci_discover_or_reset_device,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number =	xhci_get_frame,
+
+	/* Root hub support */
+	.hub_control =		xhci_hub_control,
+	.hub_status_data =	xhci_hub_status_data,
+	.bus_suspend =		xhci_bus_suspend,
+	.bus_resume =		xhci_bus_resume,
+};
+
+static int xhci_plat_probe(struct platform_device *pdev)
+{
+	const struct hc_driver	*driver;
+	struct xhci_hcd		*xhci;
+	struct resource         *res;
+	struct usb_hcd		*hcd;
+	int			ret;
+	int			irq;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	driver = &xhci_plat_xhci_driver;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+				driver->description)) {
+		dev_dbg(&pdev->dev, "controller already in use\n");
+		ret = -EBUSY;
+		goto put_hcd;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		dev_dbg(&pdev->dev, "error mapping memory\n");
+		ret = -EFAULT;
+		goto release_mem_region;
+	}
+
+	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (ret)
+		goto unmap_registers;
+
+	/* USB 2.0 roothub is stored in the platform_device now. */
+	hcd = dev_get_drvdata(&pdev->dev);
+	xhci = hcd_to_xhci(hcd);
+	xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev,
+			dev_name(&pdev->dev), hcd);
+	if (!xhci->shared_hcd) {
+		ret = -ENOMEM;
+		goto dealloc_usb2_hcd;
+	}
+
+	/*
+	 * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset)
+	 * is called by usb_add_hcd().
+	 */
+	*((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci;
+
+	ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
+	if (ret)
+		goto put_usb3_hcd;
+
+	return 0;
+
+put_usb3_hcd:
+	usb_put_hcd(xhci->shared_hcd);
+
+dealloc_usb2_hcd:
+	usb_remove_hcd(hcd);
+
+unmap_registers:
+	iounmap(hcd->regs);
+
+release_mem_region:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+put_hcd:
+	usb_put_hcd(hcd);
+
+	return ret;
+}
+
+static int xhci_plat_remove(struct platform_device *dev)
+{
+	struct usb_hcd	*hcd = platform_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+
+	usb_remove_hcd(xhci->shared_hcd);
+	usb_put_hcd(xhci->shared_hcd);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	usb_put_hcd(hcd);
+	kfree(xhci);
+
+	return 0;
+}
+
+static struct platform_driver usb_xhci_driver = {
+	.probe	= xhci_plat_probe,
+	.remove	= xhci_plat_remove,
+	.driver	= {
+		.name = "xhci-hcd",
+	},
+};
+MODULE_ALIAS("platform:xhci-hcd");
+
+int xhci_register_plat(void)
+{
+	return platform_driver_register(&usb_xhci_driver);
+}
+
+void xhci_unregister_plat(void)
+{
+	platform_driver_unregister(&usb_xhci_driver);
+}
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b62037b..6bd9d53 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -143,17 +143,25 @@
  * See Cycle bit rules. SW is the consumer for the event ring only.
  * Don't make a ring full of link TRBs.  That would be dumb and this would loop.
  */
-static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
+static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
 {
-	union xhci_trb *next = ++(ring->dequeue);
+	union xhci_trb *next;
 	unsigned long long addr;
 
 	ring->deq_updates++;
+
+	/* If this is not event ring, there is one more usable TRB */
+	if (ring->type != TYPE_EVENT &&
+			!last_trb(xhci, ring, ring->deq_seg, ring->dequeue))
+		ring->num_trbs_free++;
+	next = ++(ring->dequeue);
+
 	/* Update the dequeue pointer further if that was a link TRB or we're at
 	 * the end of an event ring segment (which doesn't have link TRBS)
 	 */
 	while (last_trb(xhci, ring, ring->deq_seg, next)) {
-		if (consumer && last_trb_on_last_seg(xhci, ring, ring->deq_seg, next)) {
+		if (ring->type == TYPE_EVENT &&	last_trb_on_last_seg(xhci,
+				ring, ring->deq_seg, next)) {
 			ring->cycle_state = (ring->cycle_state ? 0 : 1);
 		}
 		ring->deq_seg = ring->deq_seg->next;
@@ -181,13 +189,17 @@
  *			prepare_transfer()?
  */
 static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
-		bool consumer, bool more_trbs_coming, bool isoc)
+			bool more_trbs_coming)
 {
 	u32 chain;
 	union xhci_trb *next;
 	unsigned long long addr;
 
 	chain = le32_to_cpu(ring->enqueue->generic.field[3]) & TRB_CHAIN;
+	/* If this is not event ring, there is one less usable TRB */
+	if (ring->type != TYPE_EVENT &&
+			!last_trb(xhci, ring, ring->enq_seg, ring->enqueue))
+		ring->num_trbs_free--;
 	next = ++(ring->enqueue);
 
 	ring->enq_updates++;
@@ -195,35 +207,35 @@
 	 * the end of an event ring segment (which doesn't have link TRBS)
 	 */
 	while (last_trb(xhci, ring, ring->enq_seg, next)) {
-		if (!consumer) {
-			if (ring != xhci->event_ring) {
-				/*
-				 * If the caller doesn't plan on enqueueing more
-				 * TDs before ringing the doorbell, then we
-				 * don't want to give the link TRB to the
-				 * hardware just yet.  We'll give the link TRB
-				 * back in prepare_ring() just before we enqueue
-				 * the TD at the top of the ring.
-				 */
-				if (!chain && !more_trbs_coming)
-					break;
+		if (ring->type != TYPE_EVENT) {
+			/*
+			 * If the caller doesn't plan on enqueueing more
+			 * TDs before ringing the doorbell, then we
+			 * don't want to give the link TRB to the
+			 * hardware just yet.  We'll give the link TRB
+			 * back in prepare_ring() just before we enqueue
+			 * the TD at the top of the ring.
+			 */
+			if (!chain && !more_trbs_coming)
+				break;
 
-				/* If we're not dealing with 0.95 hardware or
-				 * isoc rings on AMD 0.96 host,
-				 * carry over the chain bit of the previous TRB
-				 * (which may mean the chain bit is cleared).
-				 */
-				if (!(isoc && (xhci->quirks & XHCI_AMD_0x96_HOST))
+			/* If we're not dealing with 0.95 hardware or
+			 * isoc rings on AMD 0.96 host,
+			 * carry over the chain bit of the previous TRB
+			 * (which may mean the chain bit is cleared).
+			 */
+			if (!(ring->type == TYPE_ISOC &&
+					(xhci->quirks & XHCI_AMD_0x96_HOST))
 						&& !xhci_link_trb_quirk(xhci)) {
-					next->link.control &=
-						cpu_to_le32(~TRB_CHAIN);
-					next->link.control |=
-						cpu_to_le32(chain);
-				}
-				/* Give this link TRB to the hardware */
-				wmb();
-				next->link.control ^= cpu_to_le32(TRB_CYCLE);
+				next->link.control &=
+					cpu_to_le32(~TRB_CHAIN);
+				next->link.control |=
+					cpu_to_le32(chain);
 			}
+			/* Give this link TRB to the hardware */
+			wmb();
+			next->link.control ^= cpu_to_le32(TRB_CYCLE);
+
 			/* Toggle the cycle bit after the last ring segment. */
 			if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
 				ring->cycle_state = (ring->cycle_state ? 0 : 1);
@@ -237,55 +249,23 @@
 }
 
 /*
- * Check to see if there's room to enqueue num_trbs on the ring.  See rules
- * above.
- * FIXME: this would be simpler and faster if we just kept track of the number
- * of free TRBs in a ring.
+ * Check to see if there's room to enqueue num_trbs on the ring and make sure
+ * enqueue pointer will not advance into dequeue segment. See rules above.
  */
-static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
+static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
 		unsigned int num_trbs)
 {
-	int i;
-	union xhci_trb *enq = ring->enqueue;
-	struct xhci_segment *enq_seg = ring->enq_seg;
-	struct xhci_segment *cur_seg;
-	unsigned int left_on_ring;
+	int num_trbs_in_deq_seg;
 
-	/* If we are currently pointing to a link TRB, advance the
-	 * enqueue pointer before checking for space */
-	while (last_trb(xhci, ring, enq_seg, enq)) {
-		enq_seg = enq_seg->next;
-		enq = enq_seg->trbs;
-	}
+	if (ring->num_trbs_free < num_trbs)
+		return 0;
 
-	/* Check if ring is empty */
-	if (enq == ring->dequeue) {
-		/* Can't use link trbs */
-		left_on_ring = TRBS_PER_SEGMENT - 1;
-		for (cur_seg = enq_seg->next; cur_seg != enq_seg;
-				cur_seg = cur_seg->next)
-			left_on_ring += TRBS_PER_SEGMENT - 1;
-
-		/* Always need one TRB free in the ring. */
-		left_on_ring -= 1;
-		if (num_trbs > left_on_ring) {
-			xhci_warn(xhci, "Not enough room on ring; "
-					"need %u TRBs, %u TRBs left\n",
-					num_trbs, left_on_ring);
+	if (ring->type != TYPE_COMMAND && ring->type != TYPE_EVENT) {
+		num_trbs_in_deq_seg = ring->dequeue - ring->deq_seg->trbs;
+		if (ring->num_trbs_free < num_trbs + num_trbs_in_deq_seg)
 			return 0;
-		}
-		return 1;
 	}
-	/* Make sure there's an extra empty TRB available */
-	for (i = 0; i <= num_trbs; ++i) {
-		if (enq == ring->dequeue)
-			return 0;
-		enq++;
-		while (last_trb(xhci, ring, enq_seg, enq)) {
-			enq_seg = enq_seg->next;
-			enq = enq_seg->trbs;
-		}
-	}
+
 	return 1;
 }
 
@@ -892,6 +872,43 @@
 	xhci_dbg(xhci, "xHCI host controller is dead.\n");
 }
 
+
+static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci,
+		struct xhci_virt_device *dev,
+		struct xhci_ring *ep_ring,
+		unsigned int ep_index)
+{
+	union xhci_trb *dequeue_temp;
+	int num_trbs_free_temp;
+	bool revert = false;
+
+	num_trbs_free_temp = ep_ring->num_trbs_free;
+	dequeue_temp = ep_ring->dequeue;
+
+	while (ep_ring->dequeue != dev->eps[ep_index].queued_deq_ptr) {
+		/* We have more usable TRBs */
+		ep_ring->num_trbs_free++;
+		ep_ring->dequeue++;
+		if (last_trb(xhci, ep_ring, ep_ring->deq_seg,
+				ep_ring->dequeue)) {
+			if (ep_ring->dequeue ==
+					dev->eps[ep_index].queued_deq_ptr)
+				break;
+			ep_ring->deq_seg = ep_ring->deq_seg->next;
+			ep_ring->dequeue = ep_ring->deq_seg->trbs;
+		}
+		if (ep_ring->dequeue == dequeue_temp) {
+			revert = true;
+			break;
+		}
+	}
+
+	if (revert) {
+		xhci_dbg(xhci, "Unable to find new dequeue pointer\n");
+		ep_ring->num_trbs_free = num_trbs_free_temp;
+	}
+}
+
 /*
  * When we get a completion for a Set Transfer Ring Dequeue Pointer command,
  * we need to clear the set deq pending flag in the endpoint ring state, so that
@@ -973,8 +990,8 @@
 			/* Update the ring's dequeue segment and dequeue pointer
 			 * to reflect the new position.
 			 */
-			ep_ring->deq_seg = dev->eps[ep_index].queued_deq_seg;
-			ep_ring->dequeue = dev->eps[ep_index].queued_deq_ptr;
+			update_ring_for_set_deq_completion(xhci, dev,
+				ep_ring, ep_index);
 		} else {
 			xhci_warn(xhci, "Mismatch between completed Set TR Deq "
 					"Ptr command & xHCI internal state.\n");
@@ -1185,7 +1202,7 @@
 		xhci->error_bitmask |= 1 << 6;
 		break;
 	}
-	inc_deq(xhci, xhci->cmd_ring, false);
+	inc_deq(xhci, xhci->cmd_ring);
 }
 
 static void handle_vendor_event(struct xhci_hcd *xhci,
@@ -1237,6 +1254,26 @@
 	return num_similar_speed_ports;
 }
 
+static void handle_device_notification(struct xhci_hcd *xhci,
+		union xhci_trb *event)
+{
+	u32 slot_id;
+	struct usb_device *udev;
+
+	slot_id = TRB_TO_SLOT_ID(event->generic.field[3]);
+	if (!xhci->devs[slot_id]) {
+		xhci_warn(xhci, "Device Notification event for "
+				"unused slot %u\n", slot_id);
+		return;
+	}
+
+	xhci_dbg(xhci, "Device Wake Notification event for slot ID %u\n",
+			slot_id);
+	udev = xhci->devs[slot_id]->udev;
+	if (udev && udev->parent)
+		usb_wakeup_notification(udev->parent, udev->portnum);
+}
+
 static void handle_port_status(struct xhci_hcd *xhci,
 		union xhci_trb *event)
 {
@@ -1321,20 +1358,21 @@
 		}
 
 		if (DEV_SUPERSPEED(temp)) {
-			xhci_dbg(xhci, "resume SS port %d\n", port_id);
+			xhci_dbg(xhci, "remote wake SS port %d\n", port_id);
+			/* Set a flag to say the port signaled remote wakeup,
+			 * so we can tell the difference between the end of
+			 * device and host initiated resume.
+			 */
+			bus_state->port_remote_wakeup |= 1 << faked_port_index;
+			xhci_test_and_clear_bit(xhci, port_array,
+					faked_port_index, PORT_PLC);
 			xhci_set_link_state(xhci, port_array, faked_port_index,
 						XDEV_U0);
-			slot_id = xhci_find_slot_id_by_port(hcd, xhci,
-					faked_port_index + 1);
-			if (!slot_id) {
-				xhci_dbg(xhci, "slot_id is zero\n");
-				goto cleanup;
-			}
-			xhci_ring_device(xhci, slot_id);
-			xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
-			/* Clear PORT_PLC */
-			xhci_test_and_clear_bit(xhci, port_array,
-						faked_port_index, PORT_PLC);
+			/* Need to wait until the next link state change
+			 * indicates the device is actually in U0.
+			 */
+			bogus_port_status = true;
+			goto cleanup;
 		} else {
 			xhci_dbg(xhci, "resume HS port %d\n", port_id);
 			bus_state->resume_done[faked_port_index] = jiffies +
@@ -1345,13 +1383,39 @@
 		}
 	}
 
+	if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_U0 &&
+			DEV_SUPERSPEED(temp)) {
+		xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
+		/* We've just brought the device into U0 through either the
+		 * Resume state after a device remote wakeup, or through the
+		 * U3Exit state after a host-initiated resume.  If it's a device
+		 * initiated remote wake, don't pass up the link state change,
+		 * so the roothub behavior is consistent with external
+		 * USB 3.0 hub behavior.
+		 */
+		slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+				faked_port_index + 1);
+		if (slot_id && xhci->devs[slot_id])
+			xhci_ring_device(xhci, slot_id);
+		if (bus_state->port_remote_wakeup && (1 << faked_port_index)) {
+			bus_state->port_remote_wakeup &=
+				~(1 << faked_port_index);
+			xhci_test_and_clear_bit(xhci, port_array,
+					faked_port_index, PORT_PLC);
+			usb_wakeup_notification(hcd->self.root_hub,
+					faked_port_index + 1);
+			bogus_port_status = true;
+			goto cleanup;
+		}
+	}
+
 	if (hcd->speed != HCD_USB3)
 		xhci_test_and_clear_bit(xhci, port_array, faked_port_index,
 					PORT_PLC);
 
 cleanup:
 	/* Update event ring dequeue pointer before dropping the lock */
-	inc_deq(xhci, xhci->event_ring, true);
+	inc_deq(xhci, xhci->event_ring);
 
 	/* Don't make the USB core poll the roothub if we got a bad port status
 	 * change event.  Besides, at that point we can't tell which roothub
@@ -1546,8 +1610,8 @@
 		} else {
 			/* Update ring dequeue pointer */
 			while (ep_ring->dequeue != td->last_trb)
-				inc_deq(xhci, ep_ring, false);
-			inc_deq(xhci, ep_ring, false);
+				inc_deq(xhci, ep_ring);
+			inc_deq(xhci, ep_ring);
 		}
 
 td_cleanup:
@@ -1795,8 +1859,8 @@
 
 	/* Update ring dequeue pointer */
 	while (ep_ring->dequeue != td->last_trb)
-		inc_deq(xhci, ep_ring, false);
-	inc_deq(xhci, ep_ring, false);
+		inc_deq(xhci, ep_ring);
+	inc_deq(xhci, ep_ring);
 
 	return finish_td(xhci, td, NULL, event, ep, status, true);
 }
@@ -2183,7 +2247,7 @@
 		 * Will roll back to continue process missed tds.
 		 */
 		if (trb_comp_code == COMP_MISSED_INT || !ep->skip) {
-			inc_deq(xhci, xhci->event_ring, true);
+			inc_deq(xhci, xhci->event_ring);
 		}
 
 		if (ret) {
@@ -2277,6 +2341,9 @@
 		else
 			update_ptrs = 0;
 		break;
+	case TRB_TYPE(TRB_DEV_NOTE):
+		handle_device_notification(xhci, event);
+		break;
 	default:
 		if ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK) >=
 		    TRB_TYPE(48))
@@ -2295,7 +2362,7 @@
 
 	if (update_ptrs)
 		/* Update SW event ring dequeue pointer */
-		inc_deq(xhci, xhci->event_ring, true);
+		inc_deq(xhci, xhci->event_ring);
 
 	/* Are there more items on the event ring?  Caller will call us again to
 	 * check.
@@ -2346,7 +2413,7 @@
 	/* FIXME when MSI-X is supported and there are multiple vectors */
 	/* Clear the MSI-X event interrupt status */
 
-	if (hcd->irq != -1) {
+	if (hcd->irq) {
 		u32 irq_pending;
 		/* Acknowledge the PCI interrupt */
 		irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
@@ -2411,7 +2478,7 @@
  *			prepare_transfer()?
  */
 static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
-		bool consumer, bool more_trbs_coming, bool isoc,
+		bool more_trbs_coming,
 		u32 field1, u32 field2, u32 field3, u32 field4)
 {
 	struct xhci_generic_trb *trb;
@@ -2421,7 +2488,7 @@
 	trb->field[1] = cpu_to_le32(field2);
 	trb->field[2] = cpu_to_le32(field3);
 	trb->field[3] = cpu_to_le32(field4);
-	inc_enq(xhci, ring, consumer, more_trbs_coming, isoc);
+	inc_enq(xhci, ring, more_trbs_coming);
 }
 
 /*
@@ -2429,8 +2496,10 @@
  * FIXME allocate segments if the ring is full.
  */
 static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
-		u32 ep_state, unsigned int num_trbs, bool isoc, gfp_t mem_flags)
+		u32 ep_state, unsigned int num_trbs, gfp_t mem_flags)
 {
+	unsigned int num_trbs_needed;
+
 	/* Make sure the endpoint has been added to xHC schedule */
 	switch (ep_state) {
 	case EP_STATE_DISABLED:
@@ -2458,11 +2527,25 @@
 		 */
 		return -EINVAL;
 	}
-	if (!room_on_ring(xhci, ep_ring, num_trbs)) {
-		/* FIXME allocate more room */
-		xhci_err(xhci, "ERROR no room on ep ring\n");
-		return -ENOMEM;
-	}
+
+	while (1) {
+		if (room_on_ring(xhci, ep_ring, num_trbs))
+			break;
+
+		if (ep_ring == xhci->cmd_ring) {
+			xhci_err(xhci, "Do not support expand command ring\n");
+			return -ENOMEM;
+		}
+
+		xhci_dbg(xhci, "ERROR no room on ep ring, "
+					"try ring expansion\n");
+		num_trbs_needed = num_trbs - ep_ring->num_trbs_free;
+		if (xhci_ring_expansion(xhci, ep_ring, num_trbs_needed,
+					mem_flags)) {
+			xhci_err(xhci, "Ring expansion failed\n");
+			return -ENOMEM;
+		}
+	};
 
 	if (enqueue_is_link_trb(ep_ring)) {
 		struct xhci_ring *ring = ep_ring;
@@ -2474,8 +2557,9 @@
 			/* If we're not dealing with 0.95 hardware or isoc rings
 			 * on AMD 0.96 host, clear the chain bit.
 			 */
-			if (!xhci_link_trb_quirk(xhci) && !(isoc &&
-					(xhci->quirks & XHCI_AMD_0x96_HOST)))
+			if (!xhci_link_trb_quirk(xhci) &&
+					!(ring->type == TYPE_ISOC &&
+					 (xhci->quirks & XHCI_AMD_0x96_HOST)))
 				next->link.control &= cpu_to_le32(~TRB_CHAIN);
 			else
 				next->link.control |= cpu_to_le32(TRB_CHAIN);
@@ -2503,7 +2587,6 @@
 		unsigned int num_trbs,
 		struct urb *urb,
 		unsigned int td_index,
-		bool isoc,
 		gfp_t mem_flags)
 {
 	int ret;
@@ -2521,7 +2604,7 @@
 
 	ret = prepare_ring(xhci, ep_ring,
 			   le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK,
-			   num_trbs, isoc, mem_flags);
+			   num_trbs, mem_flags);
 	if (ret)
 		return ret;
 
@@ -2731,7 +2814,7 @@
 
 	trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
 			ep_index, urb->stream_id,
-			num_trbs, urb, 0, false, mem_flags);
+			num_trbs, urb, 0, mem_flags);
 	if (trb_buff_len < 0)
 		return trb_buff_len;
 
@@ -2819,7 +2902,7 @@
 			more_trbs_coming = true;
 		else
 			more_trbs_coming = false;
-		queue_trb(xhci, ep_ring, false, more_trbs_coming, false,
+		queue_trb(xhci, ep_ring, more_trbs_coming,
 				lower_32_bits(addr),
 				upper_32_bits(addr),
 				length_field,
@@ -2901,7 +2984,7 @@
 
 	ret = prepare_transfer(xhci, xhci->devs[slot_id],
 			ep_index, urb->stream_id,
-			num_trbs, urb, 0, false, mem_flags);
+			num_trbs, urb, 0, mem_flags);
 	if (ret < 0)
 		return ret;
 
@@ -2973,7 +3056,7 @@
 			more_trbs_coming = true;
 		else
 			more_trbs_coming = false;
-		queue_trb(xhci, ep_ring, false, more_trbs_coming, false,
+		queue_trb(xhci, ep_ring, more_trbs_coming,
 				lower_32_bits(addr),
 				upper_32_bits(addr),
 				length_field,
@@ -3030,7 +3113,7 @@
 		num_trbs++;
 	ret = prepare_transfer(xhci, xhci->devs[slot_id],
 			ep_index, urb->stream_id,
-			num_trbs, urb, 0, false, mem_flags);
+			num_trbs, urb, 0, mem_flags);
 	if (ret < 0)
 		return ret;
 
@@ -3063,7 +3146,7 @@
 		}
 	}
 
-	queue_trb(xhci, ep_ring, false, true, false,
+	queue_trb(xhci, ep_ring, true,
 		  setup->bRequestType | setup->bRequest << 8 | le16_to_cpu(setup->wValue) << 16,
 		  le16_to_cpu(setup->wIndex) | le16_to_cpu(setup->wLength) << 16,
 		  TRB_LEN(8) | TRB_INTR_TARGET(0),
@@ -3083,7 +3166,7 @@
 	if (urb->transfer_buffer_length > 0) {
 		if (setup->bRequestType & USB_DIR_IN)
 			field |= TRB_DIR_IN;
-		queue_trb(xhci, ep_ring, false, true, false,
+		queue_trb(xhci, ep_ring, true,
 				lower_32_bits(urb->transfer_dma),
 				upper_32_bits(urb->transfer_dma),
 				length_field,
@@ -3099,7 +3182,7 @@
 		field = 0;
 	else
 		field = TRB_DIR_IN;
-	queue_trb(xhci, ep_ring, false, false, false,
+	queue_trb(xhci, ep_ring, false,
 			0,
 			0,
 			TRB_INTR_TARGET(0),
@@ -3239,8 +3322,7 @@
 		trbs_per_td = count_isoc_trbs_needed(xhci, urb, i);
 
 		ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index,
-				urb->stream_id, trbs_per_td, urb, i, true,
-				mem_flags);
+				urb->stream_id, trbs_per_td, urb, i, mem_flags);
 		if (ret < 0) {
 			if (i == 0)
 				return ret;
@@ -3310,7 +3392,7 @@
 				remainder |
 				TRB_INTR_TARGET(0);
 
-			queue_trb(xhci, ep_ring, false, more_trbs_coming, true,
+			queue_trb(xhci, ep_ring, more_trbs_coming,
 				lower_32_bits(addr),
 				upper_32_bits(addr),
 				length_field,
@@ -3357,6 +3439,7 @@
 	ep_ring->enqueue = urb_priv->td[0]->first_trb;
 	ep_ring->enq_seg = urb_priv->td[0]->start_seg;
 	ep_ring->cycle_state = start_cycle;
+	ep_ring->num_trbs_free = ep_ring->num_trbs_free_temp;
 	usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
 	return ret;
 }
@@ -3393,7 +3476,7 @@
 	 * Do not insert any td of the urb to the ring if the check failed.
 	 */
 	ret = prepare_ring(xhci, ep_ring, le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK,
-			   num_trbs, true, mem_flags);
+			   num_trbs, mem_flags);
 	if (ret)
 		return ret;
 
@@ -3429,6 +3512,8 @@
 				urb->dev->speed == USB_SPEED_FULL)
 			urb->interval /= 8;
 	}
+	ep_ring->num_trbs_free_temp = ep_ring->num_trbs_free;
+
 	return xhci_queue_isoc_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index);
 }
 
@@ -3452,7 +3537,7 @@
 		reserved_trbs++;
 
 	ret = prepare_ring(xhci, xhci->cmd_ring, EP_STATE_RUNNING,
-			reserved_trbs, false, GFP_ATOMIC);
+			reserved_trbs, GFP_ATOMIC);
 	if (ret < 0) {
 		xhci_err(xhci, "ERR: No room for command on command ring\n");
 		if (command_must_succeed)
@@ -3460,8 +3545,8 @@
 					"unfailable commands failed.\n");
 		return ret;
 	}
-	queue_trb(xhci, xhci->cmd_ring, false, false, false, field1, field2,
-			field3,	field4 | xhci->cmd_ring->cycle_state);
+	queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
+			field4 | xhci->cmd_ring->cycle_state);
 	return 0;
 }
 
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index c939f5f..e1963d4 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -224,13 +224,13 @@
 	int ret;
 
 	/* return if using legacy interrupt */
-	if (xhci_to_hcd(xhci)->irq >= 0)
+	if (xhci_to_hcd(xhci)->irq > 0)
 		return;
 
 	ret = xhci_free_msi(xhci);
 	if (!ret)
 		return;
-	if (pdev->irq >= 0)
+	if (pdev->irq > 0)
 		free_irq(pdev->irq, xhci_to_hcd(xhci));
 
 	return;
@@ -341,7 +341,7 @@
 	/* unregister the legacy interrupt */
 	if (hcd->irq)
 		free_irq(hcd->irq, hcd);
-	hcd->irq = -1;
+	hcd->irq = 0;
 
 	ret = xhci_setup_msix(xhci);
 	if (ret)
@@ -349,7 +349,7 @@
 		ret = xhci_setup_msi(xhci);
 
 	if (!ret)
-		/* hcd->irq is -1, we have MSI */
+		/* hcd->irq is 0, we have MSI */
 		return 0;
 
 	if (!pdev->irq) {
@@ -729,6 +729,7 @@
 	ring->enq_seg = ring->deq_seg;
 	ring->enqueue = ring->dequeue;
 
+	ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1;
 	/*
 	 * Ring is now zeroed, so the HW should look for change of ownership
 	 * when the cycle bit is set to 1.
@@ -3614,26 +3615,38 @@
 	3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000};
 
 /* Calculate HIRD/BESL for USB2 PORTPMSC*/
-static int xhci_calculate_hird_besl(int u2del, bool use_besl)
+static int xhci_calculate_hird_besl(struct xhci_hcd *xhci,
+					struct usb_device *udev)
 {
-	int hird;
+	int u2del, besl, besl_host;
+	int besl_device = 0;
+	u32 field;
 
-	if (use_besl) {
-		for (hird = 0; hird < 16; hird++) {
-			if (xhci_besl_encoding[hird] >= u2del)
+	u2del = HCS_U2_LATENCY(xhci->hcs_params3);
+	field = le32_to_cpu(udev->bos->ext_cap->bmAttributes);
+
+	if (field & USB_BESL_SUPPORT) {
+		for (besl_host = 0; besl_host < 16; besl_host++) {
+			if (xhci_besl_encoding[besl_host] >= u2del)
 				break;
 		}
+		/* Use baseline BESL value as default */
+		if (field & USB_BESL_BASELINE_VALID)
+			besl_device = USB_GET_BESL_BASELINE(field);
+		else if (field & USB_BESL_DEEP_VALID)
+			besl_device = USB_GET_BESL_DEEP(field);
 	} else {
 		if (u2del <= 50)
-			hird = 0;
+			besl_host = 0;
 		else
-			hird = (u2del - 51) / 75 + 1;
-
-		if (hird > 15)
-			hird = 15;
+			besl_host = (u2del - 51) / 75 + 1;
 	}
 
-	return hird;
+	besl = besl_host + besl_device;
+	if (besl > 15)
+		besl = 15;
+
+	return besl;
 }
 
 static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd,
@@ -3646,7 +3659,7 @@
 	u32		temp, dev_id;
 	unsigned int	port_num;
 	unsigned long	flags;
-	int		u2del, hird;
+	int		hird;
 	int		ret;
 
 	if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support ||
@@ -3692,12 +3705,7 @@
 	 * HIRD or BESL shoule be used. See USB2.0 LPM errata.
 	 */
 	pm_addr = port_array[port_num] + 1;
-	u2del = HCS_U2_LATENCY(xhci->hcs_params3);
-	if (le32_to_cpu(udev->bos->ext_cap->bmAttributes) & (1 << 2))
-		hird = xhci_calculate_hird_besl(u2del, 1);
-	else
-		hird = xhci_calculate_hird_besl(u2del, 0);
-
+	hird = xhci_calculate_hird_besl(xhci, udev);
 	temp = PORT_L1DS(udev->slot_id) | PORT_HIRD(hird);
 	xhci_writel(xhci, temp, pm_addr);
 
@@ -3776,7 +3784,7 @@
 	u32		temp;
 	unsigned int	port_num;
 	unsigned long	flags;
-	int		u2del, hird;
+	int		hird;
 
 	if (hcd->speed == HCD_USB3 || !xhci->hw_lpm_support ||
 			!udev->lpm_capable)
@@ -3799,11 +3807,7 @@
 	xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n",
 			enable ? "enable" : "disable", port_num);
 
-	u2del = HCS_U2_LATENCY(xhci->hcs_params3);
-	if (le32_to_cpu(udev->bos->ext_cap->bmAttributes) & (1 << 2))
-		hird = xhci_calculate_hird_besl(u2del, 1);
-	else
-		hird = xhci_calculate_hird_besl(u2del, 0);
+	hird = xhci_calculate_hird_besl(xhci, udev);
 
 	if (enable) {
 		temp &= ~PORT_HIRD_MASK;
@@ -3964,7 +3968,8 @@
 	int			retval;
 	u32			temp;
 
-	hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2;
+	/* Accept arbitrarily long scatter-gather lists */
+	hcd->self.sg_tablesize = ~0;
 
 	if (usb_hcd_is_primary_hcd(hcd)) {
 		xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL);
@@ -4059,6 +4064,11 @@
 		printk(KERN_DEBUG "Problem registering PCI driver.");
 		return retval;
 	}
+	retval = xhci_register_plat();
+	if (retval < 0) {
+		printk(KERN_DEBUG "Problem registering platform driver.");
+		goto unreg_pci;
+	}
 	/*
 	 * Check the compiler generated sizes of structures that must be laid
 	 * out in specific ways for hardware access.
@@ -4078,11 +4088,15 @@
 	BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8);
 	BUILD_BUG_ON(sizeof(struct xhci_doorbell_array) != 256*32/8);
 	return 0;
+unreg_pci:
+	xhci_unregister_pci();
+	return retval;
 }
 module_init(xhci_hcd_init);
 
 static void __exit xhci_hcd_cleanup(void)
 {
 	xhci_unregister_pci();
+	xhci_unregister_plat();
 }
 module_exit(xhci_hcd_cleanup);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index fb99c83..91074fd 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1223,10 +1223,7 @@
 /* Allow two commands + a link TRB, along with any reserved command TRBs */
 #define MAX_RSVD_CMD_TRBS	(TRBS_PER_SEGMENT - 3)
 #define SEGMENT_SIZE		(TRBS_PER_SEGMENT*16)
-/* SEGMENT_SHIFT should be log2(SEGMENT_SIZE).
- * Change this if you change TRBS_PER_SEGMENT!
- */
-#define SEGMENT_SHIFT		10
+#define SEGMENT_SHIFT		(__ffs(SEGMENT_SIZE))
 /* TRB buffer pointers can't cross 64KB boundaries */
 #define TRB_MAX_BUFF_SHIFT		16
 #define TRB_MAX_BUFF_SIZE	(1 << TRB_MAX_BUFF_SHIFT)
@@ -1253,8 +1250,19 @@
 	int new_cycle_state;
 };
 
+enum xhci_ring_type {
+	TYPE_CTRL = 0,
+	TYPE_ISOC,
+	TYPE_BULK,
+	TYPE_INTR,
+	TYPE_STREAM,
+	TYPE_COMMAND,
+	TYPE_EVENT,
+};
+
 struct xhci_ring {
 	struct xhci_segment	*first_seg;
+	struct xhci_segment	*last_seg;
 	union  xhci_trb		*enqueue;
 	struct xhci_segment	*enq_seg;
 	unsigned int		enq_updates;
@@ -1269,6 +1277,10 @@
 	 */
 	u32			cycle_state;
 	unsigned int		stream_id;
+	unsigned int		num_segs;
+	unsigned int		num_trbs_free;
+	unsigned int		num_trbs_free_temp;
+	enum xhci_ring_type	type;
 	bool			last_td_was_short;
 };
 
@@ -1344,6 +1356,7 @@
 	/* ports suspend status arrays - max 31 ports for USB2, 15 for USB3 */
 	u32			port_c_suspend;
 	u32			suspended_ports;
+	u32			port_remote_wakeup;
 	unsigned long		resume_done[USB_MAXCHILDREN];
 };
 
@@ -1609,6 +1622,8 @@
 		struct usb_device *udev, struct usb_host_endpoint *ep,
 		gfp_t mem_flags);
 void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring);
+int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
+				unsigned int num_trbs, gfp_t flags);
 void xhci_free_or_cache_endpoint_ring(struct xhci_hcd *xhci,
 		struct xhci_virt_device *virt_dev,
 		unsigned int ep_index);
@@ -1648,6 +1663,17 @@
 static inline void xhci_unregister_pci(void) {}
 #endif
 
+#if defined(CONFIG_USB_XHCI_PLATFORM) \
+	|| defined(CONFIG_USB_XHCI_PLATFORM_MODULE)
+int xhci_register_plat(void);
+void xhci_unregister_plat(void);
+#else
+static inline int xhci_register_plat(void)
+{ return 0; }
+static inline void xhci_unregister_plat(void)
+{  }
+#endif
+
 /* xHCI host controller glue */
 typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
 void xhci_quiesce(struct xhci_hcd *xhci);
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index e233d2b..9f3eda9 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -226,6 +226,7 @@
 	struct device *dev = musb->controller;
 	struct musb_hdrc_platform_data *plat = dev->platform_data;
 	struct omap_musb_board_data *data = plat->board_data;
+	struct usb_otg *otg = musb->xceiv->otg;
 	unsigned long flags;
 	irqreturn_t ret = IRQ_NONE;
 	u32 epintr, usbintr;
@@ -289,14 +290,14 @@
 			WARNING("VBUS error workaround (delay coming)\n");
 		} else if (is_host_enabled(musb) && drvvbus) {
 			MUSB_HST_MODE(musb);
-			musb->xceiv->default_a = 1;
+			otg->default_a = 1;
 			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
 			portstate(musb->port1_status |= USB_PORT_STAT_POWER);
 			del_timer(&otg_workaround);
 		} else {
 			musb->is_active = 0;
 			MUSB_DEV_MODE(musb);
-			musb->xceiv->default_a = 0;
+			otg->default_a = 0;
 			musb->xceiv->state = OTG_STATE_B_IDLE;
 			portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
 		}
@@ -363,7 +364,7 @@
 		return -ENODEV;
 
 	usb_nop_xceiv_register();
-	musb->xceiv = otg_get_transceiver();
+	musb->xceiv = usb_get_transceiver();
 	if (!musb->xceiv)
 		return -ENODEV;
 
@@ -405,7 +406,7 @@
 	if (data->set_phy_power)
 		data->set_phy_power(0);
 
-	otg_put_transceiver(musb->xceiv);
+	usb_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 
 	return 0;
@@ -456,7 +457,7 @@
 
 static u64 am35x_dmamask = DMA_BIT_MASK(32);
 
-static int __init am35x_probe(struct platform_device *pdev)
+static int __devinit am35x_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
@@ -561,7 +562,7 @@
 	return ret;
 }
 
-static int __exit am35x_remove(struct platform_device *pdev)
+static int __devexit am35x_remove(struct platform_device *pdev)
 {
 	struct am35x_glue	*glue = platform_get_drvdata(pdev);
 
@@ -630,7 +631,8 @@
 #endif
 
 static struct platform_driver am35x_driver = {
-	.remove		= __exit_p(am35x_remove),
+	.probe		= am35x_probe,
+	.remove		= __devexit_p(am35x_remove),
 	.driver		= {
 		.name	= "musb-am35x",
 		.pm	= DEV_PM_OPS,
@@ -643,9 +645,9 @@
 
 static int __init am35x_init(void)
 {
-	return platform_driver_probe(&am35x_driver, am35x_probe);
+	return platform_driver_register(&am35x_driver);
 }
-subsys_initcall(am35x_init);
+module_init(am35x_init);
 
 static void __exit am35x_exit(void)
 {
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index 5e7cfba..a087ed6 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -317,7 +317,7 @@
 		musb_readb(musb->mregs, MUSB_DEVCTL));
 }
 
-static int bfin_musb_set_power(struct otg_transceiver *x, unsigned mA)
+static int bfin_musb_set_power(struct usb_phy *x, unsigned mA)
 {
 	return 0;
 }
@@ -415,7 +415,7 @@
 	gpio_direction_output(musb->config->gpio_vrsel, 0);
 
 	usb_nop_xceiv_register();
-	musb->xceiv = otg_get_transceiver();
+	musb->xceiv = usb_get_transceiver();
 	if (!musb->xceiv) {
 		gpio_free(musb->config->gpio_vrsel);
 		return -ENODEV;
@@ -440,7 +440,7 @@
 {
 	gpio_free(musb->config->gpio_vrsel);
 
-	otg_put_transceiver(musb->xceiv);
+	usb_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 	return 0;
 }
@@ -463,7 +463,7 @@
 
 static u64 bfin_dmamask = DMA_BIT_MASK(32);
 
-static int __init bfin_probe(struct platform_device *pdev)
+static int __devinit bfin_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
@@ -525,7 +525,7 @@
 	return ret;
 }
 
-static int __exit bfin_remove(struct platform_device *pdev)
+static int __devexit bfin_remove(struct platform_device *pdev)
 {
 	struct bfin_glue		*glue = platform_get_drvdata(pdev);
 
@@ -575,6 +575,7 @@
 #endif
 
 static struct platform_driver bfin_driver = {
+	.probe		= bfin_probe,
 	.remove		= __exit_p(bfin_remove),
 	.driver		= {
 		.name	= "musb-blackfin",
@@ -588,9 +589,9 @@
 
 static int __init bfin_init(void)
 {
-	return platform_driver_probe(&bfin_driver, bfin_probe);
+	return platform_driver_register(&bfin_driver);
 }
-subsys_initcall(bfin_init);
+module_init(bfin_init);
 
 static void __exit bfin_exit(void)
 {
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 2613bfd..8bd9566 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -294,6 +294,7 @@
 {
 	struct musb		*musb = hci;
 	void __iomem		*reg_base = musb->ctrl_base;
+	struct usb_otg		*otg = musb->xceiv->otg;
 	unsigned long		flags;
 	irqreturn_t		ret = IRQ_NONE;
 	u32			status;
@@ -351,14 +352,14 @@
 			WARNING("VBUS error workaround (delay coming)\n");
 		} else if (is_host_enabled(musb) && drvvbus) {
 			MUSB_HST_MODE(musb);
-			musb->xceiv->default_a = 1;
+			otg->default_a = 1;
 			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
 			portstate(musb->port1_status |= USB_PORT_STAT_POWER);
 			del_timer(&otg_workaround);
 		} else {
 			musb->is_active = 0;
 			MUSB_DEV_MODE(musb);
-			musb->xceiv->default_a = 0;
+			otg->default_a = 0;
 			musb->xceiv->state = OTG_STATE_B_IDLE;
 			portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
 		}
@@ -424,7 +425,7 @@
 		goto fail;
 
 	usb_nop_xceiv_register();
-	musb->xceiv = otg_get_transceiver();
+	musb->xceiv = usb_get_transceiver();
 	if (!musb->xceiv)
 		goto fail;
 
@@ -457,7 +458,7 @@
 
 	phy_off();
 
-	otg_put_transceiver(musb->xceiv);
+	usb_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 
 	return 0;
@@ -478,7 +479,7 @@
 
 static u64 da8xx_dmamask = DMA_BIT_MASK(32);
 
-static int __init da8xx_probe(struct platform_device *pdev)
+static int __devinit da8xx_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
@@ -562,7 +563,7 @@
 	return ret;
 }
 
-static int __exit da8xx_remove(struct platform_device *pdev)
+static int __devexit da8xx_remove(struct platform_device *pdev)
 {
 	struct da8xx_glue		*glue = platform_get_drvdata(pdev);
 
@@ -576,7 +577,8 @@
 }
 
 static struct platform_driver da8xx_driver = {
-	.remove		= __exit_p(da8xx_remove),
+	.probe		= da8xx_probe,
+	.remove		= __devexit_p(da8xx_remove),
 	.driver		= {
 		.name	= "musb-da8xx",
 	},
@@ -588,9 +590,9 @@
 
 static int __init da8xx_init(void)
 {
-	return platform_driver_probe(&da8xx_driver, da8xx_probe);
+	return platform_driver_register(&da8xx_driver);
 }
-subsys_initcall(da8xx_init);
+module_init(da8xx_init);
 
 static void __exit da8xx_exit(void)
 {
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 7c569f5..97ab975 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -265,6 +265,7 @@
 	unsigned long	flags;
 	irqreturn_t	retval = IRQ_NONE;
 	struct musb	*musb = __hci;
+	struct usb_otg	*otg = musb->xceiv->otg;
 	void __iomem	*tibase = musb->ctrl_base;
 	struct cppi	*cppi;
 	u32		tmp;
@@ -331,14 +332,14 @@
 			WARNING("VBUS error workaround (delay coming)\n");
 		} else if (is_host_enabled(musb) && drvvbus) {
 			MUSB_HST_MODE(musb);
-			musb->xceiv->default_a = 1;
+			otg->default_a = 1;
 			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
 			portstate(musb->port1_status |= USB_PORT_STAT_POWER);
 			del_timer(&otg_workaround);
 		} else {
 			musb->is_active = 0;
 			MUSB_DEV_MODE(musb);
-			musb->xceiv->default_a = 0;
+			otg->default_a = 0;
 			musb->xceiv->state = OTG_STATE_B_IDLE;
 			portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
 		}
@@ -383,7 +384,7 @@
 	u32		revision;
 
 	usb_nop_xceiv_register();
-	musb->xceiv = otg_get_transceiver();
+	musb->xceiv = usb_get_transceiver();
 	if (!musb->xceiv)
 		return -ENODEV;
 
@@ -442,7 +443,7 @@
 	return 0;
 
 fail:
-	otg_put_transceiver(musb->xceiv);
+	usb_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 	return -ENODEV;
 }
@@ -464,7 +465,7 @@
 	davinci_musb_source_power(musb, 0 /*off*/, 1);
 
 	/* delay, to avoid problems with module reload */
-	if (is_host_enabled(musb) && musb->xceiv->default_a) {
+	if (is_host_enabled(musb) && musb->xceiv->otg->default_a) {
 		int	maxdelay = 30;
 		u8	devctl, warn = 0;
 
@@ -491,7 +492,7 @@
 
 	phy_off();
 
-	otg_put_transceiver(musb->xceiv);
+	usb_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 
 	return 0;
@@ -511,7 +512,7 @@
 
 static u64 davinci_dmamask = DMA_BIT_MASK(32);
 
-static int __init davinci_probe(struct platform_device *pdev)
+static int __devinit davinci_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
@@ -594,7 +595,7 @@
 	return ret;
 }
 
-static int __exit davinci_remove(struct platform_device *pdev)
+static int __devexit davinci_remove(struct platform_device *pdev)
 {
 	struct davinci_glue		*glue = platform_get_drvdata(pdev);
 
@@ -608,7 +609,8 @@
 }
 
 static struct platform_driver davinci_driver = {
-	.remove		= __exit_p(davinci_remove),
+	.probe		= davinci_probe,
+	.remove		= __devexit_p(davinci_remove),
 	.driver		= {
 		.name	= "musb-davinci",
 	},
@@ -620,9 +622,9 @@
 
 static int __init davinci_init(void)
 {
-	return platform_driver_probe(&davinci_driver, davinci_probe);
+	return platform_driver_register(&davinci_driver);
 }
-subsys_initcall(davinci_init);
+module_init(davinci_init);
 
 static void __exit davinci_exit(void)
 {
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 3d11cf64..0f8b829 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -131,9 +131,9 @@
 /*-------------------------------------------------------------------------*/
 
 #ifndef CONFIG_BLACKFIN
-static int musb_ulpi_read(struct otg_transceiver *otg, u32 offset)
+static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
 {
-	void __iomem *addr = otg->io_priv;
+	void __iomem *addr = phy->io_priv;
 	int	i = 0;
 	u8	r;
 	u8	power;
@@ -165,10 +165,9 @@
 	return musb_readb(addr, MUSB_ULPI_REG_DATA);
 }
 
-static int musb_ulpi_write(struct otg_transceiver *otg,
-		u32 offset, u32 data)
+static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
 {
-	void __iomem *addr = otg->io_priv;
+	void __iomem *addr = phy->io_priv;
 	int	i = 0;
 	u8	r = 0;
 	u8	power;
@@ -200,7 +199,7 @@
 #define musb_ulpi_write		NULL
 #endif
 
-static struct otg_io_access_ops musb_ulpi_access = {
+static struct usb_phy_io_ops musb_ulpi_access = {
 	.read = musb_ulpi_read,
 	.write = musb_ulpi_write,
 };
@@ -414,6 +413,7 @@
 static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 				u8 devctl, u8 power)
 {
+	struct usb_otg *otg = musb->xceiv->otg;
 	irqreturn_t handled = IRQ_NONE;
 
 	dev_dbg(musb->controller, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl,
@@ -626,7 +626,7 @@
 		case OTG_STATE_B_PERIPHERAL:
 			musb_g_suspend(musb);
 			musb->is_active = is_otg_enabled(musb)
-					&& musb->xceiv->gadget->b_hnp_enable;
+					&& otg->gadget->b_hnp_enable;
 			if (musb->is_active) {
 				musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
 				dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n");
@@ -643,7 +643,7 @@
 		case OTG_STATE_A_HOST:
 			musb->xceiv->state = OTG_STATE_A_SUSPEND;
 			musb->is_active = is_otg_enabled(musb)
-					&& musb->xceiv->host->b_hnp_enable;
+					&& otg->host->b_hnp_enable;
 			break;
 		case OTG_STATE_B_HOST:
 			/* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */
@@ -1017,12 +1017,12 @@
 	|| defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE)	\
 	|| defined(CONFIG_USB_MUSB_AM35X)		\
 	|| defined(CONFIG_USB_MUSB_AM35X_MODULE)
-static ushort __initdata fifo_mode = 4;
+static ushort __devinitdata fifo_mode = 4;
 #elif defined(CONFIG_USB_MUSB_UX500)			\
 	|| defined(CONFIG_USB_MUSB_UX500_MODULE)
-static ushort __initdata fifo_mode = 5;
+static ushort __devinitdata fifo_mode = 5;
 #else
-static ushort __initdata fifo_mode = 2;
+static ushort __devinitdata fifo_mode = 2;
 #endif
 
 /* "modprobe ... fifo_mode=1" etc */
@@ -1035,7 +1035,7 @@
  */
 
 /* mode 0 - fits in 2KB */
-static struct musb_fifo_cfg __initdata mode_0_cfg[] = {
+static struct musb_fifo_cfg __devinitdata mode_0_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_RXTX, .maxpacket = 512, },
@@ -1044,7 +1044,7 @@
 };
 
 /* mode 1 - fits in 4KB */
-static struct musb_fifo_cfg __initdata mode_1_cfg[] = {
+static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, },
@@ -1053,7 +1053,7 @@
 };
 
 /* mode 2 - fits in 4KB */
-static struct musb_fifo_cfg __initdata mode_2_cfg[] = {
+static struct musb_fifo_cfg __devinitdata mode_2_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 = 512, },
@@ -1063,7 +1063,7 @@
 };
 
 /* mode 3 - fits in 4KB */
-static struct musb_fifo_cfg __initdata mode_3_cfg[] = {
+static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, },
@@ -1073,7 +1073,7 @@
 };
 
 /* mode 4 - fits in 16KB */
-static struct musb_fifo_cfg __initdata mode_4_cfg[] = {
+static struct musb_fifo_cfg __devinitdata mode_4_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 = 512, },
@@ -1104,7 +1104,7 @@
 };
 
 /* mode 5 - fits in 8KB */
-static struct musb_fifo_cfg __initdata mode_5_cfg[] = {
+static struct musb_fifo_cfg __devinitdata mode_5_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 = 512, },
@@ -1140,7 +1140,7 @@
  *
  * returns negative errno or offset for next fifo.
  */
-static int __init
+static int __devinit
 fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,
 		const struct musb_fifo_cfg *cfg, u16 offset)
 {
@@ -1211,11 +1211,11 @@
 	return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0));
 }
 
-static struct musb_fifo_cfg __initdata ep0_cfg = {
+static struct musb_fifo_cfg __devinitdata ep0_cfg = {
 	.style = FIFO_RXTX, .maxpacket = 64,
 };
 
-static int __init ep_config_from_table(struct musb *musb)
+static int __devinit ep_config_from_table(struct musb *musb)
 {
 	const struct musb_fifo_cfg	*cfg;
 	unsigned		i, n;
@@ -1306,7 +1306,7 @@
  * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false
  * @param musb the controller
  */
-static int __init ep_config_from_hw(struct musb *musb)
+static int __devinit ep_config_from_hw(struct musb *musb)
 {
 	u8 epnum = 0;
 	struct musb_hw_ep *hw_ep;
@@ -1353,7 +1353,7 @@
 /* Initialize MUSB (M)HDRC part of the USB hardware subsystem;
  * configure endpoints, or take their config from silicon
  */
-static int __init musb_core_init(u16 musb_type, struct musb *musb)
+static int __devinit musb_core_init(u16 musb_type, struct musb *musb)
 {
 	u8 reg;
 	char *type;
@@ -1589,7 +1589,7 @@
 EXPORT_SYMBOL_GPL(musb_interrupt);
 
 #ifndef CONFIG_MUSB_PIO_ONLY
-static bool __initdata use_dma = 1;
+static bool __devinitdata use_dma = 1;
 
 /* "modprobe ... use_dma=0" etc */
 module_param(use_dma, bool, 0);
@@ -1777,7 +1777,7 @@
  * Init support
  */
 
-static struct musb *__init
+static struct musb *__devinit
 allocate_instance(struct device *dev,
 		struct musb_hdrc_config *config, void __iomem *mbase)
 {
@@ -1853,7 +1853,7 @@
  * @mregs: virtual address of controller registers,
  *	not yet corrected for platform-specific offsets
  */
-static int __init
+static int __devinit
 musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 {
 	int			status;
@@ -1961,11 +1961,11 @@
 	if (is_host_enabled(musb)) {
 		struct usb_hcd	*hcd = musb_to_hcd(musb);
 
-		otg_set_host(musb->xceiv, &hcd->self);
+		otg_set_host(musb->xceiv->otg, &hcd->self);
 
 		if (is_otg_enabled(musb))
 			hcd->self.otg_port = 1;
-		musb->xceiv->host = &hcd->self;
+		musb->xceiv->otg->host = &hcd->self;
 		hcd->power_budget = 2 * (plat->power ? : 250);
 
 		/* program PHY to use external vBus if required */
@@ -1984,10 +1984,10 @@
 		struct usb_hcd	*hcd = musb_to_hcd(musb);
 
 		MUSB_HST_MODE(musb);
-		musb->xceiv->default_a = 1;
+		musb->xceiv->otg->default_a = 1;
 		musb->xceiv->state = OTG_STATE_A_IDLE;
 
-		status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
+		status = usb_add_hcd(musb_to_hcd(musb), 0, 0);
 
 		hcd->self.uses_pio_for_control = 1;
 		dev_dbg(musb->controller, "%s mode, status %d, devctl %02x %c\n",
@@ -1999,7 +1999,7 @@
 
 	} else /* peripheral is enabled */ {
 		MUSB_DEV_MODE(musb);
-		musb->xceiv->default_a = 0;
+		musb->xceiv->otg->default_a = 0;
 		musb->xceiv->state = OTG_STATE_B_IDLE;
 
 		status = musb_gadget_setup(musb);
@@ -2073,7 +2073,7 @@
 static u64	*orig_dma_mask;
 #endif
 
-static int __init musb_probe(struct platform_device *pdev)
+static int __devinit musb_probe(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
 	int		irq = platform_get_irq_byname(pdev, "mc");
@@ -2102,7 +2102,7 @@
 	return status;
 }
 
-static int __exit musb_remove(struct platform_device *pdev)
+static int __devexit musb_remove(struct platform_device *pdev)
 {
 	struct musb	*musb = dev_to_musb(&pdev->dev);
 	void __iomem	*ctrl_base = musb->ctrl_base;
@@ -2112,11 +2112,9 @@
 	 *  - Peripheral mode: peripheral is deactivated (or never-activated)
 	 *  - OTG mode: both roles are deactivated (or never-activated)
 	 */
-	pm_runtime_get_sync(musb->controller);
 	musb_exit_debugfs(musb);
 	musb_shutdown(pdev);
 
-	pm_runtime_put(musb->controller);
 	musb_free(musb);
 	iounmap(ctrl_base);
 	device_init_wakeup(&pdev->dev, 0);
@@ -2364,7 +2362,8 @@
 		.owner		= THIS_MODULE,
 		.pm		= MUSB_DEV_PM_OPS,
 	},
-	.remove		= __exit_p(musb_remove),
+	.probe		= musb_probe,
+	.remove		= __devexit_p(musb_remove),
 	.shutdown	= musb_shutdown,
 };
 
@@ -2380,13 +2379,9 @@
 		", "
 		"otg (peripheral+host)",
 		musb_driver_name);
-	return platform_driver_probe(&musb_driver, musb_probe);
+	return platform_driver_register(&musb_driver);
 }
-
-/* make us init after usbcore and i2c (transceivers, regulators, etc)
- * and before usb gadget and host-side drivers start to register
- */
-fs_initcall(musb_init);
+module_init(musb_init);
 
 static void __exit musb_cleanup(void)
 {
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 3d28fb8..93de517 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -372,7 +372,7 @@
 	u16			int_rx;
 	u16			int_tx;
 
-	struct otg_transceiver	*xceiv;
+	struct usb_phy		*xceiv;
 	u8			xceiv_event;
 
 	int nIrq;
diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c
index 13d9af9..40a37c9 100644
--- a/drivers/usb/musb/musb_debugfs.c
+++ b/drivers/usb/musb/musb_debugfs.c
@@ -235,29 +235,29 @@
 	.release		= single_release,
 };
 
-int __init musb_init_debugfs(struct musb *musb)
+int __devinit musb_init_debugfs(struct musb *musb)
 {
 	struct dentry		*root;
 	struct dentry		*file;
 	int			ret;
 
 	root = debugfs_create_dir("musb", NULL);
-	if (IS_ERR(root)) {
-		ret = PTR_ERR(root);
+	if (!root) {
+		ret = -ENOMEM;
 		goto err0;
 	}
 
 	file = debugfs_create_file("regdump", S_IRUGO, root, musb,
 			&musb_regdump_fops);
-	if (IS_ERR(file)) {
-		ret = PTR_ERR(file);
+	if (!file) {
+		ret = -ENOMEM;
 		goto err1;
 	}
 
 	file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR,
 			root, musb, &musb_test_mode_fops);
-	if (IS_ERR(file)) {
-		ret = PTR_ERR(file);
+	if (!file) {
+		ret = -ENOMEM;
 		goto err1;
 	}
 
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index ac3d2ee..f42c29b 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -574,6 +574,15 @@
 
 		if (request->actual == request->length) {
 			musb_g_giveback(musb_ep, request, 0);
+			/*
+			 * In the giveback function the MUSB lock is
+			 * released and acquired after sometime. During
+			 * this time period the INDEX register could get
+			 * changed by the gadget_queue function especially
+			 * on SMP systems. Reselect the INDEX to be sure
+			 * we are reading/modifying the right registers
+			 */
+			musb_ep_select(mbase, epnum);
 			req = musb_ep->desc ? next_request(musb_ep) : NULL;
 			if (!req) {
 				dev_dbg(musb->controller, "%s idle now\n",
@@ -983,6 +992,15 @@
 		}
 #endif
 		musb_g_giveback(musb_ep, request, 0);
+		/*
+		 * In the giveback function the MUSB lock is
+		 * released and acquired after sometime. During
+		 * this time period the INDEX register could get
+		 * changed by the gadget_queue function especially
+		 * on SMP systems. Reselect the INDEX to be sure
+		 * we are reading/modifying the right registers
+		 */
+		musb_ep_select(mbase, epnum);
 
 		req = next_request(musb_ep);
 		if (!req)
@@ -1624,7 +1642,7 @@
 		}
 
 		spin_unlock_irqrestore(&musb->lock, flags);
-		otg_start_srp(musb->xceiv);
+		otg_start_srp(musb->xceiv->otg);
 		spin_lock_irqsave(&musb->lock, flags);
 
 		/* Block idling for at least 1s */
@@ -1703,7 +1721,7 @@
 
 	if (!musb->xceiv->set_power)
 		return -EOPNOTSUPP;
-	return otg_set_power(musb->xceiv, mA);
+	return usb_phy_set_power(musb->xceiv, mA);
 }
 
 static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
@@ -1762,7 +1780,7 @@
 }
 
 
-static void __init
+static void __devinit
 init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
 {
 	struct musb_hw_ep	*hw_ep = musb->endpoints + epnum;
@@ -1799,7 +1817,7 @@
  * Initialize the endpoints exposed to peripheral drivers, with backlinks
  * to the rest of the driver state.
  */
-static inline void __init musb_g_init_endpoints(struct musb *musb)
+static inline void __devinit musb_g_init_endpoints(struct musb *musb)
 {
 	u8			epnum;
 	struct musb_hw_ep	*hw_ep;
@@ -1832,7 +1850,7 @@
 /* called once during driver setup to initialize and link into
  * the driver model; memory is zeroed.
  */
-int __init musb_gadget_setup(struct musb *musb)
+int __devinit musb_gadget_setup(struct musb *musb)
 {
 	int status;
 
@@ -1898,6 +1916,7 @@
 		struct usb_gadget_driver *driver)
 {
 	struct musb		*musb = gadget_to_musb(g);
+	struct usb_otg		*otg = musb->xceiv->otg;
 	unsigned long		flags;
 	int			retval = -EINVAL;
 
@@ -1914,7 +1933,7 @@
 	spin_lock_irqsave(&musb->lock, flags);
 	musb->is_active = 1;
 
-	otg_set_peripheral(musb->xceiv, &musb->g);
+	otg_set_peripheral(otg, &musb->g);
 	musb->xceiv->state = OTG_STATE_B_IDLE;
 
 	/*
@@ -1938,15 +1957,15 @@
 		 * handles power budgeting ... this way also
 		 * ensures HdrcStart is indirectly called.
 		 */
-		retval = usb_add_hcd(musb_to_hcd(musb), -1, 0);
+		retval = usb_add_hcd(musb_to_hcd(musb), 0, 0);
 		if (retval < 0) {
 			dev_dbg(musb->controller, "add_hcd failed, %d\n", retval);
 			goto err2;
 		}
 
 		if ((musb->xceiv->last_event == USB_EVENT_ID)
-					&& musb->xceiv->set_vbus)
-			otg_set_vbus(musb->xceiv, 1);
+					&& otg->set_vbus)
+			otg_set_vbus(otg, 1);
 
 		hcd->self.uses_pio_for_control = 1;
 	}
@@ -2028,7 +2047,7 @@
 
 	musb->xceiv->state = OTG_STATE_UNDEFINED;
 	stop_activity(musb, driver);
-	otg_set_peripheral(musb->xceiv, NULL);
+	otg_set_peripheral(musb->xceiv->otg, NULL);
 
 	dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);
 
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index e9f80adc..22ec3e3 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -47,6 +47,7 @@
 
 static void musb_port_suspend(struct musb *musb, bool do_suspend)
 {
+	struct usb_otg	*otg = musb->xceiv->otg;
 	u8		power;
 	void __iomem	*mbase = musb->mregs;
 
@@ -81,7 +82,7 @@
 		case OTG_STATE_A_HOST:
 			musb->xceiv->state = OTG_STATE_A_SUSPEND;
 			musb->is_active = is_otg_enabled(musb)
-					&& musb->xceiv->host->b_hnp_enable;
+					&& otg->host->b_hnp_enable;
 			if (musb->is_active)
 				mod_timer(&musb->otg_timer, jiffies
 					+ msecs_to_jiffies(
@@ -91,7 +92,7 @@
 		case OTG_STATE_B_HOST:
 			musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
 			musb->is_active = is_otg_enabled(musb)
-					&& musb->xceiv->host->b_hnp_enable;
+					&& otg->host->b_hnp_enable;
 			musb_platform_try_idle(musb, 0);
 			break;
 		default:
@@ -179,6 +180,8 @@
 
 void musb_root_disconnect(struct musb *musb)
 {
+	struct usb_otg	*otg = musb->xceiv->otg;
+
 	musb->port1_status = USB_PORT_STAT_POWER
 			| (USB_PORT_STAT_C_CONNECTION << 16);
 
@@ -188,7 +191,7 @@
 	switch (musb->xceiv->state) {
 	case OTG_STATE_A_SUSPEND:
 		if (is_otg_enabled(musb)
-				&& musb->xceiv->host->b_hnp_enable) {
+				&& otg->host->b_hnp_enable) {
 			musb->xceiv->state = OTG_STATE_A_PERIPHERAL;
 			musb->g.is_a_peripheral = 1;
 			break;
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index df719ea..2ae0bb3 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -132,6 +132,7 @@
 
 static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
 {
+	struct usb_otg	*otg = musb->xceiv->otg;
 	u8		devctl;
 	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 	int ret = 1;
@@ -163,11 +164,11 @@
 				}
 			}
 
-			if (ret && musb->xceiv->set_vbus)
-				otg_set_vbus(musb->xceiv, 1);
+			if (ret && otg->set_vbus)
+				otg_set_vbus(otg, 1);
 		} else {
 			musb->is_active = 1;
-			musb->xceiv->default_a = 1;
+			otg->default_a = 1;
 			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
 			devctl |= MUSB_DEVCTL_SESSION;
 			MUSB_HST_MODE(musb);
@@ -179,7 +180,7 @@
 		 * jumping right to B_IDLE...
 		 */
 
-		musb->xceiv->default_a = 0;
+		otg->default_a = 0;
 		musb->xceiv->state = OTG_STATE_B_IDLE;
 		devctl &= ~MUSB_DEVCTL_SESSION;
 
@@ -246,7 +247,7 @@
 
 		if (!is_otg_enabled(musb) || musb->gadget_driver) {
 			pm_runtime_get_sync(musb->controller);
-			otg_init(musb->xceiv);
+			usb_phy_init(musb->xceiv);
 			omap2430_musb_set_vbus(musb, 1);
 		}
 		break;
@@ -256,7 +257,7 @@
 
 		if (musb->gadget_driver)
 			pm_runtime_get_sync(musb->controller);
-		otg_init(musb->xceiv);
+		usb_phy_init(musb->xceiv);
 		break;
 
 	case USB_EVENT_NONE:
@@ -269,10 +270,10 @@
 			}
 
 		if (data->interface_type == MUSB_INTERFACE_UTMI) {
-			if (musb->xceiv->set_vbus)
-				otg_set_vbus(musb->xceiv, 0);
+			if (musb->xceiv->otg->set_vbus)
+				otg_set_vbus(musb->xceiv->otg, 0);
 		}
-		otg_shutdown(musb->xceiv);
+		usb_phy_shutdown(musb->xceiv);
 		break;
 	default:
 		dev_dbg(musb->controller, "ID float\n");
@@ -290,7 +291,7 @@
 	 * up through ULPI.  TWL4030-family PMICs include one,
 	 * which needs a driver, drivers aren't always needed.
 	 */
-	musb->xceiv = otg_get_transceiver();
+	musb->xceiv = usb_get_transceiver();
 	if (!musb->xceiv) {
 		pr_err("HS USB OTG: no transceiver configured\n");
 		return -ENODEV;
@@ -325,7 +326,7 @@
 			musb_readl(musb->mregs, OTG_SIMENABLE));
 
 	musb->nb.notifier_call = musb_otg_notifications;
-	status = otg_register_notifier(musb->xceiv, &musb->nb);
+	status = usb_register_notifier(musb->xceiv, &musb->nb);
 
 	if (status)
 		dev_dbg(musb->controller, "notification register failed\n");
@@ -349,7 +350,7 @@
 	switch (musb->xceiv->last_event) {
 
 	case USB_EVENT_ID:
-		otg_init(musb->xceiv);
+		usb_phy_init(musb->xceiv);
 		if (data->interface_type != MUSB_INTERFACE_UTMI)
 			break;
 		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
@@ -368,7 +369,7 @@
 		break;
 
 	case USB_EVENT_VBUS:
-		otg_init(musb->xceiv);
+		usb_phy_init(musb->xceiv);
 		break;
 
 	default:
@@ -379,7 +380,7 @@
 static void omap2430_musb_disable(struct musb *musb)
 {
 	if (musb->xceiv->last_event)
-		otg_shutdown(musb->xceiv);
+		usb_phy_shutdown(musb->xceiv);
 }
 
 static int omap2430_musb_exit(struct musb *musb)
@@ -388,7 +389,7 @@
 	cancel_work_sync(&musb->otg_notifier_work);
 
 	omap2430_low_level_exit(musb);
-	otg_put_transceiver(musb->xceiv);
+	usb_put_transceiver(musb->xceiv);
 
 	return 0;
 }
@@ -408,7 +409,7 @@
 
 static u64 omap2430_dmamask = DMA_BIT_MASK(32);
 
-static int __init omap2430_probe(struct platform_device *pdev)
+static int __devinit omap2430_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
@@ -471,7 +472,7 @@
 	return ret;
 }
 
-static int __exit omap2430_remove(struct platform_device *pdev)
+static int __devexit omap2430_remove(struct platform_device *pdev)
 {
 	struct omap2430_glue		*glue = platform_get_drvdata(pdev);
 
@@ -494,7 +495,7 @@
 						OTG_INTERFSEL);
 
 	omap2430_low_level_exit(musb);
-	otg_set_suspend(musb->xceiv, 1);
+	usb_phy_set_suspend(musb->xceiv, 1);
 
 	return 0;
 }
@@ -508,7 +509,7 @@
 	musb_writel(musb->mregs, OTG_INTERFSEL,
 					musb->context.otg_interfsel);
 
-	otg_set_suspend(musb->xceiv, 0);
+	usb_phy_set_suspend(musb->xceiv, 0);
 
 	return 0;
 }
@@ -524,7 +525,8 @@
 #endif
 
 static struct platform_driver omap2430_driver = {
-	.remove		= __exit_p(omap2430_remove),
+	.probe		= omap2430_probe,
+	.remove		= __devexit_p(omap2430_remove),
 	.driver		= {
 		.name	= "musb-omap2430",
 		.pm	= DEV_PM_OPS,
@@ -537,9 +539,9 @@
 
 static int __init omap2430_init(void)
 {
-	return platform_driver_probe(&omap2430_driver, omap2430_probe);
+	return platform_driver_register(&omap2430_driver);
 }
-subsys_initcall(omap2430_init);
+module_init(omap2430_init);
 
 static void __exit omap2430_exit(void)
 {
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 1f40561..de13559 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -277,7 +277,7 @@
  * mode), or low power Default-B sessions, something else supplies power.
  * Caller must take care of locking.
  */
-static int tusb_draw_power(struct otg_transceiver *x, unsigned mA)
+static int tusb_draw_power(struct usb_phy *x, unsigned mA)
 {
 	struct musb	*musb = the_musb;
 	void __iomem	*tbase = musb->ctrl_base;
@@ -293,7 +293,7 @@
 	 * The actual current usage would be very board-specific.  For now,
 	 * it's simpler to just use an aggregate (also board-specific).
 	 */
-	if (x->default_a || mA < (musb->min_power << 1))
+	if (x->otg->default_a || mA < (musb->min_power << 1))
 		mA = 0;
 
 	reg = musb_readl(tbase, TUSB_PRCM_MNGMT);
@@ -510,6 +510,7 @@
 	void __iomem	*tbase = musb->ctrl_base;
 	u32		conf, prcm, timer;
 	u8		devctl;
+	struct usb_otg	*otg = musb->xceiv->otg;
 
 	/* HDRC controls CPEN, but beware current surges during device
 	 * connect.  They can trigger transient overcurrent conditions
@@ -522,7 +523,7 @@
 
 	if (is_on) {
 		timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE);
-		musb->xceiv->default_a = 1;
+		otg->default_a = 1;
 		musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
 		devctl |= MUSB_DEVCTL_SESSION;
 
@@ -548,11 +549,11 @@
 				musb->xceiv->state = OTG_STATE_A_IDLE;
 			}
 			musb->is_active = 0;
-			musb->xceiv->default_a = 1;
+			otg->default_a = 1;
 			MUSB_HST_MODE(musb);
 		} else {
 			musb->is_active = 0;
-			musb->xceiv->default_a = 0;
+			otg->default_a = 0;
 			musb->xceiv->state = OTG_STATE_B_IDLE;
 			MUSB_DEV_MODE(musb);
 		}
@@ -644,6 +645,7 @@
 {
 	u32		otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
 	unsigned long	idle_timeout = 0;
+	struct usb_otg	*otg = musb->xceiv->otg;
 
 	/* ID pin */
 	if ((int_src & TUSB_INT_SRC_ID_STATUS_CHNG)) {
@@ -654,7 +656,7 @@
 		else
 			default_a = is_host_enabled(musb);
 		dev_dbg(musb->controller, "Default-%c\n", default_a ? 'A' : 'B');
-		musb->xceiv->default_a = default_a;
+		otg->default_a = default_a;
 		tusb_musb_set_vbus(musb, default_a);
 
 		/* Don't allow idling immediately */
@@ -666,7 +668,7 @@
 	if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) {
 
 		/* B-dev state machine:  no vbus ~= disconnect */
-		if ((is_otg_enabled(musb) && !musb->xceiv->default_a)
+		if ((is_otg_enabled(musb) && !otg->default_a)
 				|| !is_host_enabled(musb)) {
 			/* ? musb_root_disconnect(musb); */
 			musb->port1_status &=
@@ -1076,7 +1078,7 @@
 	int			ret;
 
 	usb_nop_xceiv_register();
-	musb->xceiv = otg_get_transceiver();
+	musb->xceiv = usb_get_transceiver();
 	if (!musb->xceiv)
 		return -ENODEV;
 
@@ -1128,7 +1130,7 @@
 		if (sync)
 			iounmap(sync);
 
-		otg_put_transceiver(musb->xceiv);
+		usb_put_transceiver(musb->xceiv);
 		usb_nop_xceiv_unregister();
 	}
 	return ret;
@@ -1144,7 +1146,7 @@
 
 	iounmap(musb->sync_va);
 
-	otg_put_transceiver(musb->xceiv);
+	usb_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 	return 0;
 }
@@ -1165,7 +1167,7 @@
 
 static u64 tusb_dmamask = DMA_BIT_MASK(32);
 
-static int __init tusb_probe(struct platform_device *pdev)
+static int __devinit tusb_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
@@ -1227,7 +1229,7 @@
 	return ret;
 }
 
-static int __exit tusb_remove(struct platform_device *pdev)
+static int __devexit tusb_remove(struct platform_device *pdev)
 {
 	struct tusb6010_glue		*glue = platform_get_drvdata(pdev);
 
@@ -1239,7 +1241,8 @@
 }
 
 static struct platform_driver tusb_driver = {
-	.remove		= __exit_p(tusb_remove),
+	.probe		= tusb_probe,
+	.remove		= __devexit_p(tusb_remove),
 	.driver		= {
 		.name	= "musb-tusb",
 	},
@@ -1251,9 +1254,9 @@
 
 static int __init tusb_init(void)
 {
-	return platform_driver_probe(&tusb_driver, tusb_probe);
+	return platform_driver_register(&tusb_driver);
 }
-subsys_initcall(tusb_init);
+module_init(tusb_init);
 
 static void __exit tusb_exit(void)
 {
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index f7e04bf..aa09dd4 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -37,7 +37,7 @@
 
 static int ux500_musb_init(struct musb *musb)
 {
-	musb->xceiv = otg_get_transceiver();
+	musb->xceiv = usb_get_transceiver();
 	if (!musb->xceiv) {
 		pr_err("HS USB OTG: no transceiver configured\n");
 		return -ENODEV;
@@ -48,7 +48,7 @@
 
 static int ux500_musb_exit(struct musb *musb)
 {
-	otg_put_transceiver(musb->xceiv);
+	usb_put_transceiver(musb->xceiv);
 
 	return 0;
 }
@@ -58,7 +58,7 @@
 	.exit		= ux500_musb_exit,
 };
 
-static int __init ux500_probe(struct platform_device *pdev)
+static int __devinit ux500_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
@@ -141,7 +141,7 @@
 	return ret;
 }
 
-static int __exit ux500_remove(struct platform_device *pdev)
+static int __devexit ux500_remove(struct platform_device *pdev)
 {
 	struct ux500_glue	*glue = platform_get_drvdata(pdev);
 
@@ -160,7 +160,7 @@
 	struct ux500_glue	*glue = dev_get_drvdata(dev);
 	struct musb		*musb = glue_to_musb(glue);
 
-	otg_set_suspend(musb->xceiv, 1);
+	usb_phy_set_suspend(musb->xceiv, 1);
 	clk_disable(glue->clk);
 
 	return 0;
@@ -178,7 +178,7 @@
 		return ret;
 	}
 
-	otg_set_suspend(musb->xceiv, 0);
+	usb_phy_set_suspend(musb->xceiv, 0);
 
 	return 0;
 }
@@ -194,7 +194,8 @@
 #endif
 
 static struct platform_driver ux500_driver = {
-	.remove		= __exit_p(ux500_remove),
+	.probe		= ux500_probe,
+	.remove		= __devexit_p(ux500_remove),
 	.driver		= {
 		.name	= "musb-ux500",
 		.pm	= DEV_PM_OPS,
@@ -207,9 +208,9 @@
 
 static int __init ux500_init(void)
 {
-	return platform_driver_probe(&ux500_driver, ux500_probe);
+	return platform_driver_register(&ux500_driver);
 }
-subsys_initcall(ux500_init);
+module_init(ux500_init);
 
 static void __exit ux500_exit(void)
 {
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 735ef4c..5c87db0 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -23,7 +23,7 @@
 	select USB_OTG_UTILS
 	help
 	  Provides simple GPIO VBUS sensing for controllers with an
-	  internal transceiver via the otg_transceiver interface, and
+	  internal transceiver via the usb_phy interface, and
 	  optionally control of a D+ pullup GPIO as well as a VBUS
 	  current limit regulator.
 
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
index 74fe6e6..a84af67 100644
--- a/drivers/usb/otg/ab8500-usb.c
+++ b/drivers/usb/otg/ab8500-usb.c
@@ -68,7 +68,7 @@
 };
 
 struct ab8500_usb {
-	struct otg_transceiver otg;
+	struct usb_phy phy;
 	struct device *dev;
 	int irq_num_id_rise;
 	int irq_num_id_fall;
@@ -82,9 +82,9 @@
 	int rev;
 };
 
-static inline struct ab8500_usb *xceiv_to_ab(struct otg_transceiver *x)
+static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x)
 {
-	return container_of(x, struct ab8500_usb, otg);
+	return container_of(x, struct ab8500_usb, phy);
 }
 
 static void ab8500_usb_wd_workaround(struct ab8500_usb *ab)
@@ -153,7 +153,7 @@
 	u8 reg;
 	enum ab8500_usb_link_status lsts;
 	void *v = NULL;
-	enum usb_xceiv_events event;
+	enum usb_phy_events event;
 
 	abx500_get_register_interruptible(ab->dev,
 			AB8500_USB,
@@ -169,8 +169,8 @@
 		/* TODO: Disable regulators. */
 		ab8500_usb_host_phy_dis(ab);
 		ab8500_usb_peri_phy_dis(ab);
-		ab->otg.state = OTG_STATE_B_IDLE;
-		ab->otg.default_a = false;
+		ab->phy.state = OTG_STATE_B_IDLE;
+		ab->phy.otg->default_a = false;
 		ab->vbus_draw = 0;
 		event = USB_EVENT_NONE;
 		break;
@@ -181,22 +181,22 @@
 	case USB_LINK_HOST_CHG_NM:
 	case USB_LINK_HOST_CHG_HS:
 	case USB_LINK_HOST_CHG_HS_CHIRP:
-		if (ab->otg.gadget) {
+		if (ab->phy.otg->gadget) {
 			/* TODO: Enable regulators. */
 			ab8500_usb_peri_phy_en(ab);
-			v = ab->otg.gadget;
+			v = ab->phy.otg->gadget;
 		}
 		event = USB_EVENT_VBUS;
 		break;
 
 	case USB_LINK_HM_IDGND:
-		if (ab->otg.host) {
+		if (ab->phy.otg->host) {
 			/* TODO: Enable regulators. */
 			ab8500_usb_host_phy_en(ab);
-			v = ab->otg.host;
+			v = ab->phy.otg->host;
 		}
-		ab->otg.state = OTG_STATE_A_IDLE;
-		ab->otg.default_a = true;
+		ab->phy.state = OTG_STATE_A_IDLE;
+		ab->phy.otg->default_a = true;
 		event = USB_EVENT_ID;
 		break;
 
@@ -212,7 +212,7 @@
 		break;
 	}
 
-	atomic_notifier_call_chain(&ab->otg.notifier, event, v);
+	atomic_notifier_call_chain(&ab->phy.notifier, event, v);
 
 	return 0;
 }
@@ -262,27 +262,27 @@
 	struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
 						phy_dis_work);
 
-	if (!ab->otg.host)
+	if (!ab->phy.otg->host)
 		ab8500_usb_host_phy_dis(ab);
 
-	if (!ab->otg.gadget)
+	if (!ab->phy.otg->gadget)
 		ab8500_usb_peri_phy_dis(ab);
 }
 
-static int ab8500_usb_set_power(struct otg_transceiver *otg, unsigned mA)
+static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA)
 {
 	struct ab8500_usb *ab;
 
-	if (!otg)
+	if (!phy)
 		return -ENODEV;
 
-	ab = xceiv_to_ab(otg);
+	ab = phy_to_ab(phy);
 
 	ab->vbus_draw = mA;
 
 	if (mA)
-		atomic_notifier_call_chain(&ab->otg.notifier,
-				USB_EVENT_ENUMERATED, ab->otg.gadget);
+		atomic_notifier_call_chain(&ab->phy.notifier,
+				USB_EVENT_ENUMERATED, ab->phy.otg->gadget);
 	return 0;
 }
 
@@ -290,21 +290,21 @@
  * ab->vbus_draw.
  */
 
-static int ab8500_usb_set_suspend(struct otg_transceiver *x, int suspend)
+static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend)
 {
 	/* TODO */
 	return 0;
 }
 
-static int ab8500_usb_set_peripheral(struct otg_transceiver *otg,
-		struct usb_gadget *gadget)
+static int ab8500_usb_set_peripheral(struct usb_otg *otg,
+					struct usb_gadget *gadget)
 {
 	struct ab8500_usb *ab;
 
 	if (!otg)
 		return -ENODEV;
 
-	ab = xceiv_to_ab(otg);
+	ab = phy_to_ab(otg->phy);
 
 	/* Some drivers call this function in atomic context.
 	 * Do not update ab8500 registers directly till this
@@ -313,11 +313,11 @@
 
 	if (!gadget) {
 		/* TODO: Disable regulators. */
-		ab->otg.gadget = NULL;
+		otg->gadget = NULL;
 		schedule_work(&ab->phy_dis_work);
 	} else {
-		ab->otg.gadget = gadget;
-		ab->otg.state = OTG_STATE_B_IDLE;
+		otg->gadget = gadget;
+		otg->phy->state = OTG_STATE_B_IDLE;
 
 		/* Phy will not be enabled if cable is already
 		 * plugged-in. Schedule to enable phy.
@@ -329,15 +329,14 @@
 	return 0;
 }
 
-static int ab8500_usb_set_host(struct otg_transceiver *otg,
-					struct usb_bus *host)
+static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
 {
 	struct ab8500_usb *ab;
 
 	if (!otg)
 		return -ENODEV;
 
-	ab = xceiv_to_ab(otg);
+	ab = phy_to_ab(otg->phy);
 
 	/* Some drivers call this function in atomic context.
 	 * Do not update ab8500 registers directly till this
@@ -346,10 +345,10 @@
 
 	if (!host) {
 		/* TODO: Disable regulators. */
-		ab->otg.host = NULL;
+		otg->host = NULL;
 		schedule_work(&ab->phy_dis_work);
 	} else {
-		ab->otg.host = host;
+		otg->host = host;
 		/* Phy will not be enabled if cable is already
 		 * plugged-in. Schedule to enable phy.
 		 * Use same delay to avoid any race condition.
@@ -472,6 +471,7 @@
 static int __devinit ab8500_usb_probe(struct platform_device *pdev)
 {
 	struct ab8500_usb	*ab;
+	struct usb_otg		*otg;
 	int err;
 	int rev;
 
@@ -488,19 +488,28 @@
 	if (!ab)
 		return -ENOMEM;
 
+	otg = kzalloc(sizeof *otg, GFP_KERNEL);
+	if (!otg) {
+		kfree(ab);
+		return -ENOMEM;
+	}
+
 	ab->dev			= &pdev->dev;
 	ab->rev			= rev;
-	ab->otg.dev		= ab->dev;
-	ab->otg.label		= "ab8500";
-	ab->otg.state		= OTG_STATE_UNDEFINED;
-	ab->otg.set_host	= ab8500_usb_set_host;
-	ab->otg.set_peripheral	= ab8500_usb_set_peripheral;
-	ab->otg.set_suspend	= ab8500_usb_set_suspend;
-	ab->otg.set_power	= ab8500_usb_set_power;
+	ab->phy.dev		= ab->dev;
+	ab->phy.otg		= otg;
+	ab->phy.label		= "ab8500";
+	ab->phy.set_suspend	= ab8500_usb_set_suspend;
+	ab->phy.set_power	= ab8500_usb_set_power;
+	ab->phy.state		= OTG_STATE_UNDEFINED;
+
+	otg->phy		= &ab->phy;
+	otg->set_host		= ab8500_usb_set_host;
+	otg->set_peripheral	= ab8500_usb_set_peripheral;
 
 	platform_set_drvdata(pdev, ab);
 
-	ATOMIC_INIT_NOTIFIER_HEAD(&ab->otg.notifier);
+	ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier);
 
 	/* v1: Wait for link status to become stable.
 	 * all: Updates form set_host and set_peripheral as they are atomic.
@@ -520,7 +529,7 @@
 	if (err < 0)
 		goto fail0;
 
-	err = otg_set_transceiver(&ab->otg);
+	err = usb_set_transceiver(&ab->phy);
 	if (err) {
 		dev_err(&pdev->dev, "Can't register transceiver\n");
 		goto fail1;
@@ -532,6 +541,7 @@
 fail1:
 	ab8500_usb_irq_free(ab);
 fail0:
+	kfree(otg);
 	kfree(ab);
 	return err;
 }
@@ -546,13 +556,14 @@
 
 	cancel_work_sync(&ab->phy_dis_work);
 
-	otg_set_transceiver(NULL);
+	usb_set_transceiver(NULL);
 
 	ab8500_usb_host_phy_dis(ab);
 	ab8500_usb_peri_phy_dis(ab);
 
 	platform_set_drvdata(pdev, NULL);
 
+	kfree(ab->phy.otg);
 	kfree(ab);
 
 	return 0;
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c
index a190850..be4a63e 100644
--- a/drivers/usb/otg/fsl_otg.c
+++ b/drivers/usb/otg/fsl_otg.c
@@ -275,7 +275,7 @@
 	fsl_otg_dischrg_vbus(0);
 	srp_wait_done = 1;
 
-	if ((fsl_otg_dev->otg.state == OTG_STATE_B_SRP_INIT) &&
+	if ((fsl_otg_dev->phy.state == OTG_STATE_B_SRP_INIT) &&
 	    fsl_otg_dev->fsm.b_sess_vld)
 		fsl_otg_dev->fsm.b_srp_done = 1;
 }
@@ -288,7 +288,7 @@
 void a_wait_enum(unsigned long foo)
 {
 	VDBG("a_wait_enum timeout\n");
-	if (!fsl_otg_dev->otg.host->b_hnp_enable)
+	if (!fsl_otg_dev->phy.otg->host->b_hnp_enable)
 		fsl_otg_add_timer(a_wait_enum_tmr);
 	else
 		otg_statemachine(&fsl_otg_dev->fsm);
@@ -452,14 +452,14 @@
 /* Call suspend/resume routines in host driver */
 int fsl_otg_start_host(struct otg_fsm *fsm, int on)
 {
-	struct otg_transceiver *xceiv = fsm->transceiver;
+	struct usb_otg *otg = fsm->otg;
 	struct device *dev;
-	struct fsl_otg *otg_dev = container_of(xceiv, struct fsl_otg, otg);
+	struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy);
 	u32 retval = 0;
 
-	if (!xceiv->host)
+	if (!otg->host)
 		return -ENODEV;
-	dev = xceiv->host->controller;
+	dev = otg->host->controller;
 
 	/*
 	 * Update a_vbus_vld state as a_vbus_vld int is disabled
@@ -518,14 +518,14 @@
  */
 int fsl_otg_start_gadget(struct otg_fsm *fsm, int on)
 {
-	struct otg_transceiver *xceiv = fsm->transceiver;
+	struct usb_otg *otg = fsm->otg;
 	struct device *dev;
 
-	if (!xceiv->gadget || !xceiv->gadget->dev.parent)
+	if (!otg->gadget || !otg->gadget->dev.parent)
 		return -ENODEV;
 
 	VDBG("gadget %s\n", on ? "on" : "off");
-	dev = xceiv->gadget->dev.parent;
+	dev = otg->gadget->dev.parent;
 
 	if (on) {
 		if (dev->driver->resume)
@@ -542,14 +542,14 @@
  * Called by initialization code of host driver.  Register host controller
  * to the OTG.  Suspend host for OTG role detection.
  */
-static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host)
+static int fsl_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
 {
-	struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg);
+	struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy);
 
-	if (!otg_p || otg_dev != fsl_otg_dev)
+	if (!otg || otg_dev != fsl_otg_dev)
 		return -ENODEV;
 
-	otg_p->host = host;
+	otg->host = host;
 
 	otg_dev->fsm.a_bus_drop = 0;
 	otg_dev->fsm.a_bus_req = 1;
@@ -557,8 +557,8 @@
 	if (host) {
 		VDBG("host off......\n");
 
-		otg_p->host->otg_port = fsl_otg_initdata.otg_port;
-		otg_p->host->is_b_host = otg_dev->fsm.id;
+		otg->host->otg_port = fsl_otg_initdata.otg_port;
+		otg->host->is_b_host = otg_dev->fsm.id;
 		/*
 		 * must leave time for khubd to finish its thing
 		 * before yanking the host driver out from under it,
@@ -574,7 +574,7 @@
 			/* Mini-A cable connected */
 			struct otg_fsm *fsm = &otg_dev->fsm;
 
-			otg_p->state = OTG_STATE_UNDEFINED;
+			otg->phy->state = OTG_STATE_UNDEFINED;
 			fsm->protocol = PROTO_UNDEF;
 		}
 	}
@@ -587,29 +587,29 @@
 }
 
 /* Called by initialization code of udc.  Register udc to OTG. */
-static int fsl_otg_set_peripheral(struct otg_transceiver *otg_p,
-				  struct usb_gadget *gadget)
+static int fsl_otg_set_peripheral(struct usb_otg *otg,
+					struct usb_gadget *gadget)
 {
-	struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg);
+	struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy);
 
 	VDBG("otg_dev 0x%x\n", (int)otg_dev);
 	VDBG("fsl_otg_dev 0x%x\n", (int)fsl_otg_dev);
 
-	if (!otg_p || otg_dev != fsl_otg_dev)
+	if (!otg || otg_dev != fsl_otg_dev)
 		return -ENODEV;
 
 	if (!gadget) {
-		if (!otg_dev->otg.default_a)
-			otg_p->gadget->ops->vbus_draw(otg_p->gadget, 0);
-		usb_gadget_vbus_disconnect(otg_dev->otg.gadget);
-		otg_dev->otg.gadget = 0;
+		if (!otg->default_a)
+			otg->gadget->ops->vbus_draw(otg->gadget, 0);
+		usb_gadget_vbus_disconnect(otg->gadget);
+		otg->gadget = 0;
 		otg_dev->fsm.b_bus_req = 0;
 		otg_statemachine(&otg_dev->fsm);
 		return 0;
 	}
 
-	otg_p->gadget = gadget;
-	otg_p->gadget->is_a_peripheral = !otg_dev->fsm.id;
+	otg->gadget = gadget;
+	otg->gadget->is_a_peripheral = !otg_dev->fsm.id;
 
 	otg_dev->fsm.b_bus_req = 1;
 
@@ -625,11 +625,11 @@
 }
 
 /* Set OTG port power, only for B-device */
-static int fsl_otg_set_power(struct otg_transceiver *otg_p, unsigned mA)
+static int fsl_otg_set_power(struct usb_phy *phy, unsigned mA)
 {
 	if (!fsl_otg_dev)
 		return -ENODEV;
-	if (otg_p->state == OTG_STATE_B_PERIPHERAL)
+	if (phy->state == OTG_STATE_B_PERIPHERAL)
 		pr_info("FSL OTG: Draw %d mA\n", mA);
 
 	return 0;
@@ -658,12 +658,12 @@
 }
 
 /* B-device start SRP */
-static int fsl_otg_start_srp(struct otg_transceiver *otg_p)
+static int fsl_otg_start_srp(struct usb_otg *otg)
 {
-	struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg);
+	struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy);
 
-	if (!otg_p || otg_dev != fsl_otg_dev
-	    || otg_p->state != OTG_STATE_B_IDLE)
+	if (!otg || otg_dev != fsl_otg_dev
+	    || otg->phy->state != OTG_STATE_B_IDLE)
 		return -ENODEV;
 
 	otg_dev->fsm.b_bus_req = 1;
@@ -673,11 +673,11 @@
 }
 
 /* A_host suspend will call this function to start hnp */
-static int fsl_otg_start_hnp(struct otg_transceiver *otg_p)
+static int fsl_otg_start_hnp(struct usb_otg *otg)
 {
-	struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg);
+	struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy);
 
-	if (!otg_p || otg_dev != fsl_otg_dev)
+	if (!otg || otg_dev != fsl_otg_dev)
 		return -ENODEV;
 
 	DBG("start_hnp...n");
@@ -698,7 +698,7 @@
 irqreturn_t fsl_otg_isr(int irq, void *dev_id)
 {
 	struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm;
-	struct otg_transceiver *otg = &((struct fsl_otg *)dev_id)->otg;
+	struct usb_otg *otg = ((struct fsl_otg *)dev_id)->phy.otg;
 	u32 otg_int_src, otg_sc;
 
 	otg_sc = fsl_readl(&usb_dr_regs->otgsc);
@@ -774,6 +774,12 @@
 	if (!fsl_otg_tc)
 		return -ENOMEM;
 
+	fsl_otg_tc->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
+	if (!fsl_otg_tc->phy.otg) {
+		kfree(fsl_otg_tc);
+		return -ENOMEM;
+	}
+
 	INIT_DELAYED_WORK(&fsl_otg_tc->otg_event, fsl_otg_event);
 
 	INIT_LIST_HEAD(&active_timers);
@@ -788,17 +794,19 @@
 	fsl_otg_tc->fsm.ops = &fsl_otg_ops;
 
 	/* initialize the otg structure */
-	fsl_otg_tc->otg.label = DRIVER_DESC;
-	fsl_otg_tc->otg.set_host = fsl_otg_set_host;
-	fsl_otg_tc->otg.set_peripheral = fsl_otg_set_peripheral;
-	fsl_otg_tc->otg.set_power = fsl_otg_set_power;
-	fsl_otg_tc->otg.start_hnp = fsl_otg_start_hnp;
-	fsl_otg_tc->otg.start_srp = fsl_otg_start_srp;
+	fsl_otg_tc->phy.label = DRIVER_DESC;
+	fsl_otg_tc->phy.set_power = fsl_otg_set_power;
+
+	fsl_otg_tc->phy.otg->phy = &fsl_otg_tc->phy;
+	fsl_otg_tc->phy.otg->set_host = fsl_otg_set_host;
+	fsl_otg_tc->phy.otg->set_peripheral = fsl_otg_set_peripheral;
+	fsl_otg_tc->phy.otg->start_hnp = fsl_otg_start_hnp;
+	fsl_otg_tc->phy.otg->start_srp = fsl_otg_start_srp;
 
 	fsl_otg_dev = fsl_otg_tc;
 
 	/* Store the otg transceiver */
-	status = otg_set_transceiver(&fsl_otg_tc->otg);
+	status = usb_set_transceiver(&fsl_otg_tc->phy);
 	if (status) {
 		pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n");
 		goto err;
@@ -807,6 +815,7 @@
 	return 0;
 err:
 	fsl_otg_uninit_timers();
+	kfree(fsl_otg_tc->phy.otg);
 	kfree(fsl_otg_tc);
 	return status;
 }
@@ -815,19 +824,19 @@
 int usb_otg_start(struct platform_device *pdev)
 {
 	struct fsl_otg *p_otg;
-	struct otg_transceiver *otg_trans = otg_get_transceiver();
+	struct usb_phy *otg_trans = usb_get_transceiver();
 	struct otg_fsm *fsm;
 	int status;
 	struct resource *res;
 	u32 temp;
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 
-	p_otg = container_of(otg_trans, struct fsl_otg, otg);
+	p_otg = container_of(otg_trans, struct fsl_otg, phy);
 	fsm = &p_otg->fsm;
 
 	/* Initialize the state machine structure with default values */
 	SET_OTG_STATE(otg_trans, OTG_STATE_UNDEFINED);
-	fsm->transceiver = &p_otg->otg;
+	fsm->otg = p_otg->phy.otg;
 
 	/* We don't require predefined MEM/IRQ resource index */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -857,9 +866,10 @@
 	status = request_irq(p_otg->irq, fsl_otg_isr,
 				IRQF_SHARED, driver_name, p_otg);
 	if (status) {
-		dev_dbg(p_otg->otg.dev, "can't get IRQ %d, error %d\n",
+		dev_dbg(p_otg->phy.dev, "can't get IRQ %d, error %d\n",
 			p_otg->irq, status);
 		iounmap(p_otg->dr_mem_map);
+		kfree(p_otg->phy.otg);
 		kfree(p_otg);
 		return status;
 	}
@@ -919,10 +929,10 @@
 	 * Also: record initial state of ID pin
 	 */
 	if (fsl_readl(&p_otg->dr_mem_map->otgsc) & OTGSC_STS_USB_ID) {
-		p_otg->otg.state = OTG_STATE_UNDEFINED;
+		p_otg->phy.state = OTG_STATE_UNDEFINED;
 		p_otg->fsm.id = 1;
 	} else {
-		p_otg->otg.state = OTG_STATE_A_IDLE;
+		p_otg->phy.state = OTG_STATE_A_IDLE;
 		p_otg->fsm.id = 0;
 	}
 
@@ -978,7 +988,7 @@
 	/* State */
 	t = scnprintf(next, size,
 		      "OTG state: %s\n\n",
-		      otg_state_string(fsl_otg_dev->otg.state));
+		      otg_state_string(fsl_otg_dev->phy.state));
 	size -= t;
 	next += t;
 
@@ -1124,12 +1134,13 @@
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 
-	otg_set_transceiver(NULL);
+	usb_set_transceiver(NULL);
 	free_irq(fsl_otg_dev->irq, fsl_otg_dev);
 
 	iounmap((void *)usb_dr_regs);
 
 	fsl_otg_uninit_timers();
+	kfree(fsl_otg_dev->phy.otg);
 	kfree(fsl_otg_dev);
 
 	device_remove_file(&pdev->dev, &dev_attr_fsl_usb2_otg_state);
diff --git a/drivers/usb/otg/fsl_otg.h b/drivers/usb/otg/fsl_otg.h
index 3f8ef73..ca26628 100644
--- a/drivers/usb/otg/fsl_otg.h
+++ b/drivers/usb/otg/fsl_otg.h
@@ -369,7 +369,7 @@
 }
 
 struct fsl_otg {
-	struct otg_transceiver otg;
+	struct usb_phy phy;
 	struct otg_fsm fsm;
 	struct usb_dr_mmap *dr_mem_map;
 	struct delayed_work otg_event;
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c
index fb644c1..3ece43a 100644
--- a/drivers/usb/otg/gpio_vbus.c
+++ b/drivers/usb/otg/gpio_vbus.c
@@ -32,7 +32,7 @@
  * Needs to be loaded before the UDC driver that will use it.
  */
 struct gpio_vbus_data {
-	struct otg_transceiver otg;
+	struct usb_phy		phy;
 	struct device          *dev;
 	struct regulator       *vbus_draw;
 	int			vbus_draw_enabled;
@@ -98,7 +98,7 @@
 	struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
 	int gpio;
 
-	if (!gpio_vbus->otg.gadget)
+	if (!gpio_vbus->phy.otg->gadget)
 		return;
 
 	/* Peripheral controllers which manage the pullup themselves won't have
@@ -108,8 +108,8 @@
 	 */
 	gpio = pdata->gpio_pullup;
 	if (is_vbus_powered(pdata)) {
-		gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL;
-		usb_gadget_vbus_connect(gpio_vbus->otg.gadget);
+		gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL;
+		usb_gadget_vbus_connect(gpio_vbus->phy.otg->gadget);
 
 		/* drawing a "unit load" is *always* OK, except for OTG */
 		set_vbus_draw(gpio_vbus, 100);
@@ -124,8 +124,8 @@
 
 		set_vbus_draw(gpio_vbus, 0);
 
-		usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget);
-		gpio_vbus->otg.state = OTG_STATE_B_IDLE;
+		usb_gadget_vbus_disconnect(gpio_vbus->phy.otg->gadget);
+		gpio_vbus->phy.state = OTG_STATE_B_IDLE;
 	}
 }
 
@@ -135,12 +135,13 @@
 	struct platform_device *pdev = data;
 	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
 	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
+	struct usb_otg *otg = gpio_vbus->phy.otg;
 
 	dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n",
 		is_vbus_powered(pdata) ? "supplied" : "inactive",
-		gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none");
+		otg->gadget ? otg->gadget->name : "none");
 
-	if (gpio_vbus->otg.gadget)
+	if (otg->gadget)
 		schedule_work(&gpio_vbus->work);
 
 	return IRQ_HANDLED;
@@ -149,15 +150,15 @@
 /* OTG transceiver interface */
 
 /* bind/unbind the peripheral controller */
-static int gpio_vbus_set_peripheral(struct otg_transceiver *otg,
-				struct usb_gadget *gadget)
+static int gpio_vbus_set_peripheral(struct usb_otg *otg,
+					struct usb_gadget *gadget)
 {
 	struct gpio_vbus_data *gpio_vbus;
 	struct gpio_vbus_mach_info *pdata;
 	struct platform_device *pdev;
 	int gpio, irq;
 
-	gpio_vbus = container_of(otg, struct gpio_vbus_data, otg);
+	gpio_vbus = container_of(otg->phy, struct gpio_vbus_data, phy);
 	pdev = to_platform_device(gpio_vbus->dev);
 	pdata = gpio_vbus->dev->platform_data;
 	irq = gpio_to_irq(pdata->gpio_vbus);
@@ -174,7 +175,7 @@
 		set_vbus_draw(gpio_vbus, 0);
 
 		usb_gadget_vbus_disconnect(otg->gadget);
-		otg->state = OTG_STATE_UNDEFINED;
+		otg->phy->state = OTG_STATE_UNDEFINED;
 
 		otg->gadget = NULL;
 		return 0;
@@ -189,23 +190,23 @@
 }
 
 /* effective for B devices, ignored for A-peripheral */
-static int gpio_vbus_set_power(struct otg_transceiver *otg, unsigned mA)
+static int gpio_vbus_set_power(struct usb_phy *phy, unsigned mA)
 {
 	struct gpio_vbus_data *gpio_vbus;
 
-	gpio_vbus = container_of(otg, struct gpio_vbus_data, otg);
+	gpio_vbus = container_of(phy, struct gpio_vbus_data, phy);
 
-	if (otg->state == OTG_STATE_B_PERIPHERAL)
+	if (phy->state == OTG_STATE_B_PERIPHERAL)
 		set_vbus_draw(gpio_vbus, mA);
 	return 0;
 }
 
 /* for non-OTG B devices: set/clear transceiver suspend mode */
-static int gpio_vbus_set_suspend(struct otg_transceiver *otg, int suspend)
+static int gpio_vbus_set_suspend(struct usb_phy *phy, int suspend)
 {
 	struct gpio_vbus_data *gpio_vbus;
 
-	gpio_vbus = container_of(otg, struct gpio_vbus_data, otg);
+	gpio_vbus = container_of(phy, struct gpio_vbus_data, phy);
 
 	/* draw max 0 mA from vbus in suspend mode; or the previously
 	 * recorded amount of current if not suspended
@@ -213,7 +214,7 @@
 	 * NOTE: high powered configs (mA > 100) may draw up to 2.5 mA
 	 * if they're wake-enabled ... we don't handle that yet.
 	 */
-	return gpio_vbus_set_power(otg, suspend ? 0 : gpio_vbus->mA);
+	return gpio_vbus_set_power(phy, suspend ? 0 : gpio_vbus->mA);
 }
 
 /* platform driver interface */
@@ -233,13 +234,21 @@
 	if (!gpio_vbus)
 		return -ENOMEM;
 
+	gpio_vbus->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
+	if (!gpio_vbus->phy.otg) {
+		kfree(gpio_vbus);
+		return -ENOMEM;
+	}
+
 	platform_set_drvdata(pdev, gpio_vbus);
 	gpio_vbus->dev = &pdev->dev;
-	gpio_vbus->otg.label = "gpio-vbus";
-	gpio_vbus->otg.state = OTG_STATE_UNDEFINED;
-	gpio_vbus->otg.set_peripheral = gpio_vbus_set_peripheral;
-	gpio_vbus->otg.set_power = gpio_vbus_set_power;
-	gpio_vbus->otg.set_suspend = gpio_vbus_set_suspend;
+	gpio_vbus->phy.label = "gpio-vbus";
+	gpio_vbus->phy.set_power = gpio_vbus_set_power;
+	gpio_vbus->phy.set_suspend = gpio_vbus_set_suspend;
+	gpio_vbus->phy.state = OTG_STATE_UNDEFINED;
+
+	gpio_vbus->phy.otg->phy = &gpio_vbus->phy;
+	gpio_vbus->phy.otg->set_peripheral = gpio_vbus_set_peripheral;
 
 	err = gpio_request(gpio, "vbus_detect");
 	if (err) {
@@ -288,7 +297,7 @@
 	}
 
 	/* only active when a gadget is registered */
-	err = otg_set_transceiver(&gpio_vbus->otg);
+	err = usb_set_transceiver(&gpio_vbus->phy);
 	if (err) {
 		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
 			err);
@@ -304,6 +313,7 @@
 	gpio_free(pdata->gpio_vbus);
 err_gpio:
 	platform_set_drvdata(pdev, NULL);
+	kfree(gpio_vbus->phy.otg);
 	kfree(gpio_vbus);
 	return err;
 }
@@ -316,13 +326,14 @@
 
 	regulator_put(gpio_vbus->vbus_draw);
 
-	otg_set_transceiver(NULL);
+	usb_set_transceiver(NULL);
 
 	free_irq(gpio_to_irq(gpio), &pdev->dev);
 	if (gpio_is_valid(pdata->gpio_pullup))
 		gpio_free(pdata->gpio_pullup);
 	gpio_free(gpio);
 	platform_set_drvdata(pdev, NULL);
+	kfree(gpio_vbus->phy.otg);
 	kfree(gpio_vbus);
 
 	return 0;
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
index 8c86787..70cf5d7 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/otg/isp1301_omap.c
@@ -52,7 +52,7 @@
 MODULE_LICENSE("GPL");
 
 struct isp1301 {
-	struct otg_transceiver	otg;
+	struct usb_phy		phy;
 	struct i2c_client	*client;
 	void			(*i2c_release)(struct device *dev);
 
@@ -236,7 +236,7 @@
 
 static inline const char *state_name(struct isp1301 *isp)
 {
-	return otg_state_string(isp->otg.state);
+	return otg_state_string(isp->phy.state);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -251,7 +251,7 @@
 
 static void power_down(struct isp1301 *isp)
 {
-	isp->otg.state = OTG_STATE_UNDEFINED;
+	isp->phy.state = OTG_STATE_UNDEFINED;
 
 	// isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
 	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND);
@@ -280,13 +280,13 @@
 #else
 	struct device	*dev;
 
-	if (!isp->otg.host)
+	if (!isp->phy.otg->host)
 		return -ENODEV;
 
 	/* Currently ASSUMES only the OTG port matters;
 	 * other ports could be active...
 	 */
-	dev = isp->otg.host->controller;
+	dev = isp->phy.otg->host->controller;
 	return dev->driver->suspend(dev, 3, 0);
 #endif
 }
@@ -298,20 +298,20 @@
 #else
 	struct device	*dev;
 
-	if (!isp->otg.host)
+	if (!isp->phy.otg->host)
 		return -ENODEV;
 
-	dev = isp->otg.host->controller;
+	dev = isp->phy.otg->host->controller;
 	return dev->driver->resume(dev, 0);
 #endif
 }
 
 static int gadget_suspend(struct isp1301 *isp)
 {
-	isp->otg.gadget->b_hnp_enable = 0;
-	isp->otg.gadget->a_hnp_support = 0;
-	isp->otg.gadget->a_alt_hnp_support = 0;
-	return usb_gadget_vbus_disconnect(isp->otg.gadget);
+	isp->phy.otg->gadget->b_hnp_enable = 0;
+	isp->phy.otg->gadget->a_hnp_support = 0;
+	isp->phy.otg->gadget->a_alt_hnp_support = 0;
+	return usb_gadget_vbus_disconnect(isp->phy.otg->gadget);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -341,19 +341,19 @@
 {
 	u32 l;
 
-	if (isp->otg.state == OTG_STATE_A_IDLE)
+	if (isp->phy.state == OTG_STATE_A_IDLE)
 		return;
 
-	isp->otg.default_a = 1;
-	if (isp->otg.host) {
-		isp->otg.host->is_b_host = 0;
+	isp->phy.otg->default_a = 1;
+	if (isp->phy.otg->host) {
+		isp->phy.otg->host->is_b_host = 0;
 		host_suspend(isp);
 	}
-	if (isp->otg.gadget) {
-		isp->otg.gadget->is_a_peripheral = 1;
+	if (isp->phy.otg->gadget) {
+		isp->phy.otg->gadget->is_a_peripheral = 1;
 		gadget_suspend(isp);
 	}
-	isp->otg.state = OTG_STATE_A_IDLE;
+	isp->phy.state = OTG_STATE_A_IDLE;
 	l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
 	omap_writel(l, OTG_CTRL);
 	isp->last_otg_ctrl = l;
@@ -365,19 +365,19 @@
 {
 	u32 l;
 
-	if (isp->otg.state == OTG_STATE_B_IDLE)
+	if (isp->phy.state == OTG_STATE_B_IDLE)
 		return;
 
-	isp->otg.default_a = 0;
-	if (isp->otg.host) {
-		isp->otg.host->is_b_host = 1;
+	isp->phy.otg->default_a = 0;
+	if (isp->phy.otg->host) {
+		isp->phy.otg->host->is_b_host = 1;
 		host_suspend(isp);
 	}
-	if (isp->otg.gadget) {
-		isp->otg.gadget->is_a_peripheral = 0;
+	if (isp->phy.otg->gadget) {
+		isp->phy.otg->gadget->is_a_peripheral = 0;
 		gadget_suspend(isp);
 	}
-	isp->otg.state = OTG_STATE_B_IDLE;
+	isp->phy.state = OTG_STATE_B_IDLE;
 	l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
 	omap_writel(l, OTG_CTRL);
 	isp->last_otg_ctrl = l;
@@ -478,7 +478,7 @@
 	default:
 		break;
 	}
-	if (isp->otg.state == state && !extra)
+	if (isp->phy.state == state && !extra)
 		return;
 	pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag,
 		otg_state_string(state), fsm, state_name(isp),
@@ -502,22 +502,23 @@
 
 	if (int_src & INTR_SESS_VLD)
 		otg_ctrl |= OTG_ASESSVLD;
-	else if (isp->otg.state == OTG_STATE_A_WAIT_VFALL) {
+	else if (isp->phy.state == OTG_STATE_A_WAIT_VFALL) {
 		a_idle(isp, "vfall");
 		otg_ctrl &= ~OTG_CTRL_BITS;
 	}
 	if (int_src & INTR_VBUS_VLD)
 		otg_ctrl |= OTG_VBUSVLD;
 	if (int_src & INTR_ID_GND) {		/* default-A */
-		if (isp->otg.state == OTG_STATE_B_IDLE
-				|| isp->otg.state == OTG_STATE_UNDEFINED) {
+		if (isp->phy.state == OTG_STATE_B_IDLE
+				|| isp->phy.state
+					== OTG_STATE_UNDEFINED) {
 			a_idle(isp, "init");
 			return;
 		}
 	} else {				/* default-B */
 		otg_ctrl |= OTG_ID;
-		if (isp->otg.state == OTG_STATE_A_IDLE
-				|| isp->otg.state == OTG_STATE_UNDEFINED) {
+		if (isp->phy.state == OTG_STATE_A_IDLE
+			|| isp->phy.state == OTG_STATE_UNDEFINED) {
 			b_idle(isp, "init");
 			return;
 		}
@@ -551,14 +552,14 @@
 	isp->last_otg_ctrl = otg_ctrl;
 	otg_ctrl = otg_ctrl & OTG_XCEIV_INPUTS;
 
-	switch (isp->otg.state) {
+	switch (isp->phy.state) {
 	case OTG_STATE_B_IDLE:
 	case OTG_STATE_B_PERIPHERAL:
 	case OTG_STATE_B_SRP_INIT:
 		if (!(otg_ctrl & OTG_PULLUP)) {
 			// if (otg_ctrl & OTG_B_HNPEN) {
-			if (isp->otg.gadget->b_hnp_enable) {
-				isp->otg.state = OTG_STATE_B_WAIT_ACON;
+			if (isp->phy.otg->gadget->b_hnp_enable) {
+				isp->phy.state = OTG_STATE_B_WAIT_ACON;
 				pr_debug("  --> b_wait_acon\n");
 			}
 			goto pulldown;
@@ -585,10 +586,10 @@
 		else clr |= ISP; \
 		} while (0)
 
-	if (!(isp->otg.host))
+	if (!(isp->phy.otg->host))
 		otg_ctrl &= ~OTG_DRV_VBUS;
 
-	switch (isp->otg.state) {
+	switch (isp->phy.state) {
 	case OTG_STATE_A_SUSPEND:
 		if (otg_ctrl & OTG_DRV_VBUS) {
 			set |= OTG1_VBUS_DRV;
@@ -599,7 +600,7 @@
 
 		/* FALLTHROUGH */
 	case OTG_STATE_A_VBUS_ERR:
-		isp->otg.state = OTG_STATE_A_WAIT_VFALL;
+		isp->phy.state = OTG_STATE_A_WAIT_VFALL;
 		pr_debug("  --> a_wait_vfall\n");
 		/* FALLTHROUGH */
 	case OTG_STATE_A_WAIT_VFALL:
@@ -608,7 +609,7 @@
 		break;
 	case OTG_STATE_A_IDLE:
 		if (otg_ctrl & OTG_DRV_VBUS) {
-			isp->otg.state = OTG_STATE_A_WAIT_VRISE;
+			isp->phy.state = OTG_STATE_A_WAIT_VRISE;
 			pr_debug("  --> a_wait_vrise\n");
 		}
 		/* FALLTHROUGH */
@@ -628,17 +629,17 @@
 	if (otg_change & OTG_PULLUP) {
 		u32 l;
 
-		switch (isp->otg.state) {
+		switch (isp->phy.state) {
 		case OTG_STATE_B_IDLE:
 			if (clr & OTG1_DP_PULLUP)
 				break;
-			isp->otg.state = OTG_STATE_B_PERIPHERAL;
+			isp->phy.state = OTG_STATE_B_PERIPHERAL;
 			pr_debug("  --> b_peripheral\n");
 			break;
 		case OTG_STATE_A_SUSPEND:
 			if (clr & OTG1_DP_PULLUP)
 				break;
-			isp->otg.state = OTG_STATE_A_PERIPHERAL;
+			isp->phy.state = OTG_STATE_A_PERIPHERAL;
 			pr_debug("  --> a_peripheral\n");
 			break;
 		default:
@@ -659,6 +660,7 @@
 	u32		otg_ctrl;
 	int		ret = IRQ_NONE;
 	struct isp1301	*isp = _isp;
+	struct usb_otg	*otg = isp->phy.otg;
 
 	/* update ISP1301 transceiver from OTG controller */
 	if (otg_irq & OPRT_CHG) {
@@ -675,7 +677,7 @@
 		 * remote wakeup (SRP, normal) using their own timer
 		 * to give "check cable and A-device" messages.
 		 */
-		if (isp->otg.state == OTG_STATE_B_SRP_INIT)
+		if (isp->phy.state == OTG_STATE_B_SRP_INIT)
 			b_idle(isp, "srp_timeout");
 
 		omap_writew(B_SRP_TMROUT, OTG_IRQ_SRC);
@@ -693,7 +695,7 @@
 		omap_writel(otg_ctrl, OTG_CTRL);
 
 		/* subset of b_peripheral()... */
-		isp->otg.state = OTG_STATE_B_PERIPHERAL;
+		isp->phy.state = OTG_STATE_B_PERIPHERAL;
 		pr_debug("  --> b_peripheral\n");
 
 		omap_writew(B_HNP_FAIL, OTG_IRQ_SRC);
@@ -705,9 +707,9 @@
 				state_name(isp), omap_readl(OTG_CTRL));
 
 		isp1301_defer_work(isp, WORK_UPDATE_OTG);
-		switch (isp->otg.state) {
+		switch (isp->phy.state) {
 		case OTG_STATE_A_IDLE:
-			if (!isp->otg.host)
+			if (!otg->host)
 				break;
 			isp1301_defer_work(isp, WORK_HOST_RESUME);
 			otg_ctrl = omap_readl(OTG_CTRL);
@@ -736,7 +738,7 @@
 		otg_ctrl |= OTG_BUSDROP;
 		otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
 		omap_writel(otg_ctrl, OTG_CTRL);
-		isp->otg.state = OTG_STATE_A_WAIT_VFALL;
+		isp->phy.state = OTG_STATE_A_WAIT_VFALL;
 
 		omap_writew(A_REQ_TMROUT, OTG_IRQ_SRC);
 		ret = IRQ_HANDLED;
@@ -750,7 +752,7 @@
 		otg_ctrl |= OTG_BUSDROP;
 		otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
 		omap_writel(otg_ctrl, OTG_CTRL);
-		isp->otg.state = OTG_STATE_A_VBUS_ERR;
+		isp->phy.state = OTG_STATE_A_VBUS_ERR;
 
 		omap_writew(A_VBUS_ERR, OTG_IRQ_SRC);
 		ret = IRQ_HANDLED;
@@ -771,7 +773,7 @@
 
 		/* role is peripheral */
 		if (otg_ctrl & OTG_DRIVER_SEL) {
-			switch (isp->otg.state) {
+			switch (isp->phy.state) {
 			case OTG_STATE_A_IDLE:
 				b_idle(isp, __func__);
 				break;
@@ -787,19 +789,19 @@
 				omap_writel(otg_ctrl | OTG_A_BUSREQ, OTG_CTRL);
 			}
 
-			if (isp->otg.host) {
-				switch (isp->otg.state) {
+			if (otg->host) {
+				switch (isp->phy.state) {
 				case OTG_STATE_B_WAIT_ACON:
-					isp->otg.state = OTG_STATE_B_HOST;
+					isp->phy.state = OTG_STATE_B_HOST;
 					pr_debug("  --> b_host\n");
 					kick = 1;
 					break;
 				case OTG_STATE_A_WAIT_BCON:
-					isp->otg.state = OTG_STATE_A_HOST;
+					isp->phy.state = OTG_STATE_A_HOST;
 					pr_debug("  --> a_host\n");
 					break;
 				case OTG_STATE_A_PERIPHERAL:
-					isp->otg.state = OTG_STATE_A_WAIT_BCON;
+					isp->phy.state = OTG_STATE_A_WAIT_BCON;
 					pr_debug("  --> a_wait_bcon\n");
 					break;
 				default:
@@ -813,8 +815,7 @@
 		ret = IRQ_HANDLED;
 
 		if (kick)
-			usb_bus_start_enum(isp->otg.host,
-						isp->otg.host->otg_port);
+			usb_bus_start_enum(otg->host, otg->host->otg_port);
 	}
 
 	check_state(isp, __func__);
@@ -930,7 +931,7 @@
 	l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
 	omap_writel(l, OTG_CTRL);
 
-	usb_gadget_vbus_connect(isp->otg.gadget);
+	usb_gadget_vbus_connect(isp->phy.otg->gadget);
 
 #ifdef	CONFIG_USB_OTG
 	enable_vbus_draw(isp, 8);
@@ -940,7 +941,7 @@
 	/* UDC driver just set OTG_BSESSVLD */
 	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP);
 	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN);
-	isp->otg.state = OTG_STATE_B_PERIPHERAL;
+	isp->phy.state = OTG_STATE_B_PERIPHERAL;
 	pr_debug("  --> b_peripheral\n");
 	dump_regs(isp, "2periph");
 #endif
@@ -948,8 +949,9 @@
 
 static void isp_update_otg(struct isp1301 *isp, u8 stat)
 {
+	struct usb_otg		*otg = isp->phy.otg;
 	u8			isp_stat, isp_bstat;
-	enum usb_otg_state	state = isp->otg.state;
+	enum usb_otg_state	state = isp->phy.state;
 
 	if (stat & INTR_BDIS_ACON)
 		pr_debug("OTG:  BDIS_ACON, %s\n", state_name(isp));
@@ -957,7 +959,7 @@
 	/* start certain state transitions right away */
 	isp_stat = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
 	if (isp_stat & INTR_ID_GND) {
-		if (isp->otg.default_a) {
+		if (otg->default_a) {
 			switch (state) {
 			case OTG_STATE_B_IDLE:
 				a_idle(isp, "idle");
@@ -972,7 +974,7 @@
 				 * when HNP is used.
 				 */
 				if (isp_stat & INTR_VBUS_VLD)
-					isp->otg.state = OTG_STATE_A_HOST;
+					isp->phy.state = OTG_STATE_A_HOST;
 				break;
 			case OTG_STATE_A_WAIT_VFALL:
 				if (!(isp_stat & INTR_SESS_VLD))
@@ -980,7 +982,7 @@
 				break;
 			default:
 				if (!(isp_stat & INTR_VBUS_VLD))
-					isp->otg.state = OTG_STATE_A_VBUS_ERR;
+					isp->phy.state = OTG_STATE_A_VBUS_ERR;
 				break;
 			}
 			isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
@@ -989,14 +991,14 @@
 			case OTG_STATE_B_PERIPHERAL:
 			case OTG_STATE_B_HOST:
 			case OTG_STATE_B_WAIT_ACON:
-				usb_gadget_vbus_disconnect(isp->otg.gadget);
+				usb_gadget_vbus_disconnect(otg->gadget);
 				break;
 			default:
 				break;
 			}
 			if (state != OTG_STATE_A_IDLE)
 				a_idle(isp, "id");
-			if (isp->otg.host && state == OTG_STATE_A_IDLE)
+			if (otg->host && state == OTG_STATE_A_IDLE)
 				isp1301_defer_work(isp, WORK_HOST_RESUME);
 			isp_bstat = 0;
 		}
@@ -1006,10 +1008,10 @@
 		/* if user unplugged mini-A end of cable,
 		 * don't bypass A_WAIT_VFALL.
 		 */
-		if (isp->otg.default_a) {
+		if (otg->default_a) {
 			switch (state) {
 			default:
-				isp->otg.state = OTG_STATE_A_WAIT_VFALL;
+				isp->phy.state = OTG_STATE_A_WAIT_VFALL;
 				break;
 			case OTG_STATE_A_WAIT_VFALL:
 				state = OTG_STATE_A_IDLE;
@@ -1022,7 +1024,7 @@
 				host_suspend(isp);
 				isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1,
 						MC1_BDIS_ACON_EN);
-				isp->otg.state = OTG_STATE_B_IDLE;
+				isp->phy.state = OTG_STATE_B_IDLE;
 				l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
 				l &= ~OTG_CTRL_BITS;
 				omap_writel(l, OTG_CTRL);
@@ -1033,7 +1035,7 @@
 		}
 		isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
 
-		switch (isp->otg.state) {
+		switch (isp->phy.state) {
 		case OTG_STATE_B_PERIPHERAL:
 		case OTG_STATE_B_WAIT_ACON:
 		case OTG_STATE_B_HOST:
@@ -1055,7 +1057,7 @@
 			omap_writel(l, OTG_CTRL);
 			/* FALLTHROUGH */
 		case OTG_STATE_B_IDLE:
-			if (isp->otg.gadget && (isp_bstat & OTG_B_SESS_VLD)) {
+			if (otg->gadget && (isp_bstat & OTG_B_SESS_VLD)) {
 #ifdef	CONFIG_USB_OTG
 				update_otg1(isp, isp_stat);
 				update_otg2(isp, isp_bstat);
@@ -1073,7 +1075,7 @@
 		}
 	}
 
-	if (state != isp->otg.state)
+	if (state != isp->phy.state)
 		pr_debug("  isp, %s -> %s\n",
 				otg_state_string(state), state_name(isp));
 
@@ -1131,10 +1133,10 @@
 			 * skip A_WAIT_VRISE; hc transitions invisibly
 			 * skip A_WAIT_BCON; same.
 			 */
-			switch (isp->otg.state) {
+			switch (isp->phy.state) {
 			case OTG_STATE_A_WAIT_BCON:
 			case OTG_STATE_A_WAIT_VRISE:
-				isp->otg.state = OTG_STATE_A_HOST;
+				isp->phy.state = OTG_STATE_A_HOST;
 				pr_debug("  --> a_host\n");
 				otg_ctrl = omap_readl(OTG_CTRL);
 				otg_ctrl |= OTG_A_BUSREQ;
@@ -1143,7 +1145,7 @@
 				omap_writel(otg_ctrl, OTG_CTRL);
 				break;
 			case OTG_STATE_B_WAIT_ACON:
-				isp->otg.state = OTG_STATE_B_HOST;
+				isp->phy.state = OTG_STATE_B_HOST;
 				pr_debug("  --> b_host (acon)\n");
 				break;
 			case OTG_STATE_B_HOST:
@@ -1204,6 +1206,7 @@
 	/* ugly -- i2c hijacks our memory hook to wait_for_completion() */
 	if (isp->i2c_release)
 		isp->i2c_release(dev);
+	kfree(isp->phy.otg);
 	kfree (isp);
 }
 
@@ -1274,9 +1277,9 @@
 
 /* add or disable the host device+driver */
 static int
-isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+isp1301_set_host(struct usb_otg *otg, struct usb_bus *host)
 {
-	struct isp1301	*isp = container_of(otg, struct isp1301, otg);
+	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
 
 	if (!otg || isp != the_transceiver)
 		return -ENODEV;
@@ -1284,21 +1287,21 @@
 	if (!host) {
 		omap_writew(0, OTG_IRQ_EN);
 		power_down(isp);
-		isp->otg.host = NULL;
+		otg->host = NULL;
 		return 0;
 	}
 
 #ifdef	CONFIG_USB_OTG
-	isp->otg.host = host;
+	otg->host = host;
 	dev_dbg(&isp->client->dev, "registered host\n");
 	host_suspend(isp);
-	if (isp->otg.gadget)
+	if (otg->gadget)
 		return isp1301_otg_enable(isp);
 	return 0;
 
 #elif	!defined(CONFIG_USB_GADGET_OMAP)
 	// FIXME update its refcount
-	isp->otg.host = host;
+	otg->host = host;
 
 	power_up(isp);
 
@@ -1330,9 +1333,9 @@
 }
 
 static int
-isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
+isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
 {
-	struct isp1301	*isp = container_of(otg, struct isp1301, otg);
+	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
 #ifndef	CONFIG_USB_OTG
 	u32 l;
 #endif
@@ -1342,24 +1345,24 @@
 
 	if (!gadget) {
 		omap_writew(0, OTG_IRQ_EN);
-		if (!isp->otg.default_a)
+		if (!otg->default_a)
 			enable_vbus_draw(isp, 0);
-		usb_gadget_vbus_disconnect(isp->otg.gadget);
-		isp->otg.gadget = NULL;
+		usb_gadget_vbus_disconnect(otg->gadget);
+		otg->gadget = NULL;
 		power_down(isp);
 		return 0;
 	}
 
 #ifdef	CONFIG_USB_OTG
-	isp->otg.gadget = gadget;
+	otg->gadget = gadget;
 	dev_dbg(&isp->client->dev, "registered gadget\n");
 	/* gadget driver may be suspended until vbus_connect () */
-	if (isp->otg.host)
+	if (otg->host)
 		return isp1301_otg_enable(isp);
 	return 0;
 
 #elif	!defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OHCI_HCD_MODULE)
-	isp->otg.gadget = gadget;
+	otg->gadget = gadget;
 	// FIXME update its refcount
 
 	l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
@@ -1368,7 +1371,7 @@
 	omap_writel(l, OTG_CTRL);
 
 	power_up(isp);
-	isp->otg.state = OTG_STATE_B_IDLE;
+	isp->phy.state = OTG_STATE_B_IDLE;
 
 	if (machine_is_omap_h2() || machine_is_omap_h3())
 		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
@@ -1399,7 +1402,7 @@
 /*-------------------------------------------------------------------------*/
 
 static int
-isp1301_set_power(struct otg_transceiver *dev, unsigned mA)
+isp1301_set_power(struct usb_phy *dev, unsigned mA)
 {
 	if (!the_transceiver)
 		return -ENODEV;
@@ -1409,13 +1412,13 @@
 }
 
 static int
-isp1301_start_srp(struct otg_transceiver *dev)
+isp1301_start_srp(struct usb_otg *otg)
 {
-	struct isp1301	*isp = container_of(dev, struct isp1301, otg);
+	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
 	u32		otg_ctrl;
 
-	if (!dev || isp != the_transceiver
-			|| isp->otg.state != OTG_STATE_B_IDLE)
+	if (!otg || isp != the_transceiver
+			|| isp->phy.state != OTG_STATE_B_IDLE)
 		return -ENODEV;
 
 	otg_ctrl = omap_readl(OTG_CTRL);
@@ -1425,7 +1428,7 @@
 	otg_ctrl |= OTG_B_BUSREQ;
 	otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK;
 	omap_writel(otg_ctrl, OTG_CTRL);
-	isp->otg.state = OTG_STATE_B_SRP_INIT;
+	isp->phy.state = OTG_STATE_B_SRP_INIT;
 
 	pr_debug("otg: SRP, %s ... %06x\n", state_name(isp),
 			omap_readl(OTG_CTRL));
@@ -1436,27 +1439,26 @@
 }
 
 static int
-isp1301_start_hnp(struct otg_transceiver *dev)
+isp1301_start_hnp(struct usb_otg *otg)
 {
 #ifdef	CONFIG_USB_OTG
-	struct isp1301	*isp = container_of(dev, struct isp1301, otg);
+	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);
 	u32 l;
 
-	if (!dev || isp != the_transceiver)
+	if (!otg || isp != the_transceiver)
 		return -ENODEV;
-	if (isp->otg.default_a && (isp->otg.host == NULL
-			|| !isp->otg.host->b_hnp_enable))
+	if (otg->default_a && (otg->host == NULL || !otg->host->b_hnp_enable))
 		return -ENOTCONN;
-	if (!isp->otg.default_a && (isp->otg.gadget == NULL
-			|| !isp->otg.gadget->b_hnp_enable))
+	if (!otg->default_a && (otg->gadget == NULL
+			|| !otg->gadget->b_hnp_enable))
 		return -ENOTCONN;
 
 	/* We want hardware to manage most HNP protocol timings.
 	 * So do this part as early as possible...
 	 */
-	switch (isp->otg.state) {
+	switch (isp->phy.state) {
 	case OTG_STATE_B_HOST:
-		isp->otg.state = OTG_STATE_B_PERIPHERAL;
+		isp->phy.state = OTG_STATE_B_PERIPHERAL;
 		/* caller will suspend next */
 		break;
 	case OTG_STATE_A_HOST:
@@ -1466,7 +1468,7 @@
 				MC1_BDIS_ACON_EN);
 #endif
 		/* caller must suspend then clear A_BUSREQ */
-		usb_gadget_vbus_connect(isp->otg.gadget);
+		usb_gadget_vbus_connect(otg->gadget);
 		l = omap_readl(OTG_CTRL);
 		l |= OTG_A_SETB_HNPEN;
 		omap_writel(l, OTG_CTRL);
@@ -1503,6 +1505,12 @@
 	if (!isp)
 		return 0;
 
+	isp->phy.otg = kzalloc(sizeof *isp->phy.otg, GFP_KERNEL);
+	if (!isp->phy.otg) {
+		kfree(isp);
+		return 0;
+	}
+
 	INIT_WORK(&isp->work, isp1301_work);
 	init_timer(&isp->timer);
 	isp->timer.function = isp1301_timer;
@@ -1576,14 +1584,15 @@
 		goto fail;
 	}
 
-	isp->otg.dev = &i2c->dev;
-	isp->otg.label = DRIVER_NAME;
+	isp->phy.dev = &i2c->dev;
+	isp->phy.label = DRIVER_NAME;
+	isp->phy.set_power = isp1301_set_power,
 
-	isp->otg.set_host = isp1301_set_host,
-	isp->otg.set_peripheral = isp1301_set_peripheral,
-	isp->otg.set_power = isp1301_set_power,
-	isp->otg.start_srp = isp1301_start_srp,
-	isp->otg.start_hnp = isp1301_start_hnp,
+	isp->phy.otg->phy = &isp->phy;
+	isp->phy.otg->set_host = isp1301_set_host,
+	isp->phy.otg->set_peripheral = isp1301_set_peripheral,
+	isp->phy.otg->start_srp = isp1301_start_srp,
+	isp->phy.otg->start_hnp = isp1301_start_hnp,
 
 	enable_vbus_draw(isp, 0);
 	power_down(isp);
@@ -1601,7 +1610,7 @@
 	dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
 #endif
 
-	status = otg_set_transceiver(&isp->otg);
+	status = usb_set_transceiver(&isp->phy);
 	if (status < 0)
 		dev_err(&i2c->dev, "can't register transceiver, %d\n",
 			status);
@@ -1609,6 +1618,7 @@
 	return 0;
 
 fail:
+	kfree(isp->phy.otg);
 	kfree(isp);
 	return -ENODEV;
 }
@@ -1639,7 +1649,7 @@
 static void __exit isp_exit(void)
 {
 	if (the_transceiver)
-		otg_set_transceiver(NULL);
+		usb_set_transceiver(NULL);
 	i2c_del_driver(&isp1301_driver);
 }
 module_exit(isp_exit);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index b276f8f..1d0347c2 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -69,9 +69,9 @@
 	int ret = 0;
 
 	if (init) {
-		hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
+		hsusb_vddcx = regulator_get(motg->phy.dev, "HSUSB_VDDCX");
 		if (IS_ERR(hsusb_vddcx)) {
-			dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
+			dev_err(motg->phy.dev, "unable to get hsusb vddcx\n");
 			return PTR_ERR(hsusb_vddcx);
 		}
 
@@ -79,7 +79,7 @@
 				USB_PHY_VDD_DIG_VOL_MIN,
 				USB_PHY_VDD_DIG_VOL_MAX);
 		if (ret) {
-			dev_err(motg->otg.dev, "unable to set the voltage "
+			dev_err(motg->phy.dev, "unable to set the voltage "
 					"for hsusb vddcx\n");
 			regulator_put(hsusb_vddcx);
 			return ret;
@@ -87,18 +87,18 @@
 
 		ret = regulator_enable(hsusb_vddcx);
 		if (ret) {
-			dev_err(motg->otg.dev, "unable to enable hsusb vddcx\n");
+			dev_err(motg->phy.dev, "unable to enable hsusb vddcx\n");
 			regulator_put(hsusb_vddcx);
 		}
 	} else {
 		ret = regulator_set_voltage(hsusb_vddcx, 0,
 			USB_PHY_VDD_DIG_VOL_MAX);
 		if (ret)
-			dev_err(motg->otg.dev, "unable to set the voltage "
+			dev_err(motg->phy.dev, "unable to set the voltage "
 					"for hsusb vddcx\n");
 		ret = regulator_disable(hsusb_vddcx);
 		if (ret)
-			dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
+			dev_err(motg->phy.dev, "unable to disable hsusb vddcx\n");
 
 		regulator_put(hsusb_vddcx);
 	}
@@ -111,40 +111,40 @@
 	int rc = 0;
 
 	if (init) {
-		hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
+		hsusb_3p3 = regulator_get(motg->phy.dev, "HSUSB_3p3");
 		if (IS_ERR(hsusb_3p3)) {
-			dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
+			dev_err(motg->phy.dev, "unable to get hsusb 3p3\n");
 			return PTR_ERR(hsusb_3p3);
 		}
 
 		rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
 				USB_PHY_3P3_VOL_MAX);
 		if (rc) {
-			dev_err(motg->otg.dev, "unable to set voltage level "
+			dev_err(motg->phy.dev, "unable to set voltage level "
 					"for hsusb 3p3\n");
 			goto put_3p3;
 		}
 		rc = regulator_enable(hsusb_3p3);
 		if (rc) {
-			dev_err(motg->otg.dev, "unable to enable the hsusb 3p3\n");
+			dev_err(motg->phy.dev, "unable to enable the hsusb 3p3\n");
 			goto put_3p3;
 		}
-		hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
+		hsusb_1p8 = regulator_get(motg->phy.dev, "HSUSB_1p8");
 		if (IS_ERR(hsusb_1p8)) {
-			dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
+			dev_err(motg->phy.dev, "unable to get hsusb 1p8\n");
 			rc = PTR_ERR(hsusb_1p8);
 			goto disable_3p3;
 		}
 		rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
 				USB_PHY_1P8_VOL_MAX);
 		if (rc) {
-			dev_err(motg->otg.dev, "unable to set voltage level "
+			dev_err(motg->phy.dev, "unable to set voltage level "
 					"for hsusb 1p8\n");
 			goto put_1p8;
 		}
 		rc = regulator_enable(hsusb_1p8);
 		if (rc) {
-			dev_err(motg->otg.dev, "unable to enable the hsusb 1p8\n");
+			dev_err(motg->phy.dev, "unable to enable the hsusb 1p8\n");
 			goto put_1p8;
 		}
 
@@ -235,9 +235,9 @@
 	return ret < 0 ? ret : 0;
 }
 
-static int ulpi_read(struct otg_transceiver *otg, u32 reg)
+static int ulpi_read(struct usb_phy *phy, u32 reg)
 {
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
 	int cnt = 0;
 
 	/* initiate read operation */
@@ -253,16 +253,16 @@
 	}
 
 	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
-		dev_err(otg->dev, "ulpi_read: timeout %08x\n",
+		dev_err(phy->dev, "ulpi_read: timeout %08x\n",
 			readl(USB_ULPI_VIEWPORT));
 		return -ETIMEDOUT;
 	}
 	return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT));
 }
 
-static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
+static int ulpi_write(struct usb_phy *phy, u32 val, u32 reg)
 {
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
 	int cnt = 0;
 
 	/* initiate write operation */
@@ -279,13 +279,13 @@
 	}
 
 	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
-		dev_err(otg->dev, "ulpi_write: timeout\n");
+		dev_err(phy->dev, "ulpi_write: timeout\n");
 		return -ETIMEDOUT;
 	}
 	return 0;
 }
 
-static struct otg_io_access_ops msm_otg_io_ops = {
+static struct usb_phy_io_ops msm_otg_io_ops = {
 	.read = ulpi_read,
 	.write = ulpi_write,
 };
@@ -299,9 +299,9 @@
 		return;
 
 	while (seq[0] >= 0) {
-		dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n",
+		dev_vdbg(motg->phy.dev, "ulpi: write 0x%02x to 0x%02x\n",
 				seq[0], seq[1]);
-		ulpi_write(&motg->otg, seq[0], seq[1]);
+		ulpi_write(&motg->phy, seq[0], seq[1]);
 		seq += 2;
 	}
 }
@@ -313,11 +313,11 @@
 	if (assert) {
 		ret = clk_reset(motg->clk, CLK_RESET_ASSERT);
 		if (ret)
-			dev_err(motg->otg.dev, "usb hs_clk assert failed\n");
+			dev_err(motg->phy.dev, "usb hs_clk assert failed\n");
 	} else {
 		ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
 		if (ret)
-			dev_err(motg->otg.dev, "usb hs_clk deassert failed\n");
+			dev_err(motg->phy.dev, "usb hs_clk deassert failed\n");
 	}
 	return ret;
 }
@@ -328,13 +328,13 @@
 
 	ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
 	if (ret) {
-		dev_err(motg->otg.dev, "usb phy clk assert failed\n");
+		dev_err(motg->phy.dev, "usb phy clk assert failed\n");
 		return ret;
 	}
 	usleep_range(10000, 12000);
 	ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
 	if (ret)
-		dev_err(motg->otg.dev, "usb phy clk deassert failed\n");
+		dev_err(motg->phy.dev, "usb phy clk deassert failed\n");
 	return ret;
 }
 
@@ -358,7 +358,7 @@
 	writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
 
 	for (retries = 3; retries > 0; retries--) {
-		ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM,
+		ret = ulpi_write(&motg->phy, ULPI_FUNC_CTRL_SUSPENDM,
 				ULPI_CLR(ULPI_FUNC_CTRL));
 		if (!ret)
 			break;
@@ -375,7 +375,7 @@
 		return ret;
 
 	for (retries = 3; retries > 0; retries--) {
-		ret = ulpi_read(&motg->otg, ULPI_DEBUG);
+		ret = ulpi_read(&motg->phy, ULPI_DEBUG);
 		if (ret != -ETIMEDOUT)
 			break;
 		ret = msm_otg_phy_clk_reset(motg);
@@ -385,14 +385,14 @@
 	if (!retries)
 		return -ETIMEDOUT;
 
-	dev_info(motg->otg.dev, "phy_reset: success\n");
+	dev_info(motg->phy.dev, "phy_reset: success\n");
 	return 0;
 }
 
 #define LINK_RESET_TIMEOUT_USEC		(250 * 1000)
-static int msm_otg_reset(struct otg_transceiver *otg)
+static int msm_otg_reset(struct usb_phy *phy)
 {
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
 	struct msm_otg_platform_data *pdata = motg->pdata;
 	int cnt = 0;
 	int ret;
@@ -401,7 +401,7 @@
 
 	ret = msm_otg_phy_reset(motg);
 	if (ret) {
-		dev_err(otg->dev, "phy_reset failed\n");
+		dev_err(phy->dev, "phy_reset failed\n");
 		return ret;
 	}
 
@@ -435,8 +435,8 @@
 			val |= OTGSC_BSVIE;
 		}
 		writel(val, USB_OTGSC);
-		ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
-		ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
+		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_RISE);
+		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_FALL);
 	}
 
 	return 0;
@@ -448,8 +448,8 @@
 #ifdef CONFIG_PM_SLEEP
 static int msm_otg_suspend(struct msm_otg *motg)
 {
-	struct otg_transceiver *otg = &motg->otg;
-	struct usb_bus *bus = otg->host;
+	struct usb_phy *phy = &motg->phy;
+	struct usb_bus *bus = phy->otg->host;
 	struct msm_otg_platform_data *pdata = motg->pdata;
 	int cnt = 0;
 
@@ -475,10 +475,10 @@
 	 */
 
 	if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
-		ulpi_read(otg, 0x14);
+		ulpi_read(phy, 0x14);
 		if (pdata->otg_control == OTG_PHY_CONTROL)
-			ulpi_write(otg, 0x01, 0x30);
-		ulpi_write(otg, 0x08, 0x09);
+			ulpi_write(phy, 0x01, 0x30);
+		ulpi_write(phy, 0x08, 0x09);
 	}
 
 	/*
@@ -495,8 +495,8 @@
 	}
 
 	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
-		dev_err(otg->dev, "Unable to suspend PHY\n");
-		msm_otg_reset(otg);
+		dev_err(phy->dev, "Unable to suspend PHY\n");
+		msm_otg_reset(phy);
 		enable_irq(motg->irq);
 		return -ETIMEDOUT;
 	}
@@ -528,7 +528,7 @@
 		msm_hsusb_config_vddcx(0);
 	}
 
-	if (device_may_wakeup(otg->dev))
+	if (device_may_wakeup(phy->dev))
 		enable_irq_wake(motg->irq);
 	if (bus)
 		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
@@ -536,15 +536,15 @@
 	atomic_set(&motg->in_lpm, 1);
 	enable_irq(motg->irq);
 
-	dev_info(otg->dev, "USB in low power mode\n");
+	dev_info(phy->dev, "USB in low power mode\n");
 
 	return 0;
 }
 
 static int msm_otg_resume(struct msm_otg *motg)
 {
-	struct otg_transceiver *otg = &motg->otg;
-	struct usb_bus *bus = otg->host;
+	struct usb_phy *phy = &motg->phy;
+	struct usb_bus *bus = phy->otg->host;
 	int cnt = 0;
 	unsigned temp;
 
@@ -592,13 +592,13 @@
 		 * PHY. USB state can not be restored. Re-insertion
 		 * of USB cable is the only way to get USB working.
 		 */
-		dev_err(otg->dev, "Unable to resume USB."
+		dev_err(phy->dev, "Unable to resume USB."
 				"Re-plugin the cable\n");
-		msm_otg_reset(otg);
+		msm_otg_reset(phy);
 	}
 
 skip_phy_resume:
-	if (device_may_wakeup(otg->dev))
+	if (device_may_wakeup(phy->dev))
 		disable_irq_wake(motg->irq);
 	if (bus)
 		set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
@@ -607,11 +607,11 @@
 
 	if (motg->async_int) {
 		motg->async_int = 0;
-		pm_runtime_put(otg->dev);
+		pm_runtime_put(phy->dev);
 		enable_irq(motg->irq);
 	}
 
-	dev_info(otg->dev, "USB exited from low power mode\n");
+	dev_info(phy->dev, "USB exited from low power mode\n");
 
 	return 0;
 }
@@ -623,13 +623,13 @@
 		return;
 
 	/* TODO: Notify PMIC about available current */
-	dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
+	dev_info(motg->phy.dev, "Avail curr from USB = %u\n", mA);
 	motg->cur_power = mA;
 }
 
-static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
+static int msm_otg_set_power(struct usb_phy *phy, unsigned mA)
 {
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
 
 	/*
 	 * Gadget driver uses set_power method to notify about the
@@ -644,19 +644,19 @@
 	return 0;
 }
 
-static void msm_otg_start_host(struct otg_transceiver *otg, int on)
+static void msm_otg_start_host(struct usb_phy *phy, int on)
 {
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
 	struct msm_otg_platform_data *pdata = motg->pdata;
 	struct usb_hcd *hcd;
 
-	if (!otg->host)
+	if (!phy->otg->host)
 		return;
 
-	hcd = bus_to_hcd(otg->host);
+	hcd = bus_to_hcd(phy->otg->host);
 
 	if (on) {
-		dev_dbg(otg->dev, "host on\n");
+		dev_dbg(phy->dev, "host on\n");
 
 		if (pdata->vbus_power)
 			pdata->vbus_power(1);
@@ -671,7 +671,7 @@
 		usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
 #endif
 	} else {
-		dev_dbg(otg->dev, "host off\n");
+		dev_dbg(phy->dev, "host off\n");
 
 #ifdef CONFIG_USB
 		usb_remove_hcd(hcd);
@@ -683,9 +683,9 @@
 	}
 }
 
-static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+static int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
 {
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy);
 	struct usb_hcd *hcd;
 
 	/*
@@ -693,16 +693,16 @@
 	 * only peripheral configuration.
 	 */
 	if (motg->pdata->mode == USB_PERIPHERAL) {
-		dev_info(otg->dev, "Host mode is not supported\n");
+		dev_info(otg->phy->dev, "Host mode is not supported\n");
 		return -ENODEV;
 	}
 
 	if (!host) {
-		if (otg->state == OTG_STATE_A_HOST) {
-			pm_runtime_get_sync(otg->dev);
-			msm_otg_start_host(otg, 0);
+		if (otg->phy->state == OTG_STATE_A_HOST) {
+			pm_runtime_get_sync(otg->phy->dev);
+			msm_otg_start_host(otg->phy, 0);
 			otg->host = NULL;
-			otg->state = OTG_STATE_UNDEFINED;
+			otg->phy->state = OTG_STATE_UNDEFINED;
 			schedule_work(&motg->sm_work);
 		} else {
 			otg->host = NULL;
@@ -715,30 +715,30 @@
 	hcd->power_budget = motg->pdata->power_budget;
 
 	otg->host = host;
-	dev_dbg(otg->dev, "host driver registered w/ tranceiver\n");
+	dev_dbg(otg->phy->dev, "host driver registered w/ tranceiver\n");
 
 	/*
 	 * Kick the state machine work, if peripheral is not supported
 	 * or peripheral is already registered with us.
 	 */
 	if (motg->pdata->mode == USB_HOST || otg->gadget) {
-		pm_runtime_get_sync(otg->dev);
+		pm_runtime_get_sync(otg->phy->dev);
 		schedule_work(&motg->sm_work);
 	}
 
 	return 0;
 }
 
-static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
+static void msm_otg_start_peripheral(struct usb_phy *phy, int on)
 {
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
 	struct msm_otg_platform_data *pdata = motg->pdata;
 
-	if (!otg->gadget)
+	if (!phy->otg->gadget)
 		return;
 
 	if (on) {
-		dev_dbg(otg->dev, "gadget on\n");
+		dev_dbg(phy->dev, "gadget on\n");
 		/*
 		 * Some boards have a switch cotrolled by gpio
 		 * to enable/disable internal HUB. Disable internal
@@ -746,36 +746,36 @@
 		 */
 		if (pdata->setup_gpio)
 			pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
-		usb_gadget_vbus_connect(otg->gadget);
+		usb_gadget_vbus_connect(phy->otg->gadget);
 	} else {
-		dev_dbg(otg->dev, "gadget off\n");
-		usb_gadget_vbus_disconnect(otg->gadget);
+		dev_dbg(phy->dev, "gadget off\n");
+		usb_gadget_vbus_disconnect(phy->otg->gadget);
 		if (pdata->setup_gpio)
 			pdata->setup_gpio(OTG_STATE_UNDEFINED);
 	}
 
 }
 
-static int msm_otg_set_peripheral(struct otg_transceiver *otg,
-			struct usb_gadget *gadget)
+static int msm_otg_set_peripheral(struct usb_otg *otg,
+					struct usb_gadget *gadget)
 {
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy);
 
 	/*
 	 * Fail peripheral registration if this board can support
 	 * only host configuration.
 	 */
 	if (motg->pdata->mode == USB_HOST) {
-		dev_info(otg->dev, "Peripheral mode is not supported\n");
+		dev_info(otg->phy->dev, "Peripheral mode is not supported\n");
 		return -ENODEV;
 	}
 
 	if (!gadget) {
-		if (otg->state == OTG_STATE_B_PERIPHERAL) {
-			pm_runtime_get_sync(otg->dev);
-			msm_otg_start_peripheral(otg, 0);
+		if (otg->phy->state == OTG_STATE_B_PERIPHERAL) {
+			pm_runtime_get_sync(otg->phy->dev);
+			msm_otg_start_peripheral(otg->phy, 0);
 			otg->gadget = NULL;
-			otg->state = OTG_STATE_UNDEFINED;
+			otg->phy->state = OTG_STATE_UNDEFINED;
 			schedule_work(&motg->sm_work);
 		} else {
 			otg->gadget = NULL;
@@ -784,14 +784,14 @@
 		return 0;
 	}
 	otg->gadget = gadget;
-	dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n");
+	dev_dbg(otg->phy->dev, "peripheral driver registered w/ tranceiver\n");
 
 	/*
 	 * Kick the state machine work, if host is not supported
 	 * or host is already registered with us.
 	 */
 	if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
-		pm_runtime_get_sync(otg->dev);
+		pm_runtime_get_sync(otg->phy->dev);
 		schedule_work(&motg->sm_work);
 	}
 
@@ -800,17 +800,17 @@
 
 static bool msm_chg_check_secondary_det(struct msm_otg *motg)
 {
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_phy *phy = &motg->phy;
 	u32 chg_det;
 	bool ret = false;
 
 	switch (motg->pdata->phy_type) {
 	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(otg, 0x34);
+		chg_det = ulpi_read(phy, 0x34);
 		ret = chg_det & (1 << 4);
 		break;
 	case SNPS_28NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(otg, 0x87);
+		chg_det = ulpi_read(phy, 0x87);
 		ret = chg_det & 1;
 		break;
 	default:
@@ -821,38 +821,38 @@
 
 static void msm_chg_enable_secondary_det(struct msm_otg *motg)
 {
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_phy *phy = &motg->phy;
 	u32 chg_det;
 
 	switch (motg->pdata->phy_type) {
 	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(otg, 0x34);
+		chg_det = ulpi_read(phy, 0x34);
 		/* Turn off charger block */
 		chg_det |= ~(1 << 1);
-		ulpi_write(otg, chg_det, 0x34);
+		ulpi_write(phy, chg_det, 0x34);
 		udelay(20);
 		/* control chg block via ULPI */
 		chg_det &= ~(1 << 3);
-		ulpi_write(otg, chg_det, 0x34);
+		ulpi_write(phy, chg_det, 0x34);
 		/* put it in host mode for enabling D- source */
 		chg_det &= ~(1 << 2);
-		ulpi_write(otg, chg_det, 0x34);
+		ulpi_write(phy, chg_det, 0x34);
 		/* Turn on chg detect block */
 		chg_det &= ~(1 << 1);
-		ulpi_write(otg, chg_det, 0x34);
+		ulpi_write(phy, chg_det, 0x34);
 		udelay(20);
 		/* enable chg detection */
 		chg_det &= ~(1 << 0);
-		ulpi_write(otg, chg_det, 0x34);
+		ulpi_write(phy, chg_det, 0x34);
 		break;
 	case SNPS_28NM_INTEGRATED_PHY:
 		/*
 		 * Configure DM as current source, DP as current sink
 		 * and enable battery charging comparators.
 		 */
-		ulpi_write(otg, 0x8, 0x85);
-		ulpi_write(otg, 0x2, 0x85);
-		ulpi_write(otg, 0x1, 0x85);
+		ulpi_write(phy, 0x8, 0x85);
+		ulpi_write(phy, 0x2, 0x85);
+		ulpi_write(phy, 0x1, 0x85);
 		break;
 	default:
 		break;
@@ -861,17 +861,17 @@
 
 static bool msm_chg_check_primary_det(struct msm_otg *motg)
 {
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_phy *phy = &motg->phy;
 	u32 chg_det;
 	bool ret = false;
 
 	switch (motg->pdata->phy_type) {
 	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(otg, 0x34);
+		chg_det = ulpi_read(phy, 0x34);
 		ret = chg_det & (1 << 4);
 		break;
 	case SNPS_28NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(otg, 0x87);
+		chg_det = ulpi_read(phy, 0x87);
 		ret = chg_det & 1;
 		break;
 	default:
@@ -882,23 +882,23 @@
 
 static void msm_chg_enable_primary_det(struct msm_otg *motg)
 {
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_phy *phy = &motg->phy;
 	u32 chg_det;
 
 	switch (motg->pdata->phy_type) {
 	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(otg, 0x34);
+		chg_det = ulpi_read(phy, 0x34);
 		/* enable chg detection */
 		chg_det &= ~(1 << 0);
-		ulpi_write(otg, chg_det, 0x34);
+		ulpi_write(phy, chg_det, 0x34);
 		break;
 	case SNPS_28NM_INTEGRATED_PHY:
 		/*
 		 * Configure DP as current source, DM as current sink
 		 * and enable battery charging comparators.
 		 */
-		ulpi_write(otg, 0x2, 0x85);
-		ulpi_write(otg, 0x1, 0x85);
+		ulpi_write(phy, 0x2, 0x85);
+		ulpi_write(phy, 0x1, 0x85);
 		break;
 	default:
 		break;
@@ -907,17 +907,17 @@
 
 static bool msm_chg_check_dcd(struct msm_otg *motg)
 {
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_phy *phy = &motg->phy;
 	u32 line_state;
 	bool ret = false;
 
 	switch (motg->pdata->phy_type) {
 	case CI_45NM_INTEGRATED_PHY:
-		line_state = ulpi_read(otg, 0x15);
+		line_state = ulpi_read(phy, 0x15);
 		ret = !(line_state & 1);
 		break;
 	case SNPS_28NM_INTEGRATED_PHY:
-		line_state = ulpi_read(otg, 0x87);
+		line_state = ulpi_read(phy, 0x87);
 		ret = line_state & 2;
 		break;
 	default:
@@ -928,17 +928,17 @@
 
 static void msm_chg_disable_dcd(struct msm_otg *motg)
 {
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_phy *phy = &motg->phy;
 	u32 chg_det;
 
 	switch (motg->pdata->phy_type) {
 	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(otg, 0x34);
+		chg_det = ulpi_read(phy, 0x34);
 		chg_det &= ~(1 << 5);
-		ulpi_write(otg, chg_det, 0x34);
+		ulpi_write(phy, chg_det, 0x34);
 		break;
 	case SNPS_28NM_INTEGRATED_PHY:
-		ulpi_write(otg, 0x10, 0x86);
+		ulpi_write(phy, 0x10, 0x86);
 		break;
 	default:
 		break;
@@ -947,19 +947,19 @@
 
 static void msm_chg_enable_dcd(struct msm_otg *motg)
 {
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_phy *phy = &motg->phy;
 	u32 chg_det;
 
 	switch (motg->pdata->phy_type) {
 	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(otg, 0x34);
+		chg_det = ulpi_read(phy, 0x34);
 		/* Turn on D+ current source */
 		chg_det |= (1 << 5);
-		ulpi_write(otg, chg_det, 0x34);
+		ulpi_write(phy, chg_det, 0x34);
 		break;
 	case SNPS_28NM_INTEGRATED_PHY:
 		/* Data contact detection enable */
-		ulpi_write(otg, 0x10, 0x85);
+		ulpi_write(phy, 0x10, 0x85);
 		break;
 	default:
 		break;
@@ -968,32 +968,32 @@
 
 static void msm_chg_block_on(struct msm_otg *motg)
 {
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_phy *phy = &motg->phy;
 	u32 func_ctrl, chg_det;
 
 	/* put the controller in non-driving mode */
-	func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+	func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
 	func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
 	func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
-	ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+	ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);
 
 	switch (motg->pdata->phy_type) {
 	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(otg, 0x34);
+		chg_det = ulpi_read(phy, 0x34);
 		/* control chg block via ULPI */
 		chg_det &= ~(1 << 3);
-		ulpi_write(otg, chg_det, 0x34);
+		ulpi_write(phy, chg_det, 0x34);
 		/* Turn on chg detect block */
 		chg_det &= ~(1 << 1);
-		ulpi_write(otg, chg_det, 0x34);
+		ulpi_write(phy, chg_det, 0x34);
 		udelay(20);
 		break;
 	case SNPS_28NM_INTEGRATED_PHY:
 		/* Clear charger detecting control bits */
-		ulpi_write(otg, 0x3F, 0x86);
+		ulpi_write(phy, 0x3F, 0x86);
 		/* Clear alt interrupt latch and enable bits */
-		ulpi_write(otg, 0x1F, 0x92);
-		ulpi_write(otg, 0x1F, 0x95);
+		ulpi_write(phy, 0x1F, 0x92);
+		ulpi_write(phy, 0x1F, 0x95);
 		udelay(100);
 		break;
 	default:
@@ -1003,32 +1003,32 @@
 
 static void msm_chg_block_off(struct msm_otg *motg)
 {
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_phy *phy = &motg->phy;
 	u32 func_ctrl, chg_det;
 
 	switch (motg->pdata->phy_type) {
 	case CI_45NM_INTEGRATED_PHY:
-		chg_det = ulpi_read(otg, 0x34);
+		chg_det = ulpi_read(phy, 0x34);
 		/* Turn off charger block */
 		chg_det |= ~(1 << 1);
-		ulpi_write(otg, chg_det, 0x34);
+		ulpi_write(phy, chg_det, 0x34);
 		break;
 	case SNPS_28NM_INTEGRATED_PHY:
 		/* Clear charger detecting control bits */
-		ulpi_write(otg, 0x3F, 0x86);
+		ulpi_write(phy, 0x3F, 0x86);
 		/* Clear alt interrupt latch and enable bits */
-		ulpi_write(otg, 0x1F, 0x92);
-		ulpi_write(otg, 0x1F, 0x95);
+		ulpi_write(phy, 0x1F, 0x92);
+		ulpi_write(phy, 0x1F, 0x95);
 		break;
 	default:
 		break;
 	}
 
 	/* put the controller in normal mode */
-	func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+	func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
 	func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
 	func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
-	ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+	ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);
 }
 
 #define MSM_CHG_DCD_POLL_TIME		(100 * HZ/1000) /* 100 msec */
@@ -1038,14 +1038,14 @@
 static void msm_chg_detect_work(struct work_struct *w)
 {
 	struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_phy *phy = &motg->phy;
 	bool is_dcd, tmout, vout;
 	unsigned long delay;
 
-	dev_dbg(otg->dev, "chg detection work\n");
+	dev_dbg(phy->dev, "chg detection work\n");
 	switch (motg->chg_state) {
 	case USB_CHG_STATE_UNDEFINED:
-		pm_runtime_get_sync(otg->dev);
+		pm_runtime_get_sync(phy->dev);
 		msm_chg_block_on(motg);
 		msm_chg_enable_dcd(motg);
 		motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
@@ -1088,7 +1088,7 @@
 		motg->chg_state = USB_CHG_STATE_DETECTED;
 	case USB_CHG_STATE_DETECTED:
 		msm_chg_block_off(motg);
-		dev_dbg(otg->dev, "charger = %d\n", motg->chg_type);
+		dev_dbg(phy->dev, "charger = %d\n", motg->chg_type);
 		schedule_work(&motg->sm_work);
 		return;
 	default:
@@ -1152,22 +1152,22 @@
 static void msm_otg_sm_work(struct work_struct *w)
 {
 	struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_otg *otg = motg->phy.otg;
 
-	switch (otg->state) {
+	switch (otg->phy->state) {
 	case OTG_STATE_UNDEFINED:
-		dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
-		msm_otg_reset(otg);
+		dev_dbg(otg->phy->dev, "OTG_STATE_UNDEFINED state\n");
+		msm_otg_reset(otg->phy);
 		msm_otg_init_sm(motg);
-		otg->state = OTG_STATE_B_IDLE;
+		otg->phy->state = OTG_STATE_B_IDLE;
 		/* FALL THROUGH */
 	case OTG_STATE_B_IDLE:
-		dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
+		dev_dbg(otg->phy->dev, "OTG_STATE_B_IDLE state\n");
 		if (!test_bit(ID, &motg->inputs) && otg->host) {
 			/* disable BSV bit */
 			writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
-			msm_otg_start_host(otg, 1);
-			otg->state = OTG_STATE_A_HOST;
+			msm_otg_start_host(otg->phy, 1);
+			otg->phy->state = OTG_STATE_A_HOST;
 		} else if (test_bit(B_SESS_VLD, &motg->inputs)) {
 			switch (motg->chg_state) {
 			case USB_CHG_STATE_UNDEFINED:
@@ -1182,13 +1182,15 @@
 				case USB_CDP_CHARGER:
 					msm_otg_notify_charger(motg,
 							IDEV_CHG_MAX);
-					msm_otg_start_peripheral(otg, 1);
-					otg->state = OTG_STATE_B_PERIPHERAL;
+					msm_otg_start_peripheral(otg->phy, 1);
+					otg->phy->state
+						= OTG_STATE_B_PERIPHERAL;
 					break;
 				case USB_SDP_CHARGER:
 					msm_otg_notify_charger(motg, IUNIT);
-					msm_otg_start_peripheral(otg, 1);
-					otg->state = OTG_STATE_B_PERIPHERAL;
+					msm_otg_start_peripheral(otg->phy, 1);
+					otg->phy->state
+						= OTG_STATE_B_PERIPHERAL;
 					break;
 				default:
 					break;
@@ -1204,34 +1206,34 @@
 			 * is incremented in charger detection work.
 			 */
 			if (cancel_delayed_work_sync(&motg->chg_work)) {
-				pm_runtime_put_sync(otg->dev);
-				msm_otg_reset(otg);
+				pm_runtime_put_sync(otg->phy->dev);
+				msm_otg_reset(otg->phy);
 			}
 			msm_otg_notify_charger(motg, 0);
 			motg->chg_state = USB_CHG_STATE_UNDEFINED;
 			motg->chg_type = USB_INVALID_CHARGER;
 		}
-		pm_runtime_put_sync(otg->dev);
+		pm_runtime_put_sync(otg->phy->dev);
 		break;
 	case OTG_STATE_B_PERIPHERAL:
-		dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
+		dev_dbg(otg->phy->dev, "OTG_STATE_B_PERIPHERAL state\n");
 		if (!test_bit(B_SESS_VLD, &motg->inputs) ||
 				!test_bit(ID, &motg->inputs)) {
 			msm_otg_notify_charger(motg, 0);
-			msm_otg_start_peripheral(otg, 0);
+			msm_otg_start_peripheral(otg->phy, 0);
 			motg->chg_state = USB_CHG_STATE_UNDEFINED;
 			motg->chg_type = USB_INVALID_CHARGER;
-			otg->state = OTG_STATE_B_IDLE;
-			msm_otg_reset(otg);
+			otg->phy->state = OTG_STATE_B_IDLE;
+			msm_otg_reset(otg->phy);
 			schedule_work(w);
 		}
 		break;
 	case OTG_STATE_A_HOST:
-		dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
+		dev_dbg(otg->phy->dev, "OTG_STATE_A_HOST state\n");
 		if (test_bit(ID, &motg->inputs)) {
-			msm_otg_start_host(otg, 0);
-			otg->state = OTG_STATE_B_IDLE;
-			msm_otg_reset(otg);
+			msm_otg_start_host(otg->phy, 0);
+			otg->phy->state = OTG_STATE_B_IDLE;
+			msm_otg_reset(otg->phy);
 			schedule_work(w);
 		}
 		break;
@@ -1243,13 +1245,13 @@
 static irqreturn_t msm_otg_irq(int irq, void *data)
 {
 	struct msm_otg *motg = data;
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_phy *phy = &motg->phy;
 	u32 otgsc = 0;
 
 	if (atomic_read(&motg->in_lpm)) {
 		disable_irq_nosync(irq);
 		motg->async_int = 1;
-		pm_runtime_get(otg->dev);
+		pm_runtime_get(phy->dev);
 		return IRQ_HANDLED;
 	}
 
@@ -1262,15 +1264,15 @@
 			set_bit(ID, &motg->inputs);
 		else
 			clear_bit(ID, &motg->inputs);
-		dev_dbg(otg->dev, "ID set/clear\n");
-		pm_runtime_get_noresume(otg->dev);
+		dev_dbg(phy->dev, "ID set/clear\n");
+		pm_runtime_get_noresume(phy->dev);
 	} else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
 		if (otgsc & OTGSC_BSV)
 			set_bit(B_SESS_VLD, &motg->inputs);
 		else
 			clear_bit(B_SESS_VLD, &motg->inputs);
-		dev_dbg(otg->dev, "BSV set/clear\n");
-		pm_runtime_get_noresume(otg->dev);
+		dev_dbg(phy->dev, "BSV set/clear\n");
+		pm_runtime_get_noresume(phy->dev);
 	}
 
 	writel(otgsc, USB_OTGSC);
@@ -1281,9 +1283,9 @@
 static int msm_otg_mode_show(struct seq_file *s, void *unused)
 {
 	struct msm_otg *motg = s->private;
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_otg *otg = motg->phy.otg;
 
-	switch (otg->state) {
+	switch (otg->phy->state) {
 	case OTG_STATE_A_HOST:
 		seq_printf(s, "host\n");
 		break;
@@ -1309,7 +1311,7 @@
 	struct seq_file *s = file->private_data;
 	struct msm_otg *motg = s->private;
 	char buf[16];
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_otg *otg = motg->phy.otg;
 	int status = count;
 	enum usb_mode_type req_mode;
 
@@ -1333,7 +1335,7 @@
 
 	switch (req_mode) {
 	case USB_NONE:
-		switch (otg->state) {
+		switch (otg->phy->state) {
 		case OTG_STATE_A_HOST:
 		case OTG_STATE_B_PERIPHERAL:
 			set_bit(ID, &motg->inputs);
@@ -1344,7 +1346,7 @@
 		}
 		break;
 	case USB_PERIPHERAL:
-		switch (otg->state) {
+		switch (otg->phy->state) {
 		case OTG_STATE_B_IDLE:
 		case OTG_STATE_A_HOST:
 			set_bit(ID, &motg->inputs);
@@ -1355,7 +1357,7 @@
 		}
 		break;
 	case USB_HOST:
-		switch (otg->state) {
+		switch (otg->phy->state) {
 		case OTG_STATE_B_IDLE:
 		case OTG_STATE_B_PERIPHERAL:
 			clear_bit(ID, &motg->inputs);
@@ -1368,7 +1370,7 @@
 		goto out;
 	}
 
-	pm_runtime_get_sync(otg->dev);
+	pm_runtime_get_sync(otg->phy->dev);
 	schedule_work(&motg->sm_work);
 out:
 	return status;
@@ -1414,7 +1416,7 @@
 	int ret = 0;
 	struct resource *res;
 	struct msm_otg *motg;
-	struct otg_transceiver *otg;
+	struct usb_phy *phy;
 
 	dev_info(&pdev->dev, "msm_otg probe\n");
 	if (!pdev->dev.platform_data) {
@@ -1428,9 +1430,15 @@
 		return -ENOMEM;
 	}
 
+	motg->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
+	if (!motg->phy.otg) {
+		dev_err(&pdev->dev, "unable to allocate msm_otg\n");
+		return -ENOMEM;
+	}
+
 	motg->pdata = pdev->dev.platform_data;
-	otg = &motg->otg;
-	otg->dev = &pdev->dev;
+	phy = &motg->phy;
+	phy->dev = &pdev->dev;
 
 	motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
 	if (IS_ERR(motg->phy_reset_clk)) {
@@ -1538,16 +1546,18 @@
 		goto disable_clks;
 	}
 
-	otg->init = msm_otg_reset;
-	otg->set_host = msm_otg_set_host;
-	otg->set_peripheral = msm_otg_set_peripheral;
-	otg->set_power = msm_otg_set_power;
+	phy->init = msm_otg_reset;
+	phy->set_power = msm_otg_set_power;
 
-	otg->io_ops = &msm_otg_io_ops;
+	phy->io_ops = &msm_otg_io_ops;
 
-	ret = otg_set_transceiver(&motg->otg);
+	phy->otg->phy = &motg->phy;
+	phy->otg->set_host = msm_otg_set_host;
+	phy->otg->set_peripheral = msm_otg_set_peripheral;
+
+	ret = usb_set_transceiver(&motg->phy);
 	if (ret) {
-		dev_err(&pdev->dev, "otg_set_transceiver failed\n");
+		dev_err(&pdev->dev, "usb_set_transceiver failed\n");
 		goto free_irq;
 	}
 
@@ -1591,6 +1601,7 @@
 put_phy_reset_clk:
 	clk_put(motg->phy_reset_clk);
 free_motg:
+	kfree(motg->phy.otg);
 	kfree(motg);
 	return ret;
 }
@@ -1598,10 +1609,10 @@
 static int __devexit msm_otg_remove(struct platform_device *pdev)
 {
 	struct msm_otg *motg = platform_get_drvdata(pdev);
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_phy *phy = &motg->phy;
 	int cnt = 0;
 
-	if (otg->host || otg->gadget)
+	if (phy->otg->host || phy->otg->gadget)
 		return -EBUSY;
 
 	msm_otg_debugfs_cleanup();
@@ -1613,14 +1624,14 @@
 	device_init_wakeup(&pdev->dev, 0);
 	pm_runtime_disable(&pdev->dev);
 
-	otg_set_transceiver(NULL);
+	usb_set_transceiver(NULL);
 	free_irq(motg->irq, motg);
 
 	/*
 	 * Put PHY in low power mode.
 	 */
-	ulpi_read(otg, 0x14);
-	ulpi_write(otg, 0x08, 0x09);
+	ulpi_read(phy, 0x14);
+	ulpi_write(phy, 0x08, 0x09);
 
 	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
 	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
@@ -1630,7 +1641,7 @@
 		cnt++;
 	}
 	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
-		dev_err(otg->dev, "Unable to suspend PHY\n");
+		dev_err(phy->dev, "Unable to suspend PHY\n");
 
 	clk_disable(motg->pclk);
 	clk_disable(motg->clk);
@@ -1651,6 +1662,7 @@
 	if (motg->core_clk)
 		clk_put(motg->core_clk);
 
+	kfree(motg->phy.otg);
 	kfree(motg);
 
 	return 0;
@@ -1660,7 +1672,7 @@
 static int msm_otg_runtime_idle(struct device *dev)
 {
 	struct msm_otg *motg = dev_get_drvdata(dev);
-	struct otg_transceiver *otg = &motg->otg;
+	struct usb_otg *otg = motg->phy.otg;
 
 	dev_dbg(dev, "OTG runtime idle\n");
 
@@ -1670,7 +1682,7 @@
 	 * This 1 sec delay also prevents entering into LPM immediately
 	 * after asynchronous interrupt.
 	 */
-	if (otg->state != OTG_STATE_UNDEFINED)
+	if (otg->phy->state != OTG_STATE_UNDEFINED)
 		pm_schedule_suspend(dev, 1000);
 
 	return -EAGAIN;
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c
index b5fbe14..6cc6c3f 100644
--- a/drivers/usb/otg/mv_otg.c
+++ b/drivers/usb/otg/mv_otg.c
@@ -55,16 +55,16 @@
 	"a_vbus_err"
 };
 
-static int mv_otg_set_vbus(struct otg_transceiver *otg, bool on)
+static int mv_otg_set_vbus(struct usb_otg *otg, bool on)
 {
-	struct mv_otg *mvotg = container_of(otg, struct mv_otg, otg);
+	struct mv_otg *mvotg = container_of(otg->phy, struct mv_otg, phy);
 	if (mvotg->pdata->set_vbus == NULL)
 		return -ENODEV;
 
 	return mvotg->pdata->set_vbus(on);
 }
 
-static int mv_otg_set_host(struct otg_transceiver *otg,
+static int mv_otg_set_host(struct usb_otg *otg,
 			   struct usb_bus *host)
 {
 	otg->host = host;
@@ -72,7 +72,7 @@
 	return 0;
 }
 
-static int mv_otg_set_peripheral(struct otg_transceiver *otg,
+static int mv_otg_set_peripheral(struct usb_otg *otg,
 				 struct usb_gadget *gadget)
 {
 	otg->gadget = gadget;
@@ -203,7 +203,7 @@
 static void mv_otg_start_host(struct mv_otg *mvotg, int on)
 {
 #ifdef CONFIG_USB
-	struct otg_transceiver *otg = &mvotg->otg;
+	struct usb_otg *otg = mvotg->phy.otg;
 	struct usb_hcd *hcd;
 
 	if (!otg->host)
@@ -222,12 +222,12 @@
 
 static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on)
 {
-	struct otg_transceiver *otg = &mvotg->otg;
+	struct usb_otg *otg = mvotg->phy.otg;
 
 	if (!otg->gadget)
 		return;
 
-	dev_info(otg->dev, "gadget %s\n", on ? "on" : "off");
+	dev_info(mvotg->phy.dev, "gadget %s\n", on ? "on" : "off");
 
 	if (on)
 		usb_gadget_vbus_connect(otg->gadget);
@@ -343,69 +343,69 @@
 static void mv_otg_update_state(struct mv_otg *mvotg)
 {
 	struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl;
-	struct otg_transceiver *otg = &mvotg->otg;
-	int old_state = otg->state;
+	struct usb_phy *phy = &mvotg->phy;
+	int old_state = phy->state;
 
 	switch (old_state) {
 	case OTG_STATE_UNDEFINED:
-		otg->state = OTG_STATE_B_IDLE;
+		phy->state = OTG_STATE_B_IDLE;
 		/* FALL THROUGH */
 	case OTG_STATE_B_IDLE:
 		if (otg_ctrl->id == 0)
-			otg->state = OTG_STATE_A_IDLE;
+			phy->state = OTG_STATE_A_IDLE;
 		else if (otg_ctrl->b_sess_vld)
-			otg->state = OTG_STATE_B_PERIPHERAL;
+			phy->state = OTG_STATE_B_PERIPHERAL;
 		break;
 	case OTG_STATE_B_PERIPHERAL:
 		if (!otg_ctrl->b_sess_vld || otg_ctrl->id == 0)
-			otg->state = OTG_STATE_B_IDLE;
+			phy->state = OTG_STATE_B_IDLE;
 		break;
 	case OTG_STATE_A_IDLE:
 		if (otg_ctrl->id)
-			otg->state = OTG_STATE_B_IDLE;
+			phy->state = OTG_STATE_B_IDLE;
 		else if (!(otg_ctrl->a_bus_drop) &&
 			 (otg_ctrl->a_bus_req || otg_ctrl->a_srp_det))
-			otg->state = OTG_STATE_A_WAIT_VRISE;
+			phy->state = OTG_STATE_A_WAIT_VRISE;
 		break;
 	case OTG_STATE_A_WAIT_VRISE:
 		if (otg_ctrl->a_vbus_vld)
-			otg->state = OTG_STATE_A_WAIT_BCON;
+			phy->state = OTG_STATE_A_WAIT_BCON;
 		break;
 	case OTG_STATE_A_WAIT_BCON:
 		if (otg_ctrl->id || otg_ctrl->a_bus_drop
 		    || otg_ctrl->a_wait_bcon_timeout) {
 			mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
 			mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
-			otg->state = OTG_STATE_A_WAIT_VFALL;
+			phy->state = OTG_STATE_A_WAIT_VFALL;
 			otg_ctrl->a_bus_req = 0;
 		} else if (!otg_ctrl->a_vbus_vld) {
 			mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
 			mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
-			otg->state = OTG_STATE_A_VBUS_ERR;
+			phy->state = OTG_STATE_A_VBUS_ERR;
 		} else if (otg_ctrl->b_conn) {
 			mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
 			mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
-			otg->state = OTG_STATE_A_HOST;
+			phy->state = OTG_STATE_A_HOST;
 		}
 		break;
 	case OTG_STATE_A_HOST:
 		if (otg_ctrl->id || !otg_ctrl->b_conn
 		    || otg_ctrl->a_bus_drop)
-			otg->state = OTG_STATE_A_WAIT_BCON;
+			phy->state = OTG_STATE_A_WAIT_BCON;
 		else if (!otg_ctrl->a_vbus_vld)
-			otg->state = OTG_STATE_A_VBUS_ERR;
+			phy->state = OTG_STATE_A_VBUS_ERR;
 		break;
 	case OTG_STATE_A_WAIT_VFALL:
 		if (otg_ctrl->id
 		    || (!otg_ctrl->b_conn && otg_ctrl->a_sess_vld)
 		    || otg_ctrl->a_bus_req)
-			otg->state = OTG_STATE_A_IDLE;
+			phy->state = OTG_STATE_A_IDLE;
 		break;
 	case OTG_STATE_A_VBUS_ERR:
 		if (otg_ctrl->id || otg_ctrl->a_clr_err
 		    || otg_ctrl->a_bus_drop) {
 			otg_ctrl->a_clr_err = 0;
-			otg->state = OTG_STATE_A_WAIT_VFALL;
+			phy->state = OTG_STATE_A_WAIT_VFALL;
 		}
 		break;
 	default:
@@ -416,15 +416,17 @@
 static void mv_otg_work(struct work_struct *work)
 {
 	struct mv_otg *mvotg;
-	struct otg_transceiver *otg;
+	struct usb_phy *phy;
+	struct usb_otg *otg;
 	int old_state;
 
 	mvotg = container_of((struct delayed_work *)work, struct mv_otg, work);
 
 run:
 	/* work queue is single thread, or we need spin_lock to protect */
-	otg = &mvotg->otg;
-	old_state = otg->state;
+	phy = &mvotg->phy;
+	otg = phy->otg;
+	old_state = phy->state;
 
 	if (!mvotg->active)
 		return;
@@ -432,14 +434,14 @@
 	mv_otg_update_inputs(mvotg);
 	mv_otg_update_state(mvotg);
 
-	if (old_state != otg->state) {
+	if (old_state != phy->state) {
 		dev_info(&mvotg->pdev->dev, "change from state %s to %s\n",
 			 state_string[old_state],
-			 state_string[otg->state]);
+			 state_string[phy->state]);
 
-		switch (otg->state) {
+		switch (phy->state) {
 		case OTG_STATE_B_IDLE:
-			mvotg->otg.default_a = 0;
+			otg->default_a = 0;
 			if (old_state == OTG_STATE_B_PERIPHERAL)
 				mv_otg_start_periphrals(mvotg, 0);
 			mv_otg_reset(mvotg);
@@ -450,14 +452,14 @@
 			mv_otg_start_periphrals(mvotg, 1);
 			break;
 		case OTG_STATE_A_IDLE:
-			mvotg->otg.default_a = 1;
+			otg->default_a = 1;
 			mv_otg_enable(mvotg);
 			if (old_state == OTG_STATE_A_WAIT_VFALL)
 				mv_otg_start_host(mvotg, 0);
 			mv_otg_reset(mvotg);
 			break;
 		case OTG_STATE_A_WAIT_VRISE:
-			mv_otg_set_vbus(&mvotg->otg, 1);
+			mv_otg_set_vbus(otg, 1);
 			break;
 		case OTG_STATE_A_WAIT_BCON:
 			if (old_state != OTG_STATE_A_HOST)
@@ -479,7 +481,7 @@
 			 * here. In fact, it need host driver to notify us.
 			 */
 			mvotg->otg_ctrl.b_conn = 0;
-			mv_otg_set_vbus(&mvotg->otg, 0);
+			mv_otg_set_vbus(otg, 0);
 			break;
 		case OTG_STATE_A_VBUS_ERR:
 			break;
@@ -548,8 +550,8 @@
 		return -1;
 
 	/* We will use this interface to change to A device */
-	if (mvotg->otg.state != OTG_STATE_B_IDLE
-	    && mvotg->otg.state != OTG_STATE_A_IDLE)
+	if (mvotg->phy.state != OTG_STATE_B_IDLE
+	    && mvotg->phy.state != OTG_STATE_A_IDLE)
 		return -1;
 
 	/* The clock may disabled and we need to set irq for ID detected */
@@ -579,7 +581,7 @@
 	      const char *buf, size_t count)
 {
 	struct mv_otg *mvotg = dev_get_drvdata(dev);
-	if (!mvotg->otg.default_a)
+	if (!mvotg->phy.otg->default_a)
 		return -1;
 
 	if (count > 2)
@@ -615,7 +617,7 @@
 	       const char *buf, size_t count)
 {
 	struct mv_otg *mvotg = dev_get_drvdata(dev);
-	if (!mvotg->otg.default_a)
+	if (!mvotg->phy.otg->default_a)
 		return -1;
 
 	if (count > 2)
@@ -688,9 +690,10 @@
 	for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++)
 		clk_put(mvotg->clk[clk_i]);
 
-	otg_set_transceiver(NULL);
+	usb_set_transceiver(NULL);
 	platform_set_drvdata(pdev, NULL);
 
+	kfree(mvotg->phy.otg);
 	kfree(mvotg);
 
 	return 0;
@@ -700,6 +703,7 @@
 {
 	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
 	struct mv_otg *mvotg;
+	struct usb_otg *otg;
 	struct resource *r;
 	int retval = 0, clk_i, i;
 	size_t size;
@@ -716,6 +720,12 @@
 		return -ENOMEM;
 	}
 
+	otg = kzalloc(sizeof *otg, GFP_KERNEL);
+	if (!otg) {
+		kfree(mvotg);
+		return -ENOMEM;
+	}
+
 	platform_set_drvdata(pdev, mvotg);
 
 	mvotg->pdev = pdev;
@@ -741,12 +751,15 @@
 
 	/* OTG common part */
 	mvotg->pdev = pdev;
-	mvotg->otg.dev = &pdev->dev;
-	mvotg->otg.label = driver_name;
-	mvotg->otg.set_host = mv_otg_set_host;
-	mvotg->otg.set_peripheral = mv_otg_set_peripheral;
-	mvotg->otg.set_vbus = mv_otg_set_vbus;
-	mvotg->otg.state = OTG_STATE_UNDEFINED;
+	mvotg->phy.dev = &pdev->dev;
+	mvotg->phy.otg = otg;
+	mvotg->phy.label = driver_name;
+	mvotg->phy.state = OTG_STATE_UNDEFINED;
+
+	otg->phy = &mvotg->phy;
+	otg->set_host = mv_otg_set_host;
+	otg->set_peripheral = mv_otg_set_peripheral;
+	otg->set_vbus = mv_otg_set_vbus;
 
 	for (i = 0; i < OTG_TIMER_NUM; i++)
 		init_timer(&mvotg->otg_ctrl.timer[i]);
@@ -840,7 +853,7 @@
 		goto err_disable_clk;
 	}
 
-	retval = otg_set_transceiver(&mvotg->otg);
+	retval = usb_set_transceiver(&mvotg->phy);
 	if (retval < 0) {
 		dev_err(&pdev->dev, "can't register transceiver, %d\n",
 			retval);
@@ -867,7 +880,7 @@
 	return 0;
 
 err_set_transceiver:
-	otg_set_transceiver(NULL);
+	usb_set_transceiver(NULL);
 err_free_irq:
 	free_irq(mvotg->irq, mvotg);
 err_disable_clk:
@@ -888,6 +901,7 @@
 		clk_put(mvotg->clk[clk_i]);
 
 	platform_set_drvdata(pdev, NULL);
+	kfree(otg);
 	kfree(mvotg);
 
 	return retval;
@@ -898,10 +912,10 @@
 {
 	struct mv_otg *mvotg = platform_get_drvdata(pdev);
 
-	if (mvotg->otg.state != OTG_STATE_B_IDLE) {
+	if (mvotg->phy.state != OTG_STATE_B_IDLE) {
 		dev_info(&pdev->dev,
 			 "OTG state is not B_IDLE, it is %d!\n",
-			 mvotg->otg.state);
+			 mvotg->phy.state);
 		return -EAGAIN;
 	}
 
diff --git a/drivers/usb/otg/mv_otg.h b/drivers/usb/otg/mv_otg.h
index be6ca14..8a9e351 100644
--- a/drivers/usb/otg/mv_otg.h
+++ b/drivers/usb/otg/mv_otg.h
@@ -136,7 +136,7 @@
 };
 
 struct mv_otg {
-	struct otg_transceiver otg;
+	struct usb_phy phy;
 	struct mv_otg_ctrl otg_ctrl;
 
 	/* base address */
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
index c1e3600..58b26df 100644
--- a/drivers/usb/otg/nop-usb-xceiv.c
+++ b/drivers/usb/otg/nop-usb-xceiv.c
@@ -33,7 +33,7 @@
 #include <linux/slab.h>
 
 struct nop_usb_xceiv {
-	struct otg_transceiver	otg;
+	struct usb_phy		phy;
 	struct device		*dev;
 };
 
@@ -58,51 +58,37 @@
 }
 EXPORT_SYMBOL(usb_nop_xceiv_unregister);
 
-static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x)
-{
-	return container_of(x, struct nop_usb_xceiv, otg);
-}
-
-static int nop_set_suspend(struct otg_transceiver *x, int suspend)
+static int nop_set_suspend(struct usb_phy *x, int suspend)
 {
 	return 0;
 }
 
-static int nop_set_peripheral(struct otg_transceiver *x,
-		struct usb_gadget *gadget)
+static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
 {
-	struct nop_usb_xceiv *nop;
-
-	if (!x)
+	if (!otg)
 		return -ENODEV;
 
-	nop = xceiv_to_nop(x);
-
 	if (!gadget) {
-		nop->otg.gadget = NULL;
+		otg->gadget = NULL;
 		return -ENODEV;
 	}
 
-	nop->otg.gadget = gadget;
-	nop->otg.state = OTG_STATE_B_IDLE;
+	otg->gadget = gadget;
+	otg->phy->state = OTG_STATE_B_IDLE;
 	return 0;
 }
 
-static int nop_set_host(struct otg_transceiver *x, struct usb_bus *host)
+static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
 {
-	struct nop_usb_xceiv *nop;
-
-	if (!x)
+	if (!otg)
 		return -ENODEV;
 
-	nop = xceiv_to_nop(x);
-
 	if (!host) {
-		nop->otg.host = NULL;
+		otg->host = NULL;
 		return -ENODEV;
 	}
 
-	nop->otg.host = host;
+	otg->host = host;
 	return 0;
 }
 
@@ -115,15 +101,23 @@
 	if (!nop)
 		return -ENOMEM;
 
-	nop->dev		= &pdev->dev;
-	nop->otg.dev		= nop->dev;
-	nop->otg.label		= "nop-xceiv";
-	nop->otg.state		= OTG_STATE_UNDEFINED;
-	nop->otg.set_host	= nop_set_host;
-	nop->otg.set_peripheral	= nop_set_peripheral;
-	nop->otg.set_suspend	= nop_set_suspend;
+	nop->phy.otg = kzalloc(sizeof *nop->phy.otg, GFP_KERNEL);
+	if (!nop->phy.otg) {
+		kfree(nop);
+		return -ENOMEM;
+	}
 
-	err = otg_set_transceiver(&nop->otg);
+	nop->dev		= &pdev->dev;
+	nop->phy.dev		= nop->dev;
+	nop->phy.label		= "nop-xceiv";
+	nop->phy.set_suspend	= nop_set_suspend;
+	nop->phy.state		= OTG_STATE_UNDEFINED;
+
+	nop->phy.otg->phy		= &nop->phy;
+	nop->phy.otg->set_host		= nop_set_host;
+	nop->phy.otg->set_peripheral	= nop_set_peripheral;
+
+	err = usb_set_transceiver(&nop->phy);
 	if (err) {
 		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
 			err);
@@ -132,10 +126,11 @@
 
 	platform_set_drvdata(pdev, nop);
 
-	ATOMIC_INIT_NOTIFIER_HEAD(&nop->otg.notifier);
+	ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
 
 	return 0;
 exit:
+	kfree(nop->phy.otg);
 	kfree(nop);
 	return err;
 }
@@ -144,9 +139,10 @@
 {
 	struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
 
-	otg_set_transceiver(NULL);
+	usb_set_transceiver(NULL);
 
 	platform_set_drvdata(pdev, NULL);
+	kfree(nop->phy.otg);
 	kfree(nop);
 
 	return 0;
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
index 307c27b..801e597 100644
--- a/drivers/usb/otg/otg.c
+++ b/drivers/usb/otg/otg.c
@@ -15,56 +15,56 @@
 
 #include <linux/usb/otg.h>
 
-static struct otg_transceiver *xceiv;
+static struct usb_phy *phy;
 
 /**
- * otg_get_transceiver - find the (single) OTG transceiver
+ * usb_get_transceiver - find the (single) USB transceiver
  *
  * Returns the transceiver driver, after getting a refcount to it; or
  * null if there is no such transceiver.  The caller is responsible for
- * calling otg_put_transceiver() to release that count.
+ * calling usb_put_transceiver() to release that count.
  *
  * For use by USB host and peripheral drivers.
  */
-struct otg_transceiver *otg_get_transceiver(void)
+struct usb_phy *usb_get_transceiver(void)
 {
-	if (xceiv)
-		get_device(xceiv->dev);
-	return xceiv;
+	if (phy)
+		get_device(phy->dev);
+	return phy;
 }
-EXPORT_SYMBOL(otg_get_transceiver);
+EXPORT_SYMBOL(usb_get_transceiver);
 
 /**
- * otg_put_transceiver - release the (single) OTG transceiver
- * @x: the transceiver returned by otg_get_transceiver()
+ * usb_put_transceiver - release the (single) USB transceiver
+ * @x: the transceiver returned by usb_get_transceiver()
  *
- * Releases a refcount the caller received from otg_get_transceiver().
+ * Releases a refcount the caller received from usb_get_transceiver().
  *
  * For use by USB host and peripheral drivers.
  */
-void otg_put_transceiver(struct otg_transceiver *x)
+void usb_put_transceiver(struct usb_phy *x)
 {
 	if (x)
 		put_device(x->dev);
 }
-EXPORT_SYMBOL(otg_put_transceiver);
+EXPORT_SYMBOL(usb_put_transceiver);
 
 /**
- * otg_set_transceiver - declare the (single) OTG transceiver
- * @x: the USB OTG transceiver to be used; or NULL
+ * usb_set_transceiver - declare the (single) USB transceiver
+ * @x: the USB transceiver to be used; or NULL
  *
  * This call is exclusively for use by transceiver drivers, which
  * coordinate the activities of drivers for host and peripheral
  * controllers, and in some cases for VBUS current regulation.
  */
-int otg_set_transceiver(struct otg_transceiver *x)
+int usb_set_transceiver(struct usb_phy *x)
 {
-	if (xceiv && x)
+	if (phy && x)
 		return -EBUSY;
-	xceiv = x;
+	phy = x;
 	return 0;
 }
-EXPORT_SYMBOL(otg_set_transceiver);
+EXPORT_SYMBOL(usb_set_transceiver);
 
 const char *otg_state_string(enum usb_otg_state state)
 {
diff --git a/drivers/usb/otg/otg_fsm.c b/drivers/usb/otg/otg_fsm.c
index 0911738..ade131a 100644
--- a/drivers/usb/otg/otg_fsm.c
+++ b/drivers/usb/otg/otg_fsm.c
@@ -117,10 +117,10 @@
 int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
 {
 	state_changed = 1;
-	if (fsm->transceiver->state == new_state)
+	if (fsm->otg->phy->state == new_state)
 		return 0;
 	VDBG("Set state: %s\n", otg_state_string(new_state));
-	otg_leave_state(fsm, fsm->transceiver->state);
+	otg_leave_state(fsm, fsm->otg->phy->state);
 	switch (new_state) {
 	case OTG_STATE_B_IDLE:
 		otg_drv_vbus(fsm, 0);
@@ -155,8 +155,8 @@
 		otg_loc_conn(fsm, 0);
 		otg_loc_sof(fsm, 1);
 		otg_set_protocol(fsm, PROTO_HOST);
-		usb_bus_start_enum(fsm->transceiver->host,
-				fsm->transceiver->host->otg_port);
+		usb_bus_start_enum(fsm->otg->host,
+				fsm->otg->host->otg_port);
 		break;
 	case OTG_STATE_A_IDLE:
 		otg_drv_vbus(fsm, 0);
@@ -221,7 +221,7 @@
 		break;
 	}
 
-	fsm->transceiver->state = new_state;
+	fsm->otg->phy->state = new_state;
 	return 0;
 }
 
@@ -233,7 +233,7 @@
 
 	spin_lock_irqsave(&fsm->lock, flags);
 
-	state = fsm->transceiver->state;
+	state = fsm->otg->phy->state;
 	state_changed = 0;
 	/* State machine state change judgement */
 
@@ -248,7 +248,7 @@
 	case OTG_STATE_B_IDLE:
 		if (!fsm->id)
 			otg_set_state(fsm, OTG_STATE_A_IDLE);
-		else if (fsm->b_sess_vld && fsm->transceiver->gadget)
+		else if (fsm->b_sess_vld && fsm->otg->gadget)
 			otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
 		else if (fsm->b_bus_req && fsm->b_sess_end && fsm->b_se0_srp)
 			otg_set_state(fsm, OTG_STATE_B_SRP_INIT);
@@ -260,7 +260,7 @@
 	case OTG_STATE_B_PERIPHERAL:
 		if (!fsm->id || !fsm->b_sess_vld)
 			otg_set_state(fsm, OTG_STATE_B_IDLE);
-		else if (fsm->b_bus_req && fsm->transceiver->
+		else if (fsm->b_bus_req && fsm->otg->
 				gadget->b_hnp_enable && fsm->a_bus_suspend)
 			otg_set_state(fsm, OTG_STATE_B_WAIT_ACON);
 		break;
@@ -302,7 +302,7 @@
 		break;
 	case OTG_STATE_A_HOST:
 		if ((!fsm->a_bus_req || fsm->a_suspend_req) &&
-				fsm->transceiver->host->b_hnp_enable)
+				fsm->otg->host->b_hnp_enable)
 			otg_set_state(fsm, OTG_STATE_A_SUSPEND);
 		else if (fsm->id || !fsm->b_conn || fsm->a_bus_drop)
 			otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
@@ -310,9 +310,9 @@
 			otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
 		break;
 	case OTG_STATE_A_SUSPEND:
-		if (!fsm->b_conn && fsm->transceiver->host->b_hnp_enable)
+		if (!fsm->b_conn && fsm->otg->host->b_hnp_enable)
 			otg_set_state(fsm, OTG_STATE_A_PERIPHERAL);
-		else if (!fsm->b_conn && !fsm->transceiver->host->b_hnp_enable)
+		else if (!fsm->b_conn && !fsm->otg->host->b_hnp_enable)
 			otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
 		else if (fsm->a_bus_req || fsm->b_bus_resume)
 			otg_set_state(fsm, OTG_STATE_A_HOST);
diff --git a/drivers/usb/otg/otg_fsm.h b/drivers/usb/otg/otg_fsm.h
index 0cecf1d..c30a2e1 100644
--- a/drivers/usb/otg/otg_fsm.h
+++ b/drivers/usb/otg/otg_fsm.h
@@ -82,7 +82,7 @@
 	int loc_sof;
 
 	struct otg_fsm_ops *ops;
-	struct otg_transceiver *transceiver;
+	struct usb_otg *otg;
 
 	/* Current usb protocol used: 0:undefine; 1:host; 2:client */
 	int protocol;
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index 14f66c3..c4a86da 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -144,7 +144,7 @@
 #define GPIO_USB_4PIN_ULPI_2430C	(3 << 0)
 
 struct twl4030_usb {
-	struct otg_transceiver	otg;
+	struct usb_phy		phy;
 	struct device		*dev;
 
 	/* TWL4030 internal USB regulator supplies */
@@ -166,7 +166,7 @@
 };
 
 /* internal define on top of container_of */
-#define xceiv_to_twl(x)		container_of((x), struct twl4030_usb, otg)
+#define phy_to_twl(x)		container_of((x), struct twl4030_usb, phy)
 
 /*-------------------------------------------------------------------------*/
 
@@ -246,10 +246,11 @@
 
 /*-------------------------------------------------------------------------*/
 
-static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl)
+static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
 {
 	int	status;
 	int	linkstat = USB_EVENT_NONE;
+	struct usb_otg *otg = twl->phy.otg;
 
 	twl->vbus_supplied = false;
 
@@ -281,7 +282,7 @@
 	dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
 			status, status, linkstat);
 
-	twl->otg.last_event = linkstat;
+	twl->phy.last_event = linkstat;
 
 	/* REVISIT this assumes host and peripheral controllers
 	 * are registered, and that both are active...
@@ -290,11 +291,11 @@
 	spin_lock_irq(&twl->lock);
 	twl->linkstat = linkstat;
 	if (linkstat == USB_EVENT_ID) {
-		twl->otg.default_a = true;
-		twl->otg.state = OTG_STATE_A_IDLE;
+		otg->default_a = true;
+		twl->phy.state = OTG_STATE_A_IDLE;
 	} else {
-		twl->otg.default_a = false;
-		twl->otg.state = OTG_STATE_B_IDLE;
+		otg->default_a = false;
+		twl->phy.state = OTG_STATE_B_IDLE;
 	}
 	spin_unlock_irq(&twl->lock);
 
@@ -520,8 +521,8 @@
 		else
 			twl4030_phy_resume(twl);
 
-		atomic_notifier_call_chain(&twl->otg.notifier, status,
-				twl->otg.gadget);
+		atomic_notifier_call_chain(&twl->phy.notifier, status,
+				twl->phy.otg->gadget);
 	}
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 
@@ -542,15 +543,15 @@
 			twl->asleep = 0;
 		}
 
-		atomic_notifier_call_chain(&twl->otg.notifier, status,
-				twl->otg.gadget);
+		atomic_notifier_call_chain(&twl->phy.notifier, status,
+				twl->phy.otg->gadget);
 	}
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 }
 
-static int twl4030_set_suspend(struct otg_transceiver *x, int suspend)
+static int twl4030_set_suspend(struct usb_phy *x, int suspend)
 {
-	struct twl4030_usb *twl = xceiv_to_twl(x);
+	struct twl4030_usb *twl = phy_to_twl(x);
 
 	if (suspend)
 		twl4030_phy_suspend(twl, 1);
@@ -560,33 +561,27 @@
 	return 0;
 }
 
-static int twl4030_set_peripheral(struct otg_transceiver *x,
-		struct usb_gadget *gadget)
+static int twl4030_set_peripheral(struct usb_otg *otg,
+					struct usb_gadget *gadget)
 {
-	struct twl4030_usb *twl;
-
-	if (!x)
+	if (!otg)
 		return -ENODEV;
 
-	twl = xceiv_to_twl(x);
-	twl->otg.gadget = gadget;
+	otg->gadget = gadget;
 	if (!gadget)
-		twl->otg.state = OTG_STATE_UNDEFINED;
+		otg->phy->state = OTG_STATE_UNDEFINED;
 
 	return 0;
 }
 
-static int twl4030_set_host(struct otg_transceiver *x, struct usb_bus *host)
+static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host)
 {
-	struct twl4030_usb *twl;
-
-	if (!x)
+	if (!otg)
 		return -ENODEV;
 
-	twl = xceiv_to_twl(x);
-	twl->otg.host = host;
+	otg->host = host;
 	if (!host)
-		twl->otg.state = OTG_STATE_UNDEFINED;
+		otg->phy->state = OTG_STATE_UNDEFINED;
 
 	return 0;
 }
@@ -596,6 +591,7 @@
 	struct twl4030_usb_data *pdata = pdev->dev.platform_data;
 	struct twl4030_usb	*twl;
 	int			status, err;
+	struct usb_otg		*otg;
 
 	if (!pdata) {
 		dev_dbg(&pdev->dev, "platform_data not available\n");
@@ -606,16 +602,26 @@
 	if (!twl)
 		return -ENOMEM;
 
+	otg = kzalloc(sizeof *otg, GFP_KERNEL);
+	if (!otg) {
+		kfree(twl);
+		return -ENOMEM;
+	}
+
 	twl->dev		= &pdev->dev;
 	twl->irq		= platform_get_irq(pdev, 0);
-	twl->otg.dev		= twl->dev;
-	twl->otg.label		= "twl4030";
-	twl->otg.set_host	= twl4030_set_host;
-	twl->otg.set_peripheral	= twl4030_set_peripheral;
-	twl->otg.set_suspend	= twl4030_set_suspend;
 	twl->usb_mode		= pdata->usb_mode;
 	twl->vbus_supplied	= false;
-	twl->asleep = 1;
+	twl->asleep		= 1;
+
+	twl->phy.dev		= twl->dev;
+	twl->phy.label		= "twl4030";
+	twl->phy.otg		= otg;
+	twl->phy.set_suspend	= twl4030_set_suspend;
+
+	otg->phy		= &twl->phy;
+	otg->set_host		= twl4030_set_host;
+	otg->set_peripheral	= twl4030_set_peripheral;
 
 	/* init spinlock for workqueue */
 	spin_lock_init(&twl->lock);
@@ -623,16 +629,17 @@
 	err = twl4030_usb_ldo_init(twl);
 	if (err) {
 		dev_err(&pdev->dev, "ldo init failed\n");
+		kfree(otg);
 		kfree(twl);
 		return err;
 	}
-	otg_set_transceiver(&twl->otg);
+	usb_set_transceiver(&twl->phy);
 
 	platform_set_drvdata(pdev, twl);
 	if (device_create_file(&pdev->dev, &dev_attr_vbus))
 		dev_warn(&pdev->dev, "could not create sysfs file\n");
 
-	ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
+	ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
 
 	/* Our job is to use irqs and status from the power module
 	 * to keep the transceiver disabled when nothing's connected.
@@ -649,6 +656,7 @@
 	if (status < 0) {
 		dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
 			twl->irq, status);
+		kfree(otg);
 		kfree(twl);
 		return status;
 	}
@@ -693,6 +701,7 @@
 	regulator_put(twl->usb1v8);
 	regulator_put(twl->usb3v1);
 
+	kfree(twl->phy.otg);
 	kfree(twl);
 
 	return 0;
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index ed2b26c..e3fa387 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -87,7 +87,7 @@
 #define	VBUS_DET			BIT(2)
 
 struct twl6030_usb {
-	struct otg_transceiver	otg;
+	struct usb_phy		phy;
 	struct device		*dev;
 
 	/* for vbus reporting with irqs disabled */
@@ -107,7 +107,7 @@
 	unsigned long		features;
 };
 
-#define xceiv_to_twl(x)		container_of((x), struct twl6030_usb, otg)
+#define phy_to_twl(x)		container_of((x), struct twl6030_usb, phy)
 
 /*-------------------------------------------------------------------------*/
 
@@ -137,13 +137,13 @@
 	return ret;
 }
 
-static int twl6030_phy_init(struct otg_transceiver *x)
+static int twl6030_phy_init(struct usb_phy *x)
 {
 	struct twl6030_usb *twl;
 	struct device *dev;
 	struct twl4030_usb_data *pdata;
 
-	twl = xceiv_to_twl(x);
+	twl = phy_to_twl(x);
 	dev  = twl->dev;
 	pdata = dev->platform_data;
 
@@ -155,21 +155,21 @@
 	return 0;
 }
 
-static void twl6030_phy_shutdown(struct otg_transceiver *x)
+static void twl6030_phy_shutdown(struct usb_phy *x)
 {
 	struct twl6030_usb *twl;
 	struct device *dev;
 	struct twl4030_usb_data *pdata;
 
-	twl = xceiv_to_twl(x);
+	twl = phy_to_twl(x);
 	dev  = twl->dev;
 	pdata = dev->platform_data;
 	pdata->phy_power(twl->dev, 0, 0);
 }
 
-static int twl6030_phy_suspend(struct otg_transceiver *x, int suspend)
+static int twl6030_phy_suspend(struct usb_phy *x, int suspend)
 {
-	struct twl6030_usb *twl = xceiv_to_twl(x);
+	struct twl6030_usb *twl = phy_to_twl(x);
 	struct device *dev = twl->dev;
 	struct twl4030_usb_data *pdata = dev->platform_data;
 
@@ -178,9 +178,9 @@
 	return 0;
 }
 
-static int twl6030_start_srp(struct otg_transceiver *x)
+static int twl6030_start_srp(struct usb_otg *otg)
 {
-	struct twl6030_usb *twl = xceiv_to_twl(x);
+	struct twl6030_usb *twl = phy_to_twl(otg->phy);
 
 	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
 	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);
@@ -256,6 +256,7 @@
 static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
 {
 	struct twl6030_usb *twl = _twl;
+	struct usb_otg *otg = twl->phy.otg;
 	int status;
 	u8 vbus_state, hw_state;
 
@@ -268,18 +269,18 @@
 			regulator_enable(twl->usb3v3);
 			twl->asleep = 1;
 			status = USB_EVENT_VBUS;
-			twl->otg.default_a = false;
-			twl->otg.state = OTG_STATE_B_IDLE;
+			otg->default_a = false;
+			twl->phy.state = OTG_STATE_B_IDLE;
 			twl->linkstat = status;
-			twl->otg.last_event = status;
-			atomic_notifier_call_chain(&twl->otg.notifier,
-						status, twl->otg.gadget);
+			twl->phy.last_event = status;
+			atomic_notifier_call_chain(&twl->phy.notifier,
+						status, otg->gadget);
 		} else {
 			status = USB_EVENT_NONE;
 			twl->linkstat = status;
-			twl->otg.last_event = status;
-			atomic_notifier_call_chain(&twl->otg.notifier,
-						status, twl->otg.gadget);
+			twl->phy.last_event = status;
+			atomic_notifier_call_chain(&twl->phy.notifier,
+						status, otg->gadget);
 			if (twl->asleep) {
 				regulator_disable(twl->usb3v3);
 				twl->asleep = 0;
@@ -294,6 +295,7 @@
 static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
 {
 	struct twl6030_usb *twl = _twl;
+	struct usb_otg *otg = twl->phy.otg;
 	int status = USB_EVENT_NONE;
 	u8 hw_state;
 
@@ -307,12 +309,12 @@
 		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
 								0x10);
 		status = USB_EVENT_ID;
-		twl->otg.default_a = true;
-		twl->otg.state = OTG_STATE_A_IDLE;
+		otg->default_a = true;
+		twl->phy.state = OTG_STATE_A_IDLE;
 		twl->linkstat = status;
-		twl->otg.last_event = status;
-		atomic_notifier_call_chain(&twl->otg.notifier, status,
-							twl->otg.gadget);
+		twl->phy.last_event = status;
+		atomic_notifier_call_chain(&twl->phy.notifier, status,
+							otg->gadget);
 	} else  {
 		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
 								0x10);
@@ -324,25 +326,22 @@
 	return IRQ_HANDLED;
 }
 
-static int twl6030_set_peripheral(struct otg_transceiver *x,
+static int twl6030_set_peripheral(struct usb_otg *otg,
 		struct usb_gadget *gadget)
 {
-	struct twl6030_usb *twl;
-
-	if (!x)
+	if (!otg)
 		return -ENODEV;
 
-	twl = xceiv_to_twl(x);
-	twl->otg.gadget = gadget;
+	otg->gadget = gadget;
 	if (!gadget)
-		twl->otg.state = OTG_STATE_UNDEFINED;
+		otg->phy->state = OTG_STATE_UNDEFINED;
 
 	return 0;
 }
 
-static int twl6030_enable_irq(struct otg_transceiver *x)
+static int twl6030_enable_irq(struct usb_phy *x)
 {
-	struct twl6030_usb *twl = xceiv_to_twl(x);
+	struct twl6030_usb *twl = phy_to_twl(x);
 
 	twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1);
 	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
@@ -376,9 +375,9 @@
 							CHARGERUSB_CTRL1);
 }
 
-static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled)
+static int twl6030_set_vbus(struct usb_otg *otg, bool enabled)
 {
-	struct twl6030_usb *twl = xceiv_to_twl(x);
+	struct twl6030_usb *twl = phy_to_twl(otg->phy);
 
 	twl->vbus_enable = enabled;
 	schedule_work(&twl->set_vbus_work);
@@ -386,17 +385,14 @@
 	return 0;
 }
 
-static int twl6030_set_host(struct otg_transceiver *x, struct usb_bus *host)
+static int twl6030_set_host(struct usb_otg *otg, struct usb_bus *host)
 {
-	struct twl6030_usb *twl;
-
-	if (!x)
+	if (!otg)
 		return -ENODEV;
 
-	twl = xceiv_to_twl(x);
-	twl->otg.host = host;
+	otg->host = host;
 	if (!host)
-		twl->otg.state = OTG_STATE_UNDEFINED;
+		otg->phy->state = OTG_STATE_UNDEFINED;
 	return 0;
 }
 
@@ -405,6 +401,7 @@
 	struct twl6030_usb	*twl;
 	int			status, err;
 	struct twl4030_usb_data *pdata;
+	struct usb_otg		*otg;
 	struct device *dev = &pdev->dev;
 	pdata = dev->platform_data;
 
@@ -412,19 +409,29 @@
 	if (!twl)
 		return -ENOMEM;
 
+	otg = kzalloc(sizeof *otg, GFP_KERNEL);
+	if (!otg) {
+		kfree(twl);
+		return -ENOMEM;
+	}
+
 	twl->dev		= &pdev->dev;
 	twl->irq1		= platform_get_irq(pdev, 0);
 	twl->irq2		= platform_get_irq(pdev, 1);
 	twl->features		= pdata->features;
-	twl->otg.dev		= twl->dev;
-	twl->otg.label		= "twl6030";
-	twl->otg.set_host	= twl6030_set_host;
-	twl->otg.set_peripheral	= twl6030_set_peripheral;
-	twl->otg.set_vbus	= twl6030_set_vbus;
-	twl->otg.init		= twl6030_phy_init;
-	twl->otg.shutdown	= twl6030_phy_shutdown;
-	twl->otg.set_suspend	= twl6030_phy_suspend;
-	twl->otg.start_srp	= twl6030_start_srp;
+
+	twl->phy.dev		= twl->dev;
+	twl->phy.label		= "twl6030";
+	twl->phy.otg		= otg;
+	twl->phy.init		= twl6030_phy_init;
+	twl->phy.shutdown	= twl6030_phy_shutdown;
+	twl->phy.set_suspend	= twl6030_phy_suspend;
+
+	otg->phy		= &twl->phy;
+	otg->set_host		= twl6030_set_host;
+	otg->set_peripheral	= twl6030_set_peripheral;
+	otg->set_vbus		= twl6030_set_vbus;
+	otg->start_srp		= twl6030_start_srp;
 
 	/* init spinlock for workqueue */
 	spin_lock_init(&twl->lock);
@@ -432,16 +439,17 @@
 	err = twl6030_usb_ldo_init(twl);
 	if (err) {
 		dev_err(&pdev->dev, "ldo init failed\n");
+		kfree(otg);
 		kfree(twl);
 		return err;
 	}
-	otg_set_transceiver(&twl->otg);
+	usb_set_transceiver(&twl->phy);
 
 	platform_set_drvdata(pdev, twl);
 	if (device_create_file(&pdev->dev, &dev_attr_vbus))
 		dev_warn(&pdev->dev, "could not create sysfs file\n");
 
-	ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
+	ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
 
 	INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
 
@@ -453,6 +461,7 @@
 		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
 			twl->irq1, status);
 		device_remove_file(twl->dev, &dev_attr_vbus);
+		kfree(otg);
 		kfree(twl);
 		return status;
 	}
@@ -465,14 +474,15 @@
 			twl->irq2, status);
 		free_irq(twl->irq1, twl);
 		device_remove_file(twl->dev, &dev_attr_vbus);
+		kfree(otg);
 		kfree(twl);
 		return status;
 	}
 
 	twl->asleep = 0;
 	pdata->phy_init(dev);
-	twl6030_phy_suspend(&twl->otg, 0);
-	twl6030_enable_irq(&twl->otg);
+	twl6030_phy_suspend(&twl->phy, 0);
+	twl6030_enable_irq(&twl->phy);
 	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
 
 	return 0;
@@ -496,6 +506,7 @@
 	pdata->phy_exit(twl->dev);
 	device_remove_file(twl->dev, &dev_attr_vbus);
 	cancel_work_sync(&twl->set_vbus_work);
+	kfree(twl->phy.otg);
 	kfree(twl);
 
 	return 0;
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
index 0b04667..217339d 100644
--- a/drivers/usb/otg/ulpi.c
+++ b/drivers/usb/otg/ulpi.c
@@ -49,31 +49,31 @@
 	ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"),
 };
 
-static int ulpi_set_otg_flags(struct otg_transceiver *otg)
+static int ulpi_set_otg_flags(struct usb_phy *phy)
 {
 	unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN |
 			     ULPI_OTG_CTRL_DM_PULLDOWN;
 
-	if (otg->flags & ULPI_OTG_ID_PULLUP)
+	if (phy->flags & ULPI_OTG_ID_PULLUP)
 		flags |= ULPI_OTG_CTRL_ID_PULLUP;
 
 	/*
 	 * ULPI Specification rev.1.1 default
 	 * for Dp/DmPulldown is enabled.
 	 */
-	if (otg->flags & ULPI_OTG_DP_PULLDOWN_DIS)
+	if (phy->flags & ULPI_OTG_DP_PULLDOWN_DIS)
 		flags &= ~ULPI_OTG_CTRL_DP_PULLDOWN;
 
-	if (otg->flags & ULPI_OTG_DM_PULLDOWN_DIS)
+	if (phy->flags & ULPI_OTG_DM_PULLDOWN_DIS)
 		flags &= ~ULPI_OTG_CTRL_DM_PULLDOWN;
 
-	if (otg->flags & ULPI_OTG_EXTVBUSIND)
+	if (phy->flags & ULPI_OTG_EXTVBUSIND)
 		flags |= ULPI_OTG_CTRL_EXTVBUSIND;
 
-	return otg_io_write(otg, flags, ULPI_OTG_CTRL);
+	return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
 }
 
-static int ulpi_set_fc_flags(struct otg_transceiver *otg)
+static int ulpi_set_fc_flags(struct usb_phy *phy)
 {
 	unsigned int flags = 0;
 
@@ -81,27 +81,27 @@
 	 * ULPI Specification rev.1.1 default
 	 * for XcvrSelect is Full Speed.
 	 */
-	if (otg->flags & ULPI_FC_HS)
+	if (phy->flags & ULPI_FC_HS)
 		flags |= ULPI_FUNC_CTRL_HIGH_SPEED;
-	else if (otg->flags & ULPI_FC_LS)
+	else if (phy->flags & ULPI_FC_LS)
 		flags |= ULPI_FUNC_CTRL_LOW_SPEED;
-	else if (otg->flags & ULPI_FC_FS4LS)
+	else if (phy->flags & ULPI_FC_FS4LS)
 		flags |= ULPI_FUNC_CTRL_FS4LS;
 	else
 		flags |= ULPI_FUNC_CTRL_FULL_SPEED;
 
-	if (otg->flags & ULPI_FC_TERMSEL)
+	if (phy->flags & ULPI_FC_TERMSEL)
 		flags |= ULPI_FUNC_CTRL_TERMSELECT;
 
 	/*
 	 * ULPI Specification rev.1.1 default
 	 * for OpMode is Normal Operation.
 	 */
-	if (otg->flags & ULPI_FC_OP_NODRV)
+	if (phy->flags & ULPI_FC_OP_NODRV)
 		flags |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
-	else if (otg->flags & ULPI_FC_OP_DIS_NRZI)
+	else if (phy->flags & ULPI_FC_OP_DIS_NRZI)
 		flags |= ULPI_FUNC_CTRL_OPMODE_DISABLE_NRZI;
-	else if (otg->flags & ULPI_FC_OP_NSYNC_NEOP)
+	else if (phy->flags & ULPI_FC_OP_NSYNC_NEOP)
 		flags |= ULPI_FUNC_CTRL_OPMODE_NOSYNC_NOEOP;
 	else
 		flags |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
@@ -112,54 +112,54 @@
 	 */
 	flags |= ULPI_FUNC_CTRL_SUSPENDM;
 
-	return otg_io_write(otg, flags, ULPI_FUNC_CTRL);
+	return usb_phy_io_write(phy, flags, ULPI_FUNC_CTRL);
 }
 
-static int ulpi_set_ic_flags(struct otg_transceiver *otg)
+static int ulpi_set_ic_flags(struct usb_phy *phy)
 {
 	unsigned int flags = 0;
 
-	if (otg->flags & ULPI_IC_AUTORESUME)
+	if (phy->flags & ULPI_IC_AUTORESUME)
 		flags |= ULPI_IFC_CTRL_AUTORESUME;
 
-	if (otg->flags & ULPI_IC_EXTVBUS_INDINV)
+	if (phy->flags & ULPI_IC_EXTVBUS_INDINV)
 		flags |= ULPI_IFC_CTRL_EXTERNAL_VBUS;
 
-	if (otg->flags & ULPI_IC_IND_PASSTHRU)
+	if (phy->flags & ULPI_IC_IND_PASSTHRU)
 		flags |= ULPI_IFC_CTRL_PASSTHRU;
 
-	if (otg->flags & ULPI_IC_PROTECT_DIS)
+	if (phy->flags & ULPI_IC_PROTECT_DIS)
 		flags |= ULPI_IFC_CTRL_PROTECT_IFC_DISABLE;
 
-	return otg_io_write(otg, flags, ULPI_IFC_CTRL);
+	return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
 }
 
-static int ulpi_set_flags(struct otg_transceiver *otg)
+static int ulpi_set_flags(struct usb_phy *phy)
 {
 	int ret;
 
-	ret = ulpi_set_otg_flags(otg);
+	ret = ulpi_set_otg_flags(phy);
 	if (ret)
 		return ret;
 
-	ret = ulpi_set_ic_flags(otg);
+	ret = ulpi_set_ic_flags(phy);
 	if (ret)
 		return ret;
 
-	return ulpi_set_fc_flags(otg);
+	return ulpi_set_fc_flags(phy);
 }
 
-static int ulpi_check_integrity(struct otg_transceiver *otg)
+static int ulpi_check_integrity(struct usb_phy *phy)
 {
 	int ret, i;
 	unsigned int val = 0x55;
 
 	for (i = 0; i < 2; i++) {
-		ret = otg_io_write(otg, val, ULPI_SCRATCH);
+		ret = usb_phy_io_write(phy, val, ULPI_SCRATCH);
 		if (ret < 0)
 			return ret;
 
-		ret = otg_io_read(otg, ULPI_SCRATCH);
+		ret = usb_phy_io_read(phy, ULPI_SCRATCH);
 		if (ret < 0)
 			return ret;
 
@@ -175,13 +175,13 @@
 	return 0;
 }
 
-static int ulpi_init(struct otg_transceiver *otg)
+static int ulpi_init(struct usb_phy *phy)
 {
 	int i, vid, pid, ret;
 	u32 ulpi_id = 0;
 
 	for (i = 0; i < 4; i++) {
-		ret = otg_io_read(otg, ULPI_PRODUCT_ID_HIGH - i);
+		ret = usb_phy_io_read(phy, ULPI_PRODUCT_ID_HIGH - i);
 		if (ret < 0)
 			return ret;
 		ulpi_id = (ulpi_id << 8) | ret;
@@ -199,16 +199,17 @@
 		}
 	}
 
-	ret = ulpi_check_integrity(otg);
+	ret = ulpi_check_integrity(phy);
 	if (ret)
 		return ret;
 
-	return ulpi_set_flags(otg);
+	return ulpi_set_flags(phy);
 }
 
-static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+static int ulpi_set_host(struct usb_otg *otg, struct usb_bus *host)
 {
-	unsigned int flags = otg_io_read(otg, ULPI_IFC_CTRL);
+	struct usb_phy *phy = otg->phy;
+	unsigned int flags = usb_phy_io_read(phy, ULPI_IFC_CTRL);
 
 	if (!host) {
 		otg->host = NULL;
@@ -221,51 +222,62 @@
 		   ULPI_IFC_CTRL_3_PIN_SERIAL_MODE |
 		   ULPI_IFC_CTRL_CARKITMODE);
 
-	if (otg->flags & ULPI_IC_6PIN_SERIAL)
+	if (phy->flags & ULPI_IC_6PIN_SERIAL)
 		flags |= ULPI_IFC_CTRL_6_PIN_SERIAL_MODE;
-	else if (otg->flags & ULPI_IC_3PIN_SERIAL)
+	else if (phy->flags & ULPI_IC_3PIN_SERIAL)
 		flags |= ULPI_IFC_CTRL_3_PIN_SERIAL_MODE;
-	else if (otg->flags & ULPI_IC_CARKIT)
+	else if (phy->flags & ULPI_IC_CARKIT)
 		flags |= ULPI_IFC_CTRL_CARKITMODE;
 
-	return otg_io_write(otg, flags, ULPI_IFC_CTRL);
+	return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
 }
 
-static int ulpi_set_vbus(struct otg_transceiver *otg, bool on)
+static int ulpi_set_vbus(struct usb_otg *otg, bool on)
 {
-	unsigned int flags = otg_io_read(otg, ULPI_OTG_CTRL);
+	struct usb_phy *phy = otg->phy;
+	unsigned int flags = usb_phy_io_read(phy, ULPI_OTG_CTRL);
 
 	flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT);
 
 	if (on) {
-		if (otg->flags & ULPI_OTG_DRVVBUS)
+		if (phy->flags & ULPI_OTG_DRVVBUS)
 			flags |= ULPI_OTG_CTRL_DRVVBUS;
 
-		if (otg->flags & ULPI_OTG_DRVVBUS_EXT)
+		if (phy->flags & ULPI_OTG_DRVVBUS_EXT)
 			flags |= ULPI_OTG_CTRL_DRVVBUS_EXT;
 	}
 
-	return otg_io_write(otg, flags, ULPI_OTG_CTRL);
+	return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
 }
 
-struct otg_transceiver *
-otg_ulpi_create(struct otg_io_access_ops *ops,
+struct usb_phy *
+otg_ulpi_create(struct usb_phy_io_ops *ops,
 		unsigned int flags)
 {
-	struct otg_transceiver *otg;
+	struct usb_phy *phy;
+	struct usb_otg *otg;
 
-	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
-	if (!otg)
+	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
+	if (!phy)
 		return NULL;
 
-	otg->label	= "ULPI";
-	otg->flags	= flags;
-	otg->io_ops	= ops;
-	otg->init	= ulpi_init;
+	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
+	if (!otg) {
+		kfree(phy);
+		return NULL;
+	}
+
+	phy->label	= "ULPI";
+	phy->flags	= flags;
+	phy->io_ops	= ops;
+	phy->otg	= otg;
+	phy->init	= ulpi_init;
+
+	otg->phy	= phy;
 	otg->set_host	= ulpi_set_host;
 	otg->set_vbus	= ulpi_set_vbus;
 
-	return otg;
+	return phy;
 }
 EXPORT_SYMBOL_GPL(otg_ulpi_create);
 
diff --git a/drivers/usb/otg/ulpi_viewport.c b/drivers/usb/otg/ulpi_viewport.c
index e9a37f9..c5ba7e5 100644
--- a/drivers/usb/otg/ulpi_viewport.c
+++ b/drivers/usb/otg/ulpi_viewport.c
@@ -40,7 +40,7 @@
 	return -ETIMEDOUT;
 }
 
-static int ulpi_viewport_read(struct otg_transceiver *otg, u32 reg)
+static int ulpi_viewport_read(struct usb_phy *otg, u32 reg)
 {
 	int ret;
 	void __iomem *view = otg->io_priv;
@@ -58,7 +58,7 @@
 	return ULPI_VIEW_DATA_READ(readl(view));
 }
 
-static int ulpi_viewport_write(struct otg_transceiver *otg, u32 val, u32 reg)
+static int ulpi_viewport_write(struct usb_phy *otg, u32 val, u32 reg)
 {
 	int ret;
 	void __iomem *view = otg->io_priv;
@@ -74,7 +74,7 @@
 	return ulpi_viewport_wait(view, ULPI_VIEW_RUN);
 }
 
-struct otg_io_access_ops ulpi_viewport_access_ops = {
+struct usb_phy_io_ops ulpi_viewport_access_ops = {
 	.read	= ulpi_viewport_read,
 	.write	= ulpi_viewport_write,
 };
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index e9a5b1d..a165490 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -413,8 +413,7 @@
 	struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
 	struct renesas_usbhs_driver_callback *dfunc;
 	struct usbhs_priv *priv;
-	struct resource *res;
-	unsigned int irq;
+	struct resource *res, *irq_res;
 	int ret;
 
 	/* check platform information */
@@ -426,8 +425,8 @@
 
 	/* platform data */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irq = platform_get_irq(pdev, 0);
-	if (!res || (int)irq <= 0) {
+	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res || !irq_res) {
 		dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n");
 		return -ENODEV;
 	}
@@ -476,7 +475,9 @@
 	/*
 	 * priv settings
 	 */
-	priv->irq	= irq;
+	priv->irq	= irq_res->start;
+	if (irq_res->flags & IORESOURCE_IRQ_SHAREABLE)
+		priv->irqflags = IRQF_SHARED;
 	priv->pdev	= pdev;
 	INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug);
 	spin_lock_init(usbhs_priv_to_lock(priv));
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h
index d79b3e2..3f3ccd3 100644
--- a/drivers/usb/renesas_usbhs/common.h
+++ b/drivers/usb/renesas_usbhs/common.h
@@ -242,6 +242,7 @@
 
 	void __iomem *base;
 	unsigned int irq;
+	unsigned long irqflags;
 
 	struct renesas_usbhs_platform_callback	pfunc;
 	struct renesas_usbhs_driver_param	dparam;
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 72339bd..3648c82 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -23,6 +23,7 @@
 #define usbhsf_get_cfifo(p)	(&((p)->fifo_info.cfifo))
 #define usbhsf_get_d0fifo(p)	(&((p)->fifo_info.d0fifo))
 #define usbhsf_get_d1fifo(p)	(&((p)->fifo_info.d1fifo))
+#define usbhsf_is_cfifo(p, f)	(usbhsf_get_cfifo(p) == f)
 
 #define usbhsf_fifo_is_busy(f)	((f)->pipe) /* see usbhs_pipe_select_fifo */
 
@@ -75,8 +76,7 @@
 		pipe->handler = &usbhsf_null_handler;
 	}
 
-	list_del_init(&pkt->node);
-	list_add_tail(&pkt->node, &pipe->list);
+	list_move_tail(&pkt->node, &pipe->list);
 
 	/*
 	 * each pkt must hold own handler.
@@ -106,7 +106,7 @@
 	if (list_empty(&pipe->list))
 		return NULL;
 
-	return list_entry(pipe->list.next, struct usbhs_pkt, node);
+	return list_first_entry(&pipe->list, struct usbhs_pkt, node);
 }
 
 struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt)
@@ -305,7 +305,10 @@
 	}
 
 	/* "base" will be used below  */
-	usbhs_write(priv, fifo->sel, base | MBW_32);
+	if (usbhs_get_dparam(priv, has_sudmac) && !usbhsf_is_cfifo(priv, fifo))
+		usbhs_write(priv, fifo->sel, base);
+	else
+		usbhs_write(priv, fifo->sel, base | MBW_32);
 
 	/* check ISEL and CURPIPE value */
 	while (timeout--) {
@@ -762,9 +765,9 @@
 }
 
 static void usbhsf_dma_complete(void *arg);
-static void usbhsf_dma_prepare_tasklet(unsigned long data)
+static void xfer_work(struct work_struct *work)
 {
-	struct usbhs_pkt *pkt = (struct usbhs_pkt *)data;
+	struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work);
 	struct usbhs_pipe *pipe = pkt->pipe;
 	struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe);
 	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
@@ -844,11 +847,8 @@
 
 	pkt->trans = len;
 
-	tasklet_init(&fifo->tasklet,
-		     usbhsf_dma_prepare_tasklet,
-		     (unsigned long)pkt);
-
-	tasklet_schedule(&fifo->tasklet);
+	INIT_WORK(&pkt->work, xfer_work);
+	schedule_work(&pkt->work);
 
 	return 0;
 
@@ -938,11 +938,8 @@
 
 	pkt->trans = len;
 
-	tasklet_init(&fifo->tasklet,
-		     usbhsf_dma_prepare_tasklet,
-		     (unsigned long)pkt);
-
-	tasklet_schedule(&fifo->tasklet);
+	INIT_WORK(&pkt->work, xfer_work);
+	schedule_work(&pkt->work);
 
 	return 0;
 
diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h
index f68609c..c31731a 100644
--- a/drivers/usb/renesas_usbhs/fifo.h
+++ b/drivers/usb/renesas_usbhs/fifo.h
@@ -19,6 +19,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/sh_dma.h>
+#include <linux/workqueue.h>
 #include <asm/dma.h>
 #include "pipe.h"
 
@@ -31,7 +32,6 @@
 	u32 ctr;	/* xFIFOCTR */
 
 	struct usbhs_pipe	*pipe;
-	struct tasklet_struct	tasklet;
 
 	struct dma_chan		*tx_chan;
 	struct dma_chan		*rx_chan;
@@ -53,6 +53,7 @@
 	struct usbhs_pkt_handle *handler;
 	void (*done)(struct usbhs_priv *priv,
 		     struct usbhs_pkt *pkt);
+	struct work_struct work;
 	dma_addr_t dma;
 	void *buf;
 	int length;
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c
index 1b97fb1..0871e81 100644
--- a/drivers/usb/renesas_usbhs/mod.c
+++ b/drivers/usb/renesas_usbhs/mod.c
@@ -152,7 +152,7 @@
 
 	/* irq settings */
 	ret = request_irq(priv->irq, usbhs_interrupt,
-			  0, dev_name(dev), priv);
+			  priv->irqflags, dev_name(dev), priv);
 	if (ret) {
 		dev_err(dev, "irq request err\n");
 		goto mod_init_gadget_err;
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 7542aa9..00bd2a5 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -165,69 +165,32 @@
 /*
  *		dma map/unmap
  */
-static int usbhsg_dma_map(struct device *dev,
-			  struct usbhs_pkt *pkt,
-			  enum dma_data_direction dir)
-{
-	struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
-	struct usb_request *req = &ureq->req;
-
-	if (pkt->dma != DMA_ADDR_INVALID) {
-		dev_err(dev, "dma is already mapped\n");
-		return -EIO;
-	}
-
-	if (req->dma == DMA_ADDR_INVALID) {
-		pkt->dma = dma_map_single(dev, pkt->buf, pkt->length, dir);
-	} else {
-		dma_sync_single_for_device(dev, req->dma, req->length, dir);
-		pkt->dma = req->dma;
-	}
-
-	if (dma_mapping_error(dev, pkt->dma)) {
-		dev_err(dev, "dma mapping error %llx\n", (u64)pkt->dma);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int usbhsg_dma_unmap(struct device *dev,
-			    struct usbhs_pkt *pkt,
-			    enum dma_data_direction dir)
-{
-	struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
-	struct usb_request *req = &ureq->req;
-
-	if (pkt->dma == DMA_ADDR_INVALID) {
-		dev_err(dev, "dma is not mapped\n");
-		return -EIO;
-	}
-
-	if (req->dma == DMA_ADDR_INVALID)
-		dma_unmap_single(dev, pkt->dma, pkt->length, dir);
-	else
-		dma_sync_single_for_cpu(dev, req->dma, req->length, dir);
-
-	pkt->dma = DMA_ADDR_INVALID;
-
-	return 0;
-}
-
 static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
 {
+	struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
+	struct usb_request *req = &ureq->req;
 	struct usbhs_pipe *pipe = pkt->pipe;
 	struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe);
 	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
-	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
 	enum dma_data_direction dir;
+	int ret = 0;
 
-	dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	dir = usbhs_pipe_is_dir_host(pipe);
 
-	if (map)
-		return usbhsg_dma_map(dev, pkt, dir);
-	else
-		return usbhsg_dma_unmap(dev, pkt, dir);
+	if (map) {
+		/* it can not use scatter/gather */
+		WARN_ON(req->num_sgs);
+
+		ret = usb_gadget_map_request(&gpriv->gadget, req, dir);
+		if (ret < 0)
+			return ret;
+
+		pkt->dma = req->dma;
+	} else {
+		usb_gadget_unmap_request(&gpriv->gadget, req, dir);
+	}
+
+	return ret;
 }
 
 /*
@@ -657,8 +620,6 @@
 
 	usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq));
 
-	ureq->req.dma = DMA_ADDR_INVALID;
-
 	return &ureq->req;
 }
 
@@ -941,6 +902,11 @@
 	return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);
 }
 
+static void usbhs_mod_gadget_release(struct device *pdev)
+{
+	/* do nothing */
+}
+
 int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 {
 	struct usbhsg_gpriv *gpriv;
@@ -989,6 +955,7 @@
 	 */
 	dev_set_name(&gpriv->gadget.dev, "gadget");
 	gpriv->gadget.dev.parent	= dev;
+	gpriv->gadget.dev.release	= usbhs_mod_gadget_release;
 	gpriv->gadget.name		= "renesas_usbhs_udc";
 	gpriv->gadget.ops		= &usbhsg_gadget_ops;
 	gpriv->gadget.max_speed		= USB_SPEED_HIGH;
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 677f577..7141d65 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -238,6 +238,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called io_ti.
 
+config USB_SERIAL_F81232
+	tristate "USB Fintek F81232 Single Port Serial Driver"
+	help
+	  Say Y here if you want to use the Fintek F81232 single
+	  port usb to serial adapter.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called f81232.
+
 config USB_SERIAL_GARMIN
        tristate "USB Garmin GPS driver"
        help
@@ -417,6 +426,14 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called mct_u232.
 
+config USB_SERIAL_METRO
+	tristate "USB Metrologic Instruments USB-POS Barcode Scanner Driver"
+	---help---
+	  Say Y here if you want to use a USB POS Metrologic barcode scanner.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called metro-usb.
+
 config USB_SERIAL_MOS7720
 	tristate "USB Moschip 7720 Serial Driver"
 	---help---
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 9e536ee..07f198e 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -23,6 +23,7 @@
 obj-$(CONFIG_USB_SERIAL_EDGEPORT)		+= io_edgeport.o
 obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI)		+= io_ti.o
 obj-$(CONFIG_USB_SERIAL_EMPEG)			+= empeg.o
+obj-$(CONFIG_USB_SERIAL_F81232)			+= f81232.o
 obj-$(CONFIG_USB_SERIAL_FTDI_SIO)		+= ftdi_sio.o
 obj-$(CONFIG_USB_SERIAL_FUNSOFT)		+= funsoft.o
 obj-$(CONFIG_USB_SERIAL_GARMIN)			+= garmin_gps.o
@@ -36,6 +37,7 @@
 obj-$(CONFIG_USB_SERIAL_KLSI)			+= kl5kusb105.o
 obj-$(CONFIG_USB_SERIAL_KOBIL_SCT)		+= kobil_sct.o
 obj-$(CONFIG_USB_SERIAL_MCT_U232)		+= mct_u232.o
+obj-$(CONFIG_USB_SERIAL_METRO)			+= metro-usb.o
 obj-$(CONFIG_USB_SERIAL_MOS7720)		+= mos7720.o
 obj-$(CONFIG_USB_SERIAL_MOS7840)		+= mos7840.o
 obj-$(CONFIG_USB_SERIAL_MOTOROLA)		+= moto_modem.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 123bf91..eec4fb9 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -175,7 +175,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id =	1,
 };
 
 static struct usb_serial_driver aircable_device = {
@@ -183,7 +182,6 @@
 		.owner =	THIS_MODULE,
 		.name =		"aircable",
 	},
-	.usb_driver = 		&aircable_driver,
 	.id_table = 		id_table,
 	.num_ports =		1,
 	.bulk_out_size =	HCI_COMPLETE_FRAME,
@@ -194,36 +192,16 @@
 	.unthrottle =		usb_serial_generic_unthrottle,
 };
 
-static int __init aircable_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&aircable_device);
-	if (retval)
-		goto failed_serial_register;
-	retval = usb_register(&aircable_driver);
-	if (retval)
-		goto failed_usb_register;
-	return 0;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&aircable_device, NULL
+};
 
-failed_usb_register:
-	usb_serial_deregister(&aircable_device);
-failed_serial_register:
-	return retval;
-}
-
-static void __exit aircable_exit(void)
-{
-	usb_deregister(&aircable_driver);
-	usb_serial_deregister(&aircable_device);
-}
+module_usb_serial_driver(aircable_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
-module_init(aircable_init);
-module_exit(aircable_exit);
-
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 69328dc..f99f4710 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -719,7 +719,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id =	1,
 };
 
 static struct usb_serial_driver ark3116_device = {
@@ -728,7 +727,6 @@
 		.name =		"ark3116",
 	},
 	.id_table =		id_table,
-	.usb_driver =		&ark3116_driver,
 	.num_ports =		1,
 	.attach =		ark3116_attach,
 	.release =		ark3116_release,
@@ -745,32 +743,12 @@
 	.process_read_urb =	ark3116_process_read_urb,
 };
 
-static int __init ark3116_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&ark3116_device, NULL
+};
 
-	retval = usb_serial_register(&ark3116_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&ark3116_driver);
-	if (retval == 0) {
-		printk(KERN_INFO "%s:"
-		       DRIVER_VERSION ":"
-		       DRIVER_DESC "\n",
-		       KBUILD_MODNAME);
-	} else
-		usb_serial_deregister(&ark3116_device);
-	return retval;
-}
+module_usb_serial_driver(ark3116_driver, serial_drivers);
 
-static void __exit ark3116_exit(void)
-{
-	usb_deregister(&ark3116_driver);
-	usb_serial_deregister(&ark3116_device);
-}
-
-module_init(ark3116_init);
-module_exit(ark3116_exit);
 MODULE_LICENSE("GPL");
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 29ffeb6..a52e0d2 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -78,7 +78,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
-	.no_dynamic_id =	1,
 };
 
 /* All of the device info needed for the serial converters */
@@ -88,7 +87,6 @@
 		.name =		"belkin",
 	},
 	.description =		"Belkin / Peracom / GoHubs USB Serial Adapter",
-	.usb_driver =		&belkin_driver,
 	.id_table =		id_table_combined,
 	.num_ports =		1,
 	.open =			belkin_sa_open,
@@ -103,6 +101,10 @@
 	.release =		belkin_sa_release,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&belkin_device, NULL
+};
+
 struct belkin_sa_private {
 	spinlock_t		lock;
 	unsigned long		control_state;
@@ -522,34 +524,7 @@
 	return retval;
 }
 
-
-static int __init belkin_sa_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&belkin_device);
-	if (retval)
-		goto failed_usb_serial_register;
-	retval = usb_register(&belkin_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&belkin_device);
-failed_usb_serial_register:
-	return retval;
-}
-
-static void __exit belkin_sa_exit (void)
-{
-	usb_deregister(&belkin_driver);
-	usb_serial_deregister(&belkin_device);
-}
-
-
-module_init(belkin_sa_init);
-module_exit(belkin_sa_exit);
+module_usb_serial_driver(belkin_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 5e53cc5..aaab32d 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -625,7 +625,6 @@
 	.resume		= usb_serial_resume,
 	.reset_resume	= ch341_reset_resume,
 	.id_table	= id_table,
-	.no_dynamic_id	= 1,
 	.supports_autosuspend =	1,
 };
 
@@ -635,7 +634,6 @@
 		.name	= "ch341-uart",
 	},
 	.id_table          = id_table,
-	.usb_driver        = &ch341_driver,
 	.num_ports         = 1,
 	.open              = ch341_open,
 	.dtr_rts	   = ch341_dtr_rts,
@@ -650,30 +648,13 @@
 	.attach            = ch341_attach,
 };
 
-static int __init ch341_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&ch341_device, NULL
+};
 
-	retval = usb_serial_register(&ch341_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&ch341_driver);
-	if (retval)
-		usb_serial_deregister(&ch341_device);
-	return retval;
-}
+module_usb_serial_driver(ch341_driver, serial_drivers);
 
-static void __exit ch341_exit(void)
-{
-	usb_deregister(&ch341_driver);
-	usb_serial_deregister(&ch341_device);
-}
-
-module_init(ch341_init);
-module_exit(ch341_exit);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
-
-/* EOF ch341.c */
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 08a5575..0310e2d 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -49,6 +49,7 @@
 		unsigned int, unsigned int);
 static void cp210x_break_ctl(struct tty_struct *, int);
 static int cp210x_startup(struct usb_serial *);
+static void cp210x_release(struct usb_serial *);
 static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
 
 static bool debug;
@@ -121,6 +122,8 @@
 	{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+	{ USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
+	{ USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
 	{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
 	{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
@@ -149,12 +152,15 @@
 
 MODULE_DEVICE_TABLE(usb, id_table);
 
+struct cp210x_port_private {
+	__u8			bInterfaceNumber;
+};
+
 static struct usb_driver cp210x_driver = {
 	.name		= "cp210x",
 	.probe		= usb_serial_probe,
 	.disconnect	= usb_serial_disconnect,
 	.id_table	= id_table,
-	.no_dynamic_id	= 	1,
 };
 
 static struct usb_serial_driver cp210x_device = {
@@ -162,7 +168,6 @@
 		.owner =	THIS_MODULE,
 		.name = 	"cp210x",
 	},
-	.usb_driver		= &cp210x_driver,
 	.id_table		= id_table,
 	.num_ports		= 1,
 	.bulk_in_size		= 256,
@@ -174,9 +179,14 @@
 	.tiocmget 		= cp210x_tiocmget,
 	.tiocmset		= cp210x_tiocmset,
 	.attach			= cp210x_startup,
+	.release		= cp210x_release,
 	.dtr_rts		= cp210x_dtr_rts
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&cp210x_device, NULL
+};
+
 /* Config request types */
 #define REQTYPE_HOST_TO_DEVICE	0x41
 #define REQTYPE_DEVICE_TO_HOST	0xc1
@@ -261,6 +271,7 @@
 		unsigned int *data, int size)
 {
 	struct usb_serial *serial = port->serial;
+	struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
 	__le32 *buf;
 	int result, i, length;
 
@@ -276,7 +287,7 @@
 	/* Issue the request, attempting to read 'size' bytes */
 	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				request, REQTYPE_DEVICE_TO_HOST, 0x0000,
-				0, buf, size, 300);
+				port_priv->bInterfaceNumber, buf, size, 300);
 
 	/* Convert data into an array of integers */
 	for (i = 0; i < length; i++)
@@ -286,7 +297,7 @@
 
 	if (result != size) {
 		dbg("%s - Unable to send config request, "
-				"request=0x%x size=%d result=%d\n",
+				"request=0x%x size=%d result=%d",
 				__func__, request, size, result);
 		if (result > 0)
 			result = -EPROTO;
@@ -307,6 +318,7 @@
 		unsigned int *data, int size)
 {
 	struct usb_serial *serial = port->serial;
+	struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
 	__le32 *buf;
 	int result, i, length;
 
@@ -328,19 +340,19 @@
 		result = usb_control_msg(serial->dev,
 				usb_sndctrlpipe(serial->dev, 0),
 				request, REQTYPE_HOST_TO_DEVICE, 0x0000,
-				0, buf, size, 300);
+				port_priv->bInterfaceNumber, buf, size, 300);
 	} else {
 		result = usb_control_msg(serial->dev,
 				usb_sndctrlpipe(serial->dev, 0),
 				request, REQTYPE_HOST_TO_DEVICE, data[0],
-				0, NULL, 0, 300);
+				port_priv->bInterfaceNumber, NULL, 0, 300);
 	}
 
 	kfree(buf);
 
 	if ((size > 2 && result != size) || result < 0) {
 		dbg("%s - Unable to send request, "
-				"request=0x%x size=%d result=%d\n",
+				"request=0x%x size=%d result=%d",
 				__func__, request, size, result);
 		if (result > 0)
 			result = -EPROTO;
@@ -683,13 +695,13 @@
 		default:
 			dbg("cp210x driver does not "
 					"support the number of bits requested,"
-					" using 8 bit mode\n");
+					" using 8 bit mode");
 				bits |= BITS_DATA_8;
 				break;
 		}
 		if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
 			dbg("Number of data bits requested "
-					"not supported by device\n");
+					"not supported by device");
 	}
 
 	if ((cflag     & (PARENB|PARODD|CMSPAR)) !=
@@ -716,8 +728,7 @@
 			}
 		}
 		if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
-			dbg("Parity mode not supported "
-					"by device\n");
+			dbg("Parity mode not supported by device");
 	}
 
 	if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
@@ -732,7 +743,7 @@
 		}
 		if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
 			dbg("Number of stop bits requested "
-					"not supported by device\n");
+					"not supported by device");
 	}
 
 	if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
@@ -844,40 +855,40 @@
 
 static int cp210x_startup(struct usb_serial *serial)
 {
+	struct cp210x_port_private *port_priv;
+	int i;
+
 	/* cp210x buffers behave strangely unless device is reset */
 	usb_reset_device(serial->dev);
-	return 0;
-}
 
-static int __init cp210x_init(void)
-{
-	int retval;
+	for (i = 0; i < serial->num_ports; i++) {
+		port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
+		if (!port_priv)
+			return -ENOMEM;
 
-	retval = usb_serial_register(&cp210x_device);
-	if (retval)
-		return retval; /* Failed to register */
+		memset(port_priv, 0x00, sizeof(*port_priv));
+		port_priv->bInterfaceNumber =
+		    serial->interface->cur_altsetting->desc.bInterfaceNumber;
 
-	retval = usb_register(&cp210x_driver);
-	if (retval) {
-		/* Failed to register */
-		usb_serial_deregister(&cp210x_device);
-		return retval;
+		usb_set_serial_port_data(serial->port[i], port_priv);
 	}
 
-	/* Success */
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
 	return 0;
 }
 
-static void __exit cp210x_exit(void)
+static void cp210x_release(struct usb_serial *serial)
 {
-	usb_deregister(&cp210x_driver);
-	usb_serial_deregister(&cp210x_device);
+	struct cp210x_port_private *port_priv;
+	int i;
+
+	for (i = 0; i < serial->num_ports; i++) {
+		port_priv = usb_get_serial_port_data(serial->port[i]);
+		kfree(port_priv);
+		usb_set_serial_port_data(serial->port[i], NULL);
+	}
 }
 
-module_init(cp210x_init);
-module_exit(cp210x_exit);
+module_usb_serial_driver(cp210x_driver, serial_drivers);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 6bc3802..d39b941 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -82,7 +82,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver cyberjack_device = {
@@ -91,7 +90,6 @@
 		.name =		"cyberjack",
 	},
 	.description =		"Reiner SCT Cyberjack USB card reader",
-	.usb_driver = 		&cyberjack_driver,
 	.id_table =		id_table,
 	.num_ports =		1,
 	.attach =		cyberjack_startup,
@@ -106,6 +104,10 @@
 	.write_bulk_callback =	cyberjack_write_bulk_callback,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&cyberjack_device, NULL
+};
+
 struct cyberjack_private {
 	spinlock_t	lock;		/* Lock for SMP */
 	short		rdtodo;		/* Bytes still to read */
@@ -473,35 +475,7 @@
 	usb_serial_port_softint(port);
 }
 
-static int __init cyberjack_init(void)
-{
-	int retval;
-	retval  = usb_serial_register(&cyberjack_device);
-	if (retval)
-		goto failed_usb_serial_register;
-	retval = usb_register(&cyberjack_driver);
-	if (retval)
-		goto failed_usb_register;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION " "
-	       DRIVER_AUTHOR "\n");
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
-
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&cyberjack_device);
-failed_usb_serial_register:
-	return retval;
-}
-
-static void __exit cyberjack_exit(void)
-{
-	usb_deregister(&cyberjack_driver);
-	usb_serial_deregister(&cyberjack_device);
-}
-
-module_init(cyberjack_init);
-module_exit(cyberjack_exit);
+module_usb_serial_driver(cyberjack_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 3bdeafa..afc886c 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -94,7 +94,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
-	.no_dynamic_id = 	1,
 };
 
 enum packet_format {
@@ -163,7 +162,6 @@
 		.name =			"earthmate",
 	},
 	.description =			"DeLorme Earthmate USB",
-	.usb_driver = 			&cypress_driver,
 	.id_table =			id_table_earthmate,
 	.num_ports =			1,
 	.attach =			cypress_earthmate_startup,
@@ -190,7 +188,6 @@
 		.name =			"cyphidcom",
 	},
 	.description =			"HID->COM RS232 Adapter",
-	.usb_driver = 			&cypress_driver,
 	.id_table =			id_table_cyphidcomrs232,
 	.num_ports =			1,
 	.attach =			cypress_hidcom_startup,
@@ -217,7 +214,6 @@
 		.name =			"nokiaca42v2",
 	},
 	.description =			"Nokia CA-42 V2 Adapter",
-	.usb_driver = 			&cypress_driver,
 	.id_table =			id_table_nokiaca42v2,
 	.num_ports =			1,
 	.attach =			cypress_ca42v2_startup,
@@ -238,6 +234,11 @@
 	.write_int_callback =		cypress_write_int_callback,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&cypress_earthmate_device, &cypress_hidcom_device,
+	&cypress_ca42v2_device, NULL
+};
+
 /*****************************************************************************
  * Cypress serial helper functions
  *****************************************************************************/
@@ -800,7 +801,7 @@
 		cypress_write_int_callback, port, priv->write_urb_interval);
 	result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
 	if (result) {
-		dev_err(&port->dev,
+		dev_err_console(port,
 				"%s - failed submitting write urb, error %d\n",
 							__func__, result);
 		priv->write_urb_in_use = 0;
@@ -1345,58 +1346,7 @@
 	cypress_send(port);
 }
 
-
-/*****************************************************************************
- * Module functions
- *****************************************************************************/
-
-static int __init cypress_init(void)
-{
-	int retval;
-
-	dbg("%s", __func__);
-
-	retval = usb_serial_register(&cypress_earthmate_device);
-	if (retval)
-		goto failed_em_register;
-	retval = usb_serial_register(&cypress_hidcom_device);
-	if (retval)
-		goto failed_hidcom_register;
-	retval = usb_serial_register(&cypress_ca42v2_device);
-	if (retval)
-		goto failed_ca42v2_register;
-	retval = usb_register(&cypress_driver);
-	if (retval)
-		goto failed_usb_register;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-
-failed_usb_register:
-	usb_serial_deregister(&cypress_ca42v2_device);
-failed_ca42v2_register:
-	usb_serial_deregister(&cypress_hidcom_device);
-failed_hidcom_register:
-	usb_serial_deregister(&cypress_earthmate_device);
-failed_em_register:
-	return retval;
-}
-
-
-static void __exit cypress_exit(void)
-{
-	dbg("%s", __func__);
-
-	usb_deregister(&cypress_driver);
-	usb_serial_deregister(&cypress_earthmate_device);
-	usb_serial_deregister(&cypress_hidcom_device);
-	usb_serial_deregister(&cypress_ca42v2_device);
-}
-
-
-module_init(cypress_init);
-module_exit(cypress_exit);
+module_usb_serial_driver(cypress_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index b23bebd..999f91b 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -276,7 +276,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
-	.no_dynamic_id = 	1,
 };
 
 
@@ -288,7 +287,6 @@
 		.name =			"digi_2",
 	},
 	.description =			"Digi 2 port USB adapter",
-	.usb_driver = 			&digi_driver,
 	.id_table =			id_table_2,
 	.num_ports =			3,
 	.open =				digi_open,
@@ -316,7 +314,6 @@
 		.name =			"digi_4",
 	},
 	.description =			"Digi 4 port USB adapter",
-	.usb_driver = 			&digi_driver,
 	.id_table =			id_table_4,
 	.num_ports =			4,
 	.open =				digi_open,
@@ -337,6 +334,9 @@
 	.release =			digi_release,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&digi_acceleport_2_device, &digi_acceleport_4_device, NULL
+};
 
 /* Functions */
 
@@ -995,7 +995,7 @@
 	/* return length of new data written, or error */
 	spin_unlock_irqrestore(&priv->dp_port_lock, flags);
 	if (ret < 0)
-		dev_err(&port->dev,
+		dev_err_console(port,
 			"%s: usb_submit_urb failed, ret=%d, port=%d\n",
 			__func__, ret, priv->dp_port_num);
 	dbg("digi_write: returning %d", ret);
@@ -1065,7 +1065,7 @@
 
 	spin_unlock(&priv->dp_port_lock);
 	if (ret && ret != -EPERM)
-		dev_err(&port->dev,
+		dev_err_console(port,
 			"%s: usb_submit_urb failed, ret=%d, port=%d\n",
 			__func__, ret, priv->dp_port_num);
 }
@@ -1580,40 +1580,7 @@
 
 }
 
-static int __init digi_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&digi_acceleport_2_device);
-	if (retval)
-		goto failed_acceleport_2_device;
-	retval = usb_serial_register(&digi_acceleport_4_device);
-	if (retval)
-		goto failed_acceleport_4_device;
-	retval = usb_register(&digi_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&digi_acceleport_4_device);
-failed_acceleport_4_device:
-	usb_serial_deregister(&digi_acceleport_2_device);
-failed_acceleport_2_device:
-	return retval;
-}
-
-static void __exit digi_exit (void)
-{
-	usb_deregister(&digi_driver);
-	usb_serial_deregister(&digi_acceleport_2_device);
-	usb_serial_deregister(&digi_acceleport_4_device);
-}
-
-
-module_init(digi_init);
-module_exit(digi_exit);
-
+module_usb_serial_driver(digi_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index aced681..5b99fc0 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -56,7 +56,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id =	1,
 };
 
 static struct usb_serial_driver empeg_device = {
@@ -65,7 +64,6 @@
 		.name =		"empeg",
 	},
 	.id_table =		id_table,
-	.usb_driver =		&empeg_driver,
 	.num_ports =		1,
 	.bulk_out_size =	256,
 	.throttle =		usb_serial_generic_throttle,
@@ -74,6 +72,10 @@
 	.init_termios =		empeg_init_termios,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&empeg_device, NULL
+};
+
 static int empeg_startup(struct usb_serial *serial)
 {
 	int r;
@@ -136,33 +138,7 @@
 	tty_encode_baud_rate(tty, 115200, 115200);
 }
 
-static int __init empeg_init(void)
-{
-	int retval;
-
-	retval = usb_serial_register(&empeg_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&empeg_driver);
-	if (retval) {
-		usb_serial_deregister(&empeg_device);
-		return retval;
-	}
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-
-	return 0;
-}
-
-static void __exit empeg_exit(void)
-{
-	usb_deregister(&empeg_driver);
-	usb_serial_deregister(&empeg_device);
-}
-
-
-module_init(empeg_init);
-module_exit(empeg_exit);
+module_usb_serial_driver(empeg_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
new file mode 100644
index 0000000..88c0b19
--- /dev/null
+++ b/drivers/usb/serial/f81232.c
@@ -0,0 +1,405 @@
+/*
+ * Fintek F81232 USB to serial adaptor driver
+ *
+ * Copyright (C) 2012 Greg Kroah-Hartman (gregkh@linuxfoundation.org)
+ * Copyright (C) 2012 Linux Foundation
+ *
+ * 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+static bool debug;
+
+static const struct usb_device_id id_table[] = {
+	{ USB_DEVICE(0x1934, 0x0706) },
+	{ }					/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+#define CONTROL_DTR			0x01
+#define CONTROL_RTS			0x02
+
+#define UART_STATE			0x08
+#define UART_STATE_TRANSIENT_MASK	0x74
+#define UART_DCD			0x01
+#define UART_DSR			0x02
+#define UART_BREAK_ERROR		0x04
+#define UART_RING			0x08
+#define UART_FRAME_ERROR		0x10
+#define UART_PARITY_ERROR		0x20
+#define UART_OVERRUN_ERROR		0x40
+#define UART_CTS			0x80
+
+struct f81232_private {
+	spinlock_t lock;
+	wait_queue_head_t delta_msr_wait;
+	u8 line_control;
+	u8 line_status;
+};
+
+static void f81232_update_line_status(struct usb_serial_port *port,
+				      unsigned char *data,
+				      unsigned int actual_length)
+{
+}
+
+static void f81232_read_int_callback(struct urb *urb)
+{
+	struct usb_serial_port *port =  urb->context;
+	unsigned char *data = urb->transfer_buffer;
+	unsigned int actual_length = urb->actual_length;
+	int status = urb->status;
+	int retval;
+
+	dbg("%s (%d)", __func__, port->number);
+
+	switch (status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d", __func__,
+		    status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d", __func__,
+		    status);
+		goto exit;
+	}
+
+	usb_serial_debug_data(debug, &port->dev, __func__,
+			      urb->actual_length, urb->transfer_buffer);
+
+	f81232_update_line_status(port, data, actual_length);
+
+exit:
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	if (retval)
+		dev_err(&urb->dev->dev,
+			"%s - usb_submit_urb failed with result %d\n",
+			__func__, retval);
+}
+
+static void f81232_process_read_urb(struct urb *urb)
+{
+	struct usb_serial_port *port = urb->context;
+	struct f81232_private *priv = usb_get_serial_port_data(port);
+	struct tty_struct *tty;
+	unsigned char *data = urb->transfer_buffer;
+	char tty_flag = TTY_NORMAL;
+	unsigned long flags;
+	u8 line_status;
+	int i;
+
+	/* update line status */
+	spin_lock_irqsave(&priv->lock, flags);
+	line_status = priv->line_status;
+	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
+	spin_unlock_irqrestore(&priv->lock, flags);
+	wake_up_interruptible(&priv->delta_msr_wait);
+
+	if (!urb->actual_length)
+		return;
+
+	tty = tty_port_tty_get(&port->port);
+	if (!tty)
+		return;
+
+	/* break takes precedence over parity, */
+	/* which takes precedence over framing errors */
+	if (line_status & UART_BREAK_ERROR)
+		tty_flag = TTY_BREAK;
+	else if (line_status & UART_PARITY_ERROR)
+		tty_flag = TTY_PARITY;
+	else if (line_status & UART_FRAME_ERROR)
+		tty_flag = TTY_FRAME;
+	dbg("%s - tty_flag = %d", __func__, tty_flag);
+
+	/* overrun is special, not associated with a char */
+	if (line_status & UART_OVERRUN_ERROR)
+		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+
+	if (port->port.console && port->sysrq) {
+		for (i = 0; i < urb->actual_length; ++i)
+			if (!usb_serial_handle_sysrq_char(port, data[i]))
+				tty_insert_flip_char(tty, data[i], tty_flag);
+	} else {
+		tty_insert_flip_string_fixed_flag(tty, data, tty_flag,
+							urb->actual_length);
+	}
+
+	tty_flip_buffer_push(tty);
+	tty_kref_put(tty);
+}
+
+static int set_control_lines(struct usb_device *dev, u8 value)
+{
+	/* FIXME - Stubbed out for now */
+	return 0;
+}
+
+static void f81232_break_ctl(struct tty_struct *tty, int break_state)
+{
+	/* FIXME - Stubbed out for now */
+
+	/*
+	 * break_state = -1 to turn on break, and 0 to turn off break
+	 * see drivers/char/tty_io.c to see it used.
+	 * last_set_data_urb_value NEVER has the break bit set in it.
+	 */
+}
+
+static void f81232_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
+{
+	/* FIXME - Stubbed out for now */
+
+	/* Don't change anything if nothing has changed */
+	if (!tty_termios_hw_change(tty->termios, old_termios))
+		return;
+
+	/* Do the real work here... */
+}
+
+static int f81232_tiocmget(struct tty_struct *tty)
+{
+	/* FIXME - Stubbed out for now */
+	return 0;
+}
+
+static int f81232_tiocmset(struct tty_struct *tty,
+			unsigned int set, unsigned int clear)
+{
+	/* FIXME - Stubbed out for now */
+	return 0;
+}
+
+static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port)
+{
+	struct ktermios tmp_termios;
+	int result;
+
+	/* Setup termios */
+	if (tty)
+		f81232_set_termios(tty, port, &tmp_termios);
+
+	dbg("%s - submitting interrupt urb", __func__);
+	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+	if (result) {
+		dev_err(&port->dev, "%s - failed submitting interrupt urb,"
+			" error %d\n", __func__, result);
+		return result;
+	}
+
+	result = usb_serial_generic_open(tty, port);
+	if (result) {
+		usb_kill_urb(port->interrupt_in_urb);
+		return result;
+	}
+
+	port->port.drain_delay = 256;
+	return 0;
+}
+
+static void f81232_close(struct usb_serial_port *port)
+{
+	usb_serial_generic_close(port);
+	usb_kill_urb(port->interrupt_in_urb);
+}
+
+static void f81232_dtr_rts(struct usb_serial_port *port, int on)
+{
+	struct f81232_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	u8 control;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	/* Change DTR and RTS */
+	if (on)
+		priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+	else
+		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+	control = priv->line_control;
+	spin_unlock_irqrestore(&priv->lock, flags);
+	set_control_lines(port->serial->dev, control);
+}
+
+static int f81232_carrier_raised(struct usb_serial_port *port)
+{
+	struct f81232_private *priv = usb_get_serial_port_data(port);
+	if (priv->line_status & UART_DCD)
+		return 1;
+	return 0;
+}
+
+static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+{
+	struct f81232_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	unsigned int prevstatus;
+	unsigned int status;
+	unsigned int changed;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	prevstatus = priv->line_status;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	while (1) {
+		interruptible_sleep_on(&priv->delta_msr_wait);
+		/* see if a signal did it */
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+
+		spin_lock_irqsave(&priv->lock, flags);
+		status = priv->line_status;
+		spin_unlock_irqrestore(&priv->lock, flags);
+
+		changed = prevstatus ^ status;
+
+		if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||
+		    ((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
+		    ((arg & TIOCM_CD)  && (changed & UART_DCD)) ||
+		    ((arg & TIOCM_CTS) && (changed & UART_CTS))) {
+			return 0;
+		}
+		prevstatus = status;
+	}
+	/* NOTREACHED */
+	return 0;
+}
+
+static int f81232_ioctl(struct tty_struct *tty,
+			unsigned int cmd, unsigned long arg)
+{
+	struct serial_struct ser;
+	struct usb_serial_port *port = tty->driver_data;
+	dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		memset(&ser, 0, sizeof ser);
+		ser.type = PORT_16654;
+		ser.line = port->serial->minor;
+		ser.port = port->number;
+		ser.baud_base = 460800;
+
+		if (copy_to_user((void __user *)arg, &ser, sizeof ser))
+			return -EFAULT;
+
+		return 0;
+
+	case TIOCMIWAIT:
+		dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
+		return wait_modem_info(port, arg);
+	default:
+		dbg("%s not supported = 0x%04x", __func__, cmd);
+		break;
+	}
+	return -ENOIOCTLCMD;
+}
+
+static int f81232_startup(struct usb_serial *serial)
+{
+	struct f81232_private *priv;
+	int i;
+
+	for (i = 0; i < serial->num_ports; ++i) {
+		priv = kzalloc(sizeof(struct f81232_private), GFP_KERNEL);
+		if (!priv)
+			goto cleanup;
+		spin_lock_init(&priv->lock);
+		init_waitqueue_head(&priv->delta_msr_wait);
+		usb_set_serial_port_data(serial->port[i], priv);
+	}
+	return 0;
+
+cleanup:
+	for (--i; i >= 0; --i) {
+		priv = usb_get_serial_port_data(serial->port[i]);
+		kfree(priv);
+		usb_set_serial_port_data(serial->port[i], NULL);
+	}
+	return -ENOMEM;
+}
+
+static void f81232_release(struct usb_serial *serial)
+{
+	int i;
+	struct f81232_private *priv;
+
+	for (i = 0; i < serial->num_ports; ++i) {
+		priv = usb_get_serial_port_data(serial->port[i]);
+		kfree(priv);
+	}
+}
+
+static struct usb_driver f81232_driver = {
+	.name =		"f81232",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+	.suspend =      usb_serial_suspend,
+	.resume =       usb_serial_resume,
+	.no_dynamic_id = 	1,
+	.supports_autosuspend =	1,
+};
+
+static struct usb_serial_driver f81232_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"f81232",
+	},
+	.id_table =		id_table,
+	.usb_driver = 		&f81232_driver,
+	.num_ports =		1,
+	.bulk_in_size =		256,
+	.bulk_out_size =	256,
+	.open =			f81232_open,
+	.close =		f81232_close,
+	.dtr_rts = 		f81232_dtr_rts,
+	.carrier_raised =	f81232_carrier_raised,
+	.ioctl =		f81232_ioctl,
+	.break_ctl =		f81232_break_ctl,
+	.set_termios =		f81232_set_termios,
+	.tiocmget =		f81232_tiocmget,
+	.tiocmset =		f81232_tiocmset,
+	.process_read_urb =	f81232_process_read_urb,
+	.read_int_callback =	f81232_read_int_callback,
+	.attach =		f81232_startup,
+	.release =		f81232_release,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+	&f81232_device,
+	NULL,
+};
+
+module_usb_serial_driver(f81232_driver, serial_drivers);
+
+MODULE_DESCRIPTION("Fintek F81232 USB to serial adaptor driver");
+MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org");
+MODULE_LICENSE("GPL v2");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index f770415..7c229d3 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -188,6 +188,7 @@
 		.driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_232H_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_FTX_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
@@ -536,6 +537,10 @@
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) },
 	{ USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
 	{ USB_DEVICE(OCT_VID, OCT_US101_PID) },
 	{ USB_DEVICE(OCT_VID, OCT_DK201_PID) },
@@ -797,7 +802,7 @@
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
-	{ USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) },
+	{ USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) },
 	{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
 	{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
@@ -846,6 +851,9 @@
 	{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
+	{ USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -857,7 +865,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
-	.no_dynamic_id =	1,
 };
 
 static const char *ftdi_chip_name[] = {
@@ -868,7 +875,8 @@
 	[FT232RL] = "FT232RL",
 	[FT2232H] = "FT2232H",
 	[FT4232H] = "FT4232H",
-	[FT232H]  = "FT232H"
+	[FT232H]  = "FT232H",
+	[FTX]     = "FT-X"
 };
 
 
@@ -915,7 +923,6 @@
 		.name =		"ftdi_sio",
 	},
 	.description =		"FTDI USB Serial Device",
-	.usb_driver = 		&ftdi_driver,
 	.id_table =		id_table_combined,
 	.num_ports =		1,
 	.bulk_in_size =		512,
@@ -938,6 +945,10 @@
 	.break_ctl =		ftdi_break_ctl,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&ftdi_sio_device, NULL
+};
+
 
 #define WDR_TIMEOUT 5000 /* default urb timeout */
 #define WDR_SHORT_TIMEOUT 1000	/* shorter urb timeout */
@@ -1169,7 +1180,8 @@
 		break;
 	case FT232BM: /* FT232BM chip */
 	case FT2232C: /* FT2232C chip */
-	case FT232RL:
+	case FT232RL: /* FT232RL chip */
+	case FTX:     /* FT-X series */
 		if (baud <= 3000000) {
 			__u16 product_id = le16_to_cpu(
 				port->serial->dev->descriptor.idProduct);
@@ -1458,10 +1470,14 @@
 	} else if (version < 0x900) {
 		/* Assume it's an FT232RL */
 		priv->chip_type = FT232RL;
-	} else {
+	} else if (version < 0x1000) {
 		/* Assume it's an FT232H */
 		priv->chip_type = FT232H;
+	} else {
+		/* Assume it's an FT-X series device */
+		priv->chip_type = FTX;
 	}
+
 	dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]);
 }
 
@@ -1589,7 +1605,8 @@
 		     priv->chip_type == FT232RL ||
 		     priv->chip_type == FT2232H ||
 		     priv->chip_type == FT4232H ||
-		     priv->chip_type == FT232H)) {
+		     priv->chip_type == FT232H ||
+		     priv->chip_type == FTX)) {
 			retval = device_create_file(&port->dev,
 						    &dev_attr_latency_timer);
 		}
@@ -1611,7 +1628,8 @@
 		    priv->chip_type == FT232RL ||
 		    priv->chip_type == FT2232H ||
 		    priv->chip_type == FT4232H ||
-                    priv->chip_type == FT232H) {
+		    priv->chip_type == FT232H ||
+		    priv->chip_type == FTX) {
 			device_remove_file(&port->dev, &dev_attr_latency_timer);
 		}
 	}
@@ -1763,7 +1781,8 @@
 
 	dbg("%s", __func__);
 
-	if (strcmp(udev->manufacturer, "CALAO Systems") == 0)
+	if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
+	    (udev->product && !strcmp(udev->product, "BeagleBone/XDS100")))
 		return ftdi_jtag_probe(serial);
 
 	return 0;
@@ -2288,6 +2307,7 @@
 	case FT2232H:
 	case FT4232H:
 	case FT232H:
+	case FTX:
 		len = 2;
 		break;
 	default:
@@ -2420,19 +2440,10 @@
 		id_table_combined[i].idVendor = vendor;
 		id_table_combined[i].idProduct = product;
 	}
-	retval = usb_serial_register(&ftdi_sio_device);
-	if (retval)
-		goto failed_sio_register;
-	retval = usb_register(&ftdi_driver);
-	if (retval)
-		goto failed_usb_register;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&ftdi_sio_device);
-failed_sio_register:
+	retval = usb_serial_register_drivers(&ftdi_driver, serial_drivers);
+	if (retval == 0)
+		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+			       DRIVER_DESC "\n");
 	return retval;
 }
 
@@ -2440,8 +2451,7 @@
 {
 	dbg("%s", __func__);
 
-	usb_deregister(&ftdi_driver);
-	usb_serial_deregister(&ftdi_sio_device);
+	usb_serial_deregister_drivers(&ftdi_driver, serial_drivers);
 }
 
 
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 19584fa..ed58c6f 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -157,7 +157,8 @@
 	FT232RL = 5,
 	FT2232H = 6,
 	FT4232H = 7,
-	FT232H  = 8
+	FT232H  = 8,
+	FTX     = 9,
 };
 
 enum ftdi_sio_baudrate {
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 6f6058f..0838baf8 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -23,12 +23,15 @@
 #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
 #define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
 #define FTDI_232H_PID  0x6014 /* Single channel hi-speed device */
+#define FTDI_FTX_PID   0x6015 /* FT-X series (FT201X, FT230X, FT231X, etc) */
 #define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX */
 #define FTDI_232RL_PID  0xFBFA  /* Product ID for FT232RL */
 
 
 /*** third-party PIDs (using FTDI_VID) ***/
 
+#define FTDI_LUMEL_PD12_PID	0x6002
+
 /*
  * Marvell OpenRD Base, Client
  * http://www.open-rd.org
@@ -97,6 +100,8 @@
 #define FTDI_TACTRIX_OPENPORT_13S_PID	0xCC49	/* OpenPort 1.3 Subaru */
 #define FTDI_TACTRIX_OPENPORT_13U_PID	0xCC4A	/* OpenPort 1.3 Universal */
 
+#define FTDI_DISTORTEC_JTAG_LOCK_PICK_PID	0xCFF8
+
 /* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */
 /* the VID is the standard ftdi vid (FTDI_VID) */
 #define FTDI_SCS_DEVICE_0_PID 0xD010    /* SCS PTC-IIusb */
@@ -532,10 +537,14 @@
 #define ADI_GNICEPLUS_PID	0xF001
 
 /*
- * Hornby Elite
+ * Microchip Technology, Inc.
+ *
+ * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by:
+ * Hornby Elite - Digital Command Control Console
+ * http://www.hornby.com/hornby-dcc/controllers/
  */
-#define HORNBY_VID		0x04D8
-#define HORNBY_ELITE_PID	0x000A
+#define MICROCHIP_VID		0x04D8
+#define MICROCHIP_USB_BOARD_PID	0x000A /* CDC RS-232 Emulation Demo */
 
 /*
  * RATOC REX-USB60F
@@ -680,6 +689,10 @@
 #define SEALEVEL_2803_6_PID	0X2863	/* SeaLINK+8 (2803) Port 6 */
 #define SEALEVEL_2803_7_PID	0X2873	/* SeaLINK+8 (2803) Port 7 */
 #define SEALEVEL_2803_8_PID	0X2883	/* SeaLINK+8 (2803) Port 8 */
+#define SEALEVEL_2803R_1_PID	0Xa02a	/* SeaLINK+8 (2803-ROHS) Port 1+2 */
+#define SEALEVEL_2803R_2_PID	0Xa02b	/* SeaLINK+8 (2803-ROHS) Port 3+4 */
+#define SEALEVEL_2803R_3_PID	0Xa02c	/* SeaLINK+8 (2803-ROHS) Port 5+6 */
+#define SEALEVEL_2803R_4_PID	0Xa02d	/* SeaLINK+8 (2803-ROHS) Port 7+8 */
 
 /*
  * JETI SPECTROMETER SPECBOS 1201
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
index 5d4b099..4577b36 100644
--- a/drivers/usb/serial/funsoft.c
+++ b/drivers/usb/serial/funsoft.c
@@ -29,7 +29,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver funsoft_device = {
@@ -38,31 +37,15 @@
 		.name =		"funsoft",
 	},
 	.id_table =		id_table,
-	.usb_driver = 		&funsoft_driver,
 	.num_ports =		1,
 };
 
-static int __init funsoft_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&funsoft_device, NULL
+};
 
-	retval = usb_serial_register(&funsoft_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&funsoft_driver);
-	if (retval)
-		usb_serial_deregister(&funsoft_device);
-	return retval;
-}
+module_usb_serial_driver(funsoft_driver, serial_drivers);
 
-static void __exit funsoft_exit(void)
-{
-	usb_deregister(&funsoft_driver);
-	usb_serial_deregister(&funsoft_device);
-}
-
-module_init(funsoft_init);
-module_exit(funsoft_exit);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 2134337..e8eb634 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -224,7 +224,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id = 1,
 };
 
 
@@ -1497,7 +1496,6 @@
 		.name        = "garmin_gps",
 	},
 	.description         = "Garmin GPS usb/tty",
-	.usb_driver          = &garmin_driver,
 	.id_table            = id_table,
 	.num_ports           = 1,
 	.open                = garmin_open,
@@ -1514,40 +1512,11 @@
 	.read_int_callback   = garmin_read_int_callback,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&garmin_device, NULL
+};
 
-
-static int __init garmin_init(void)
-{
-	int retval;
-
-	retval = usb_serial_register(&garmin_device);
-	if (retval)
-		goto failed_garmin_register;
-	retval = usb_register(&garmin_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&garmin_device);
-failed_garmin_register:
-	return retval;
-}
-
-
-static void __exit garmin_exit(void)
-{
-	usb_deregister(&garmin_driver);
-	usb_serial_deregister(&garmin_device);
-}
-
-
-
-
-module_init(garmin_init);
-module_exit(garmin_exit);
+module_usb_serial_driver(garmin_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -1557,4 +1526,3 @@
 MODULE_PARM_DESC(debug, "Debug enabled or not");
 module_param(initial_mode, int, S_IRUGO);
 MODULE_PARM_DESC(initial_mode, "Initial mode");
-
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index f740357..664deb6 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -54,7 +54,6 @@
 	.probe =	generic_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	generic_serial_ids,
-	.no_dynamic_id =	1,
 };
 
 /* All of the device info needed for the Generic Serial Converter */
@@ -64,7 +63,6 @@
 		.name =		"generic",
 	},
 	.id_table =		generic_device_ids,
-	.usb_driver = 		&generic_driver,
 	.num_ports =		1,
 	.disconnect =		usb_serial_generic_disconnect,
 	.release =		usb_serial_generic_release,
@@ -73,6 +71,10 @@
 	.resume =		usb_serial_generic_resume,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&usb_serial_generic_device, NULL
+};
+
 static int generic_probe(struct usb_interface *interface,
 			       const struct usb_device_id *id)
 {
@@ -97,13 +99,7 @@
 		USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
 
 	/* register our generic driver with ourselves */
-	retval = usb_serial_register(&usb_serial_generic_device);
-	if (retval)
-		goto exit;
-	retval = usb_register(&generic_driver);
-	if (retval)
-		usb_serial_deregister(&usb_serial_generic_device);
-exit:
+	retval = usb_serial_register_drivers(&generic_driver, serial_drivers);
 #endif
 	return retval;
 }
@@ -112,8 +108,7 @@
 {
 #ifdef CONFIG_USB_SERIAL_GENERIC
 	/* remove our generic driver */
-	usb_deregister(&generic_driver);
-	usb_serial_deregister(&usb_serial_generic_device);
+	usb_serial_deregister_drivers(&generic_driver, serial_drivers);
 #endif
 }
 
@@ -217,7 +212,7 @@
 	clear_bit(i, &port->write_urbs_free);
 	result = usb_submit_urb(urb, GFP_ATOMIC);
 	if (result) {
-		dev_err(&port->dev, "%s - error submitting urb: %d\n",
+		dev_err_console(port, "%s - error submitting urb: %d\n",
 						__func__, result);
 		set_bit(i, &port->write_urbs_free);
 		spin_lock_irqsave(&port->lock, flags);
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 8093791..2563e78 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -41,7 +41,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver hp49gp_device = {
@@ -50,36 +49,14 @@
 		.name =		"hp4X",
 	},
 	.id_table =		id_table,
-	.usb_driver = 		&hp49gp_driver,
 	.num_ports =		1,
 };
 
-static int __init hp49gp_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&hp49gp_device);
-	if (retval)
-		goto failed_usb_serial_register;
-	retval = usb_register(&hp49gp_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&hp49gp_device);
-failed_usb_serial_register:
-	return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+	&hp49gp_device, NULL
+};
 
-static void __exit hp49gp_exit(void)
-{
-	usb_deregister(&hp49gp_driver);
-	usb_serial_deregister(&hp49gp_device);
-}
-
-module_init(hp49gp_init);
-module_exit(hp49gp_exit);
+module_usb_serial_driver(hp49gp_driver, serial_drivers);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 0497575..323e872 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -193,7 +193,8 @@
 /* local variables */
 static bool debug;
 
-static atomic_t CmdUrbs;	/* Number of outstanding Command Write Urbs */
+/* Number of outstanding Command Write Urbs */
+static atomic_t CmdUrbs = ATOMIC_INIT(0);
 
 
 /* local function prototypes */
@@ -1286,7 +1287,7 @@
 	count = fifo->count;
 	buffer = kmalloc(count+2, GFP_ATOMIC);
 	if (buffer == NULL) {
-		dev_err(&edge_port->port->dev,
+		dev_err_console(edge_port->port,
 				"%s - no more kernel memory...\n", __func__);
 		edge_port->write_in_progress = false;
 		goto exit_send;
@@ -1331,7 +1332,7 @@
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
 		/* something went wrong */
-		dev_err(&edge_port->port->dev,
+		dev_err_console(edge_port->port,
 			"%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n",
 				__func__, status);
 		edge_port->write_in_progress = false;
@@ -3180,65 +3181,8 @@
 	kfree(edge_serial);
 }
 
+module_usb_serial_driver(io_driver, serial_drivers);
 
-/****************************************************************************
- * edgeport_init
- *	This is called by the module subsystem, or on startup to initialize us
- ****************************************************************************/
-static int __init edgeport_init(void)
-{
-	int retval;
-
-	retval = usb_serial_register(&edgeport_2port_device);
-	if (retval)
-		goto failed_2port_device_register;
-	retval = usb_serial_register(&edgeport_4port_device);
-	if (retval)
-		goto failed_4port_device_register;
-	retval = usb_serial_register(&edgeport_8port_device);
-	if (retval)
-		goto failed_8port_device_register;
-	retval = usb_serial_register(&epic_device);
-	if (retval)
-		goto failed_epic_device_register;
-	retval = usb_register(&io_driver);
-	if (retval)
-		goto failed_usb_register;
-	atomic_set(&CmdUrbs, 0);
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-
-failed_usb_register:
-	usb_serial_deregister(&epic_device);
-failed_epic_device_register:
-	usb_serial_deregister(&edgeport_8port_device);
-failed_8port_device_register:
-	usb_serial_deregister(&edgeport_4port_device);
-failed_4port_device_register:
-	usb_serial_deregister(&edgeport_2port_device);
-failed_2port_device_register:
-	return retval;
-}
-
-
-/****************************************************************************
- * edgeport_exit
- *	Called when the driver is about to be unloaded.
- ****************************************************************************/
-static void __exit edgeport_exit (void)
-{
-	usb_deregister(&io_driver);
-	usb_serial_deregister(&edgeport_2port_device);
-	usb_serial_deregister(&edgeport_4port_device);
-	usb_serial_deregister(&edgeport_8port_device);
-	usb_serial_deregister(&epic_device);
-}
-
-module_init(edgeport_init);
-module_exit(edgeport_exit);
-
-/* Module information */
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index 178b22e..d0e7c9a 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -100,7 +100,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
-	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver edgeport_2port_device = {
@@ -109,7 +108,6 @@
 		.name		= "edgeport_2",
 	},
 	.description		= "Edgeport 2 port adapter",
-	.usb_driver		= &io_driver,
 	.id_table		= edgeport_2port_id_table,
 	.num_ports		= 2,
 	.open			= edge_open,
@@ -139,7 +137,6 @@
 		.name		= "edgeport_4",
 	},
 	.description		= "Edgeport 4 port adapter",
-	.usb_driver		= &io_driver,
 	.id_table		= edgeport_4port_id_table,
 	.num_ports		= 4,
 	.open			= edge_open,
@@ -169,7 +166,6 @@
 		.name		= "edgeport_8",
 	},
 	.description		= "Edgeport 8 port adapter",
-	.usb_driver		= &io_driver,
 	.id_table		= edgeport_8port_id_table,
 	.num_ports		= 8,
 	.open			= edge_open,
@@ -199,7 +195,6 @@
 		.name		= "epic",
 	},
 	.description		= "EPiC device",
-	.usb_driver		= &io_driver,
 	.id_table		= Epic_port_id_table,
 	.num_ports		= 1,
 	.open			= edge_open,
@@ -223,5 +218,10 @@
 	.write_bulk_callback	= edge_bulk_out_data_callback,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&edgeport_2port_device, &edgeport_4port_device,
+	&edgeport_8port_device, &epic_device, NULL
+};
+
 #endif
 
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 5818bfc..40a95a7 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -202,7 +202,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
-	.no_dynamic_id = 	1,
 };
 
 
@@ -1817,7 +1816,7 @@
 		    __func__, status);
 		return;
 	default:
-		dev_err(&urb->dev->dev, "%s - nonzero write bulk status "
+		dev_err_console(port, "%s - nonzero write bulk status "
 			"received: %d\n", __func__, status);
 	}
 
@@ -2111,7 +2110,7 @@
 	/* send the data out the bulk port */
 	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 	if (result) {
-		dev_err(&port->dev,
+		dev_err_console(port,
 			"%s - failed submitting write urb, error %d\n",
 				__func__, result);
 		edge_port->ep_write_urb_in_use = 0;
@@ -2725,7 +2724,6 @@
 		.name		= "edgeport_ti_1",
 	},
 	.description		= "Edgeport TI 1 port adapter",
-	.usb_driver		= &io_driver,
 	.id_table		= edgeport_1port_id_table,
 	.num_ports		= 1,
 	.open			= edge_open,
@@ -2757,7 +2755,6 @@
 		.name		= "edgeport_ti_2",
 	},
 	.description		= "Edgeport TI 2 port adapter",
-	.usb_driver		= &io_driver,
 	.id_table		= edgeport_2port_id_table,
 	.num_ports		= 2,
 	.open			= edge_open,
@@ -2782,41 +2779,12 @@
 	.write_bulk_callback	= edge_bulk_out_callback,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&edgeport_1port_device, &edgeport_2port_device, NULL
+};
 
-static int __init edgeport_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&edgeport_1port_device);
-	if (retval)
-		goto failed_1port_device_register;
-	retval = usb_serial_register(&edgeport_2port_device);
-	if (retval)
-		goto failed_2port_device_register;
-	retval = usb_register(&io_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&edgeport_2port_device);
-failed_2port_device_register:
-	usb_serial_deregister(&edgeport_1port_device);
-failed_1port_device_register:
-	return retval;
-}
+module_usb_serial_driver(io_driver, serial_drivers);
 
-static void __exit edgeport_exit(void)
-{
-	usb_deregister(&io_driver);
-	usb_serial_deregister(&edgeport_1port_device);
-	usb_serial_deregister(&edgeport_2port_device);
-}
-
-module_init(edgeport_init);
-module_exit(edgeport_exit);
-
-/* Module information */
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 06053a9..10c02b8 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -510,7 +510,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	ipaq_id_table,
-	.no_dynamic_id =	1,
 };
 
 
@@ -521,7 +520,6 @@
 		.name =		"ipaq",
 	},
 	.description =		"PocketPC PDA",
-	.usb_driver =		&ipaq_driver,
 	.id_table =		ipaq_id_table,
 	.bulk_in_size =		256,
 	.bulk_out_size =	256,
@@ -530,6 +528,10 @@
 	.calc_num_ports =	ipaq_calc_num_ports,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&ipaq_device, NULL
+};
+
 static int ipaq_open(struct tty_struct *tty,
 			struct usb_serial_port *port)
 {
@@ -624,30 +626,22 @@
 static int __init ipaq_init(void)
 {
 	int retval;
-	retval = usb_serial_register(&ipaq_device);
-	if (retval)
-		goto failed_usb_serial_register;
+
 	if (vendor) {
 		ipaq_id_table[0].idVendor = vendor;
 		ipaq_id_table[0].idProduct = product;
 	}
-	retval = usb_register(&ipaq_driver);
-	if (retval)
-		goto failed_usb_register;
 
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&ipaq_device);
-failed_usb_serial_register:
+	retval = usb_serial_register_drivers(&ipaq_driver, serial_drivers);
+	if (retval == 0)
+		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+			       DRIVER_DESC "\n");
 	return retval;
 }
 
 static void __exit ipaq_exit(void)
 {
-	usb_deregister(&ipaq_driver);
-	usb_serial_deregister(&ipaq_device);
+	usb_serial_deregister_drivers(&ipaq_driver, serial_drivers);
 }
 
 
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 6f9356f..76a0640 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -144,7 +144,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	usb_ipw_ids,
-	.no_dynamic_id = 	1,
 };
 
 static bool debug;
@@ -318,7 +317,6 @@
 		.name =		"ipw",
 	},
 	.description =		"IPWireless converter",
-	.usb_driver =		&usb_ipw_driver,
 	.id_table =		usb_ipw_ids,
 	.num_ports =		1,
 	.disconnect =		usb_wwan_disconnect,
@@ -331,33 +329,11 @@
 	.write =		usb_wwan_write,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&ipw_device, NULL
+};
 
-
-static int __init usb_ipw_init(void)
-{
-	int retval;
-
-	retval = usb_serial_register(&ipw_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&usb_ipw_driver);
-	if (retval) {
-		usb_serial_deregister(&ipw_device);
-		return retval;
-	}
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-}
-
-static void __exit usb_ipw_exit(void)
-{
-	usb_deregister(&usb_ipw_driver);
-	usb_serial_deregister(&ipw_device);
-}
-
-module_init(usb_ipw_init);
-module_exit(usb_ipw_exit);
+module_usb_serial_driver(usb_ipw_driver, serial_drivers);
 
 /* Module information */
 MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 84a396e..84965cd 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -82,7 +82,6 @@
 	.probe		= usb_serial_probe,
 	.disconnect	= usb_serial_disconnect,
 	.id_table	= ir_id_table,
-	.no_dynamic_id	= 1,
 };
 
 static struct usb_serial_driver ir_device = {
@@ -91,7 +90,6 @@
 		.name	= "ir-usb",
 	},
 	.description		= "IR Dongle",
-	.usb_driver		= &ir_driver,
 	.id_table		= ir_id_table,
 	.num_ports		= 1,
 	.set_termios		= ir_set_termios,
@@ -101,6 +99,10 @@
 	.process_read_urb	= ir_process_read_urb,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&ir_device, NULL
+};
+
 static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc)
 {
 	dbg("bLength=%x", desc->bLength);
@@ -445,30 +447,16 @@
 		ir_device.bulk_out_size = buffer_size;
 	}
 
-	retval = usb_serial_register(&ir_device);
-	if (retval)
-		goto failed_usb_serial_register;
-
-	retval = usb_register(&ir_driver);
-	if (retval)
-		goto failed_usb_register;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-
-	return 0;
-
-failed_usb_register:
-	usb_serial_deregister(&ir_device);
-
-failed_usb_serial_register:
+	retval = usb_serial_register_drivers(&ir_driver, serial_drivers);
+	if (retval == 0)
+		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+			       DRIVER_DESC "\n");
 	return retval;
 }
 
 static void __exit ir_exit(void)
 {
-	usb_deregister(&ir_driver);
-	usb_serial_deregister(&ir_device);
+	usb_serial_deregister_drivers(&ir_driver, serial_drivers);
 }
 
 
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 3077a44..f2192d5 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -56,7 +56,6 @@
 	.probe = usb_serial_probe,
 	.disconnect = usb_serial_disconnect,
 	.id_table = id_table,
-	.no_dynamic_id = 1,
 };
 
 /* turbo parameter */
@@ -1274,7 +1273,6 @@
 		   .name = "iuu_phoenix",
 		   },
 	.id_table = id_table,
-	.usb_driver = &iuu_driver,
 	.num_ports = 1,
 	.bulk_in_size = 512,
 	.bulk_out_size = 512,
@@ -1292,32 +1290,11 @@
 	.release = iuu_release,
 };
 
-static int __init iuu_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&iuu_device);
-	if (retval)
-		goto failed_usb_serial_register;
-	retval = usb_register(&iuu_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&iuu_device);
-failed_usb_serial_register:
-	return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+	&iuu_device, NULL
+};
 
-static void __exit iuu_exit(void)
-{
-	usb_deregister(&iuu_driver);
-	usb_serial_deregister(&iuu_device);
-}
-
-module_init(iuu_init);
-module_exit(iuu_exit);
+module_usb_serial_driver(iuu_driver, serial_drivers);
 
 MODULE_AUTHOR("Alain Degreffe eczema@ecze.com");
 
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 4cc36c7..a39ddd1 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -130,53 +130,7 @@
 #include "keyspan_usa67msg.h"
 
 
-/* Functions used by new usb-serial code. */
-static int __init keyspan_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&keyspan_pre_device);
-	if (retval)
-		goto failed_pre_device_register;
-	retval = usb_serial_register(&keyspan_1port_device);
-	if (retval)
-		goto failed_1port_device_register;
-	retval = usb_serial_register(&keyspan_2port_device);
-	if (retval)
-		goto failed_2port_device_register;
-	retval = usb_serial_register(&keyspan_4port_device);
-	if (retval)
-		goto failed_4port_device_register;
-	retval = usb_register(&keyspan_driver);
-	if (retval)
-		goto failed_usb_register;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&keyspan_4port_device);
-failed_4port_device_register:
-	usb_serial_deregister(&keyspan_2port_device);
-failed_2port_device_register:
-	usb_serial_deregister(&keyspan_1port_device);
-failed_1port_device_register:
-	usb_serial_deregister(&keyspan_pre_device);
-failed_pre_device_register:
-	return retval;
-}
-
-static void __exit keyspan_exit(void)
-{
-	usb_deregister(&keyspan_driver);
-	usb_serial_deregister(&keyspan_pre_device);
-	usb_serial_deregister(&keyspan_1port_device);
-	usb_serial_deregister(&keyspan_2port_device);
-	usb_serial_deregister(&keyspan_4port_device);
-}
-
-module_init(keyspan_init);
-module_exit(keyspan_exit);
+module_usb_serial_driver(keyspan_driver, serial_drivers);
 
 static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
 {
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 13fa1d1..622853c 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -492,7 +492,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	keyspan_ids_combined,
-	.no_dynamic_id = 	1,
 };
 
 /* usb_device_id table for the pre-firmware download keyspan devices */
@@ -545,7 +544,6 @@
 		.name		= "keyspan_no_firm",
 	},
 	.description		= "Keyspan - (without firmware)",
-	.usb_driver		= &keyspan_driver,
 	.id_table		= keyspan_pre_ids,
 	.num_ports		= 1,
 	.attach			= keyspan_fake_startup,
@@ -557,7 +555,6 @@
 		.name		= "keyspan_1",
 	},
 	.description		= "Keyspan 1 port adapter",
-	.usb_driver		= &keyspan_driver,
 	.id_table		= keyspan_1port_ids,
 	.num_ports		= 1,
 	.open			= keyspan_open,
@@ -580,7 +577,6 @@
 		.name		= "keyspan_2",
 	},
 	.description		= "Keyspan 2 port adapter",
-	.usb_driver		= &keyspan_driver,
 	.id_table		= keyspan_2port_ids,
 	.num_ports		= 2,
 	.open			= keyspan_open,
@@ -603,7 +599,6 @@
 		.name		= "keyspan_4",
 	},
 	.description		= "Keyspan 4 port adapter",
-	.usb_driver		= &keyspan_driver,
 	.id_table		= keyspan_4port_ids,
 	.num_ports		= 4,
 	.open			= keyspan_open,
@@ -620,4 +615,9 @@
 	.release		= keyspan_release,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&keyspan_pre_device, &keyspan_1port_device,
+	&keyspan_2port_device, &keyspan_4port_device, NULL
+};
+
 #endif
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 7c62a70..693bcdf 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -91,7 +91,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
-	.no_dynamic_id = 	1,
 };
 
 static const struct usb_device_id id_table_std[] = {
@@ -779,7 +778,6 @@
 		.name =		"keyspan_pda_pre",
 	},
 	.description =		"Keyspan PDA - (prerenumeration)",
-	.usb_driver = 		&keyspan_pda_driver,
 	.id_table =		id_table_fake,
 	.num_ports =		1,
 	.attach =		keyspan_pda_fake_startup,
@@ -793,7 +791,6 @@
 		.name =		"xircom_no_firm",
 	},
 	.description =		"Xircom / Entregra PGS - (prerenumeration)",
-	.usb_driver = 		&keyspan_pda_driver,
 	.id_table =		id_table_fake_xircom,
 	.num_ports =		1,
 	.attach =		keyspan_pda_fake_startup,
@@ -806,7 +803,6 @@
 		.name =		"keyspan_pda",
 	},
 	.description =		"Keyspan PDA",
-	.usb_driver = 		&keyspan_pda_driver,
 	.id_table =		id_table_std,
 	.num_ports =		1,
 	.dtr_rts =		keyspan_pda_dtr_rts,
@@ -827,61 +823,18 @@
 	.release =		keyspan_pda_release,
 };
 
-
-static int __init keyspan_pda_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&keyspan_pda_device);
-	if (retval)
-		goto failed_pda_register;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&keyspan_pda_device,
 #ifdef KEYSPAN
-	retval = usb_serial_register(&keyspan_pda_fake_device);
-	if (retval)
-		goto failed_pda_fake_register;
+	&keyspan_pda_fake_device,
 #endif
 #ifdef XIRCOM
-	retval = usb_serial_register(&xircom_pgs_fake_device);
-	if (retval)
-		goto failed_xircom_register;
+	&xircom_pgs_fake_device,
 #endif
-	retval = usb_register(&keyspan_pda_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-#ifdef XIRCOM
-	usb_serial_deregister(&xircom_pgs_fake_device);
-failed_xircom_register:
-#endif /* XIRCOM */
-#ifdef KEYSPAN
-	usb_serial_deregister(&keyspan_pda_fake_device);
-#endif
-#ifdef KEYSPAN
-failed_pda_fake_register:
-#endif
-	usb_serial_deregister(&keyspan_pda_device);
-failed_pda_register:
-	return retval;
-}
+	NULL
+};
 
-
-static void __exit keyspan_pda_exit(void)
-{
-	usb_deregister(&keyspan_pda_driver);
-	usb_serial_deregister(&keyspan_pda_device);
-#ifdef KEYSPAN
-	usb_serial_deregister(&keyspan_pda_fake_device);
-#endif
-#ifdef XIRCOM
-	usb_serial_deregister(&xircom_pgs_fake_device);
-#endif
-}
-
-
-module_init(keyspan_pda_init);
-module_exit(keyspan_pda_exit);
+module_usb_serial_driver(keyspan_pda_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -889,4 +842,3 @@
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
-
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index fc064e1..10f0540 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -91,7 +91,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id =	1,
 };
 
 static struct usb_serial_driver kl5kusb105d_device = {
@@ -100,7 +99,6 @@
 		.name =		"kl5kusb105d",
 	},
 	.description =		"KL5KUSB105D / PalmConnect",
-	.usb_driver =		&kl5kusb105d_driver,
 	.id_table =		id_table,
 	.num_ports =		1,
 	.bulk_out_size =	64,
@@ -118,6 +116,10 @@
 	.prepare_write_buffer =	klsi_105_prepare_write_buffer,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&kl5kusb105d_device, NULL
+};
+
 struct klsi_105_port_settings {
 	__u8	pktlen;		/* always 5, it seems */
 	__u8	baudrate;
@@ -690,40 +692,11 @@
 	return retval;
 }
 
-
-static int __init klsi_105_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&kl5kusb105d_device);
-	if (retval)
-		goto failed_usb_serial_register;
-	retval = usb_register(&kl5kusb105d_driver);
-	if (retval)
-		goto failed_usb_register;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&kl5kusb105d_device);
-failed_usb_serial_register:
-	return retval;
-}
-
-static void __exit klsi_105_exit(void)
-{
-	usb_deregister(&kl5kusb105d_driver);
-	usb_serial_deregister(&kl5kusb105d_device);
-}
-
-
-module_init(klsi_105_init);
-module_exit(klsi_105_exit);
+module_usb_serial_driver(kl5kusb105d_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "enable extensive debugging messages");
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index a92a3ef..4a9a75e 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -90,7 +90,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id = 	1,
 };
 
 
@@ -100,7 +99,6 @@
 		.name =		"kobil",
 	},
 	.description =		"KOBIL USB smart card terminal",
-	.usb_driver = 		&kobil_driver,
 	.id_table =		id_table,
 	.num_ports =		1,
 	.attach =		kobil_startup,
@@ -117,6 +115,9 @@
 	.read_int_callback =	kobil_read_int_callback,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&kobil_device, NULL
+};
 
 struct kobil_private {
 	int write_int_endpoint_address;
@@ -682,35 +683,7 @@
 	}
 }
 
-static int __init kobil_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&kobil_device);
-	if (retval)
-		goto failed_usb_serial_register;
-	retval = usb_register(&kobil_driver);
-	if (retval)
-		goto failed_usb_register;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&kobil_device);
-failed_usb_serial_register:
-	return retval;
-}
-
-
-static void __exit kobil_exit(void)
-{
-	usb_deregister(&kobil_driver);
-	usb_serial_deregister(&kobil_device);
-}
-
-module_init(kobil_init);
-module_exit(kobil_exit);
+module_usb_serial_driver(kobil_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 27fa9c8..6edd261 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -88,7 +88,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
-	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver mct_u232_device = {
@@ -97,7 +96,6 @@
 		.name =		"mct_u232",
 	},
 	.description =	     "MCT U232",
-	.usb_driver = 	     &mct_u232_driver,
 	.id_table =	     id_table_combined,
 	.num_ports =	     1,
 	.open =		     mct_u232_open,
@@ -116,6 +114,10 @@
 	.get_icount =        mct_u232_get_icount,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&mct_u232_device, NULL
+};
+
 struct mct_u232_private {
 	spinlock_t lock;
 	unsigned int	     control_state; /* Modem Line Setting (TIOCM) */
@@ -904,33 +906,7 @@
 	return 0;
 }
 
-static int __init mct_u232_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&mct_u232_device);
-	if (retval)
-		goto failed_usb_serial_register;
-	retval = usb_register(&mct_u232_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&mct_u232_device);
-failed_usb_serial_register:
-	return retval;
-}
-
-
-static void __exit mct_u232_exit(void)
-{
-	usb_deregister(&mct_u232_driver);
-	usb_serial_deregister(&mct_u232_device);
-}
-
-module_init(mct_u232_init);
-module_exit(mct_u232_exit);
+module_usb_serial_driver(mct_u232_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c
new file mode 100644
index 0000000..6e1622f
--- /dev/null
+++ b/drivers/usb/serial/metro-usb.c
@@ -0,0 +1,402 @@
+/*
+  Some of this code is credited to Linux USB open source files that are
+  distributed with Linux.
+
+  Copyright:	2007 Metrologic Instruments. All rights reserved.
+  Copyright:	2011 Azimut Ltd. <http://azimutrzn.ru/>
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/uaccess.h>
+#include <linux/usb/serial.h>
+
+/* Version Information */
+#define DRIVER_VERSION "v1.2.0.0"
+#define DRIVER_DESC "Metrologic Instruments Inc. - USB-POS driver"
+
+/* Product information. */
+#define FOCUS_VENDOR_ID			0x0C2E
+#define FOCUS_PRODUCT_ID		0x0720
+#define FOCUS_PRODUCT_ID_UNI		0x0710
+
+#define METROUSB_SET_REQUEST_TYPE	0x40
+#define METROUSB_SET_MODEM_CTRL_REQUEST	10
+#define METROUSB_SET_BREAK_REQUEST	0x40
+#define METROUSB_MCR_NONE		0x08	/* Deactivate DTR and RTS. */
+#define METROUSB_MCR_RTS		0x0a	/* Activate RTS. */
+#define METROUSB_MCR_DTR		0x09	/* Activate DTR. */
+#define WDR_TIMEOUT			5000	/* default urb timeout. */
+
+/* Private data structure. */
+struct metrousb_private {
+	spinlock_t lock;
+	int throttled;
+	unsigned long control_state;
+};
+
+/* Device table list. */
+static struct usb_device_id id_table[] = {
+	{ USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID) },
+	{ USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) },
+	{ }, /* Terminating entry. */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/* Input parameter constants. */
+static bool debug;
+
+static void metrousb_read_int_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = urb->context;
+	struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
+	struct tty_struct *tty;
+	unsigned char *data = urb->transfer_buffer;
+	int throttled = 0;
+	int result = 0;
+	unsigned long flags = 0;
+
+	dev_dbg(&port->dev, "%s\n", __func__);
+
+	switch (urb->status) {
+	case 0:
+		/* Success status, read from the port. */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* urb has been terminated. */
+		dev_dbg(&port->dev,
+			"%s - urb shutting down, error code=%d\n",
+			__func__, result);
+		return;
+	default:
+		dev_dbg(&port->dev,
+			"%s - non-zero urb received, error code=%d\n",
+			__func__, result);
+		goto exit;
+	}
+
+
+	/* Set the data read from the usb port into the serial port buffer. */
+	tty = tty_port_tty_get(&port->port);
+	if (!tty) {
+		dev_dbg(&port->dev, "%s - bad tty pointer - exiting\n",
+			__func__);
+		return;
+	}
+
+	if (tty && urb->actual_length) {
+		/* Loop through the data copying each byte to the tty layer. */
+		tty_insert_flip_string(tty, data, urb->actual_length);
+
+		/* Force the data to the tty layer. */
+		tty_flip_buffer_push(tty);
+	}
+	tty_kref_put(tty);
+
+	/* Set any port variables. */
+	spin_lock_irqsave(&metro_priv->lock, flags);
+	throttled = metro_priv->throttled;
+	spin_unlock_irqrestore(&metro_priv->lock, flags);
+
+	/* Continue trying to read if set. */
+	if (!throttled) {
+		usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
+				 usb_rcvintpipe(port->serial->dev, port->interrupt_in_endpointAddress),
+				 port->interrupt_in_urb->transfer_buffer,
+				 port->interrupt_in_urb->transfer_buffer_length,
+				 metrousb_read_int_callback, port, 1);
+
+		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+
+		if (result)
+			dev_dbg(&port->dev,
+				"%s - failed submitting interrupt in urb, error code=%d\n",
+				__func__, result);
+	}
+	return;
+
+exit:
+	/* Try to resubmit the urb. */
+	result = usb_submit_urb(urb, GFP_ATOMIC);
+	if (result)
+		dev_dbg(&port->dev,
+			"%s - failed submitting interrupt in urb, error code=%d\n",
+			__func__, result);
+}
+
+static void metrousb_cleanup(struct usb_serial_port *port)
+{
+	dev_dbg(&port->dev, "%s\n", __func__);
+
+	if (port->serial->dev) {
+		/* Shutdown any interrupt in urbs. */
+		if (port->interrupt_in_urb) {
+			usb_unlink_urb(port->interrupt_in_urb);
+			usb_kill_urb(port->interrupt_in_urb);
+		}
+	}
+}
+
+static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
+{
+	struct usb_serial *serial = port->serial;
+	struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
+	unsigned long flags = 0;
+	int result = 0;
+
+	dev_dbg(&port->dev, "%s\n", __func__);
+
+	/* Make sure the urb is initialized. */
+	if (!port->interrupt_in_urb) {
+		dev_dbg(&port->dev, "%s - interrupt urb not initialized\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	/* Set the private data information for the port. */
+	spin_lock_irqsave(&metro_priv->lock, flags);
+	metro_priv->control_state = 0;
+	metro_priv->throttled = 0;
+	spin_unlock_irqrestore(&metro_priv->lock, flags);
+
+	/*
+	 * Force low_latency on so that our tty_push actually forces the data
+	 * through, otherwise it is scheduled, and with high data rates (like
+	 * with OHCI) data can get lost.
+	 */
+	if (tty)
+		tty->low_latency = 1;
+
+	/* Clear the urb pipe. */
+	usb_clear_halt(serial->dev, port->interrupt_in_urb->pipe);
+
+	/* Start reading from the device */
+	usb_fill_int_urb(port->interrupt_in_urb, serial->dev,
+			  usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),
+			   port->interrupt_in_urb->transfer_buffer,
+			   port->interrupt_in_urb->transfer_buffer_length,
+			   metrousb_read_int_callback, port, 1);
+	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+
+	if (result) {
+		dev_dbg(&port->dev,
+			"%s - failed submitting interrupt in urb, error code=%d\n",
+			__func__, result);
+		goto exit;
+	}
+
+	dev_dbg(&port->dev, "%s - port open\n", __func__);
+exit:
+	return result;
+}
+
+static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int control_state)
+{
+	int retval = 0;
+	unsigned char mcr = METROUSB_MCR_NONE;
+
+	dev_dbg(&serial->dev->dev, "%s - control state = %d\n",
+		__func__, control_state);
+
+	/* Set the modem control value. */
+	if (control_state & TIOCM_DTR)
+		mcr |= METROUSB_MCR_DTR;
+	if (control_state & TIOCM_RTS)
+		mcr |= METROUSB_MCR_RTS;
+
+	/* Send the command to the usb port. */
+	retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+				METROUSB_SET_REQUEST_TYPE, METROUSB_SET_MODEM_CTRL_REQUEST,
+				control_state, 0, NULL, 0, WDR_TIMEOUT);
+	if (retval < 0)
+		dev_dbg(&serial->dev->dev,
+			"%s - set modem ctrl=0x%x failed, error code=%d\n",
+			__func__, mcr, retval);
+
+	return retval;
+}
+
+static void metrousb_shutdown(struct usb_serial *serial)
+{
+	int i = 0;
+
+	dev_dbg(&serial->dev->dev, "%s\n", __func__);
+
+	/* Stop reading and writing on all ports. */
+	for (i = 0; i < serial->num_ports; ++i) {
+		/* Close any open urbs. */
+		metrousb_cleanup(serial->port[i]);
+
+		/* Free memory. */
+		kfree(usb_get_serial_port_data(serial->port[i]));
+		usb_set_serial_port_data(serial->port[i], NULL);
+
+		dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n",
+			__func__, serial->port[i]->number);
+	}
+}
+
+static int metrousb_startup(struct usb_serial *serial)
+{
+	struct metrousb_private *metro_priv;
+	struct usb_serial_port *port;
+	int i = 0;
+
+	dev_dbg(&serial->dev->dev, "%s\n", __func__);
+
+	/* Loop through the serial ports setting up the private structures.
+	 * Currently we only use one port. */
+	for (i = 0; i < serial->num_ports; ++i) {
+		port = serial->port[i];
+
+		/* Declare memory. */
+		metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL);
+		if (!metro_priv)
+			return -ENOMEM;
+
+		/* Initialize memory. */
+		spin_lock_init(&metro_priv->lock);
+		usb_set_serial_port_data(port, metro_priv);
+
+		dev_dbg(&serial->dev->dev, "%s - port number=%d\n ",
+			__func__, port->number);
+	}
+
+	return 0;
+}
+
+static void metrousb_throttle(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
+	unsigned long flags = 0;
+
+	dev_dbg(tty->dev, "%s\n", __func__);
+
+	/* Set the private information for the port to stop reading data. */
+	spin_lock_irqsave(&metro_priv->lock, flags);
+	metro_priv->throttled = 1;
+	spin_unlock_irqrestore(&metro_priv->lock, flags);
+}
+
+static int metrousb_tiocmget(struct tty_struct *tty)
+{
+	unsigned long control_state = 0;
+	struct usb_serial_port *port = tty->driver_data;
+	struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
+	unsigned long flags = 0;
+
+	dev_dbg(tty->dev, "%s\n", __func__);
+
+	spin_lock_irqsave(&metro_priv->lock, flags);
+	control_state = metro_priv->control_state;
+	spin_unlock_irqrestore(&metro_priv->lock, flags);
+
+	return control_state;
+}
+
+static int metrousb_tiocmset(struct tty_struct *tty,
+			     unsigned int set, unsigned int clear)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct usb_serial *serial = port->serial;
+	struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
+	unsigned long flags = 0;
+	unsigned long control_state = 0;
+
+	dev_dbg(tty->dev, "%s - set=%d, clear=%d\n", __func__, set, clear);
+
+	spin_lock_irqsave(&metro_priv->lock, flags);
+	control_state = metro_priv->control_state;
+
+	/* Set the RTS and DTR values. */
+	if (set & TIOCM_RTS)
+		control_state |= TIOCM_RTS;
+	if (set & TIOCM_DTR)
+		control_state |= TIOCM_DTR;
+	if (clear & TIOCM_RTS)
+		control_state &= ~TIOCM_RTS;
+	if (clear & TIOCM_DTR)
+		control_state &= ~TIOCM_DTR;
+
+	metro_priv->control_state = control_state;
+	spin_unlock_irqrestore(&metro_priv->lock, flags);
+	return metrousb_set_modem_ctrl(serial, control_state);
+}
+
+static void metrousb_unthrottle(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
+	unsigned long flags = 0;
+	int result = 0;
+
+	dev_dbg(tty->dev, "%s\n", __func__);
+
+	/* Set the private information for the port to resume reading data. */
+	spin_lock_irqsave(&metro_priv->lock, flags);
+	metro_priv->throttled = 0;
+	spin_unlock_irqrestore(&metro_priv->lock, flags);
+
+	/* Submit the urb to read from the port. */
+	port->interrupt_in_urb->dev = port->serial->dev;
+	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+	if (result)
+		dev_dbg(tty->dev,
+			"failed submitting interrupt in urb error code=%d\n",
+			result);
+}
+
+static struct usb_driver metrousb_driver = {
+	.name =		"metro-usb",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table
+};
+
+static struct usb_serial_driver metrousb_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"metro-usb",
+	},
+	.description		= "Metrologic USB to serial converter.",
+	.id_table		= id_table,
+	.num_ports		= 1,
+	.open			= metrousb_open,
+	.close			= metrousb_cleanup,
+	.read_int_callback	= metrousb_read_int_callback,
+	.attach			= metrousb_startup,
+	.release		= metrousb_shutdown,
+	.throttle		= metrousb_throttle,
+	.unthrottle		= metrousb_unthrottle,
+	.tiocmget		= metrousb_tiocmget,
+	.tiocmset		= metrousb_tiocmset,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+	&metrousb_device,
+	NULL,
+};
+
+module_usb_serial_driver(metrousb_driver, serial_drivers);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Philip Nicastro");
+MODULE_AUTHOR("Aleksey Babahin <tamerlan311@gmail.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+
+/* Module input parameters */
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Print debug info (bool 1=on, 0=off)");
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 4554ee4..bdce820 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1294,7 +1294,7 @@
 		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
 					       GFP_KERNEL);
 		if (urb->transfer_buffer == NULL) {
-			dev_err(&port->dev, "%s no more kernel memory...\n",
+			dev_err_console(port, "%s no more kernel memory...\n",
 				__func__);
 			goto exit;
 		}
@@ -1315,7 +1315,7 @@
 	/* send it down the pipe */
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
-		dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+		dev_err_console(port, "%s - usb_submit_urb(write bulk) failed "
 			"with status = %d\n", __func__, status);
 		bytes_sent = status;
 		goto exit;
@@ -2169,7 +2169,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	moschip_port_id_table,
-	.no_dynamic_id =	1,
 };
 
 static struct usb_serial_driver moschip7720_2port_driver = {
@@ -2178,7 +2177,6 @@
 		.name =		"moschip7720",
 	},
 	.description		= "Moschip 2 port adapter",
-	.usb_driver		= &usb_driver,
 	.id_table		= moschip_port_id_table,
 	.calc_num_ports		= mos77xx_calc_num_ports,
 	.open			= mos7720_open,
@@ -2201,44 +2199,12 @@
 	.read_int_callback	= NULL  /* dynamically assigned in probe() */
 };
 
-static int __init moschip7720_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&moschip7720_2port_driver, NULL
+};
 
-	dbg("%s: Entering ..........", __func__);
+module_usb_serial_driver(usb_driver, serial_drivers);
 
-	/* Register with the usb serial */
-	retval = usb_serial_register(&moschip7720_2port_driver);
-	if (retval)
-		goto failed_port_device_register;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-
-	/* Register with the usb */
-	retval = usb_register(&usb_driver);
-	if (retval)
-		goto failed_usb_register;
-
-	return 0;
-
-failed_usb_register:
-	usb_serial_deregister(&moschip7720_2port_driver);
-
-failed_port_device_register:
-	return retval;
-}
-
-static void __exit moschip7720_exit(void)
-{
-	usb_deregister(&usb_driver);
-	usb_serial_deregister(&moschip7720_2port_driver);
-}
-
-module_init(moschip7720_init);
-module_exit(moschip7720_exit);
-
-/* Module information */
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 03b5e249..c526550 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -174,6 +174,7 @@
 
 #define CLK_MULTI_REGISTER         ((__u16)(0x02))
 #define CLK_START_VALUE_REGISTER   ((__u16)(0x03))
+#define GPIO_REGISTER              ((__u16)(0x07))
 
 #define SERIAL_LCR_DLAB            ((__u16)(0x0080))
 
@@ -1101,14 +1102,25 @@
 	mos7840_port->read_urb = port->read_urb;
 
 	/* set up our bulk in urb */
-
-	usb_fill_bulk_urb(mos7840_port->read_urb,
-			  serial->dev,
-			  usb_rcvbulkpipe(serial->dev,
-					  port->bulk_in_endpointAddress),
-			  port->bulk_in_buffer,
-			  mos7840_port->read_urb->transfer_buffer_length,
-			  mos7840_bulk_in_callback, mos7840_port);
+	if ((serial->num_ports == 2)
+		&& ((((__u16)port->number -
+			(__u16)(port->serial->minor)) % 2) != 0)) {
+		usb_fill_bulk_urb(mos7840_port->read_urb,
+			serial->dev,
+			usb_rcvbulkpipe(serial->dev,
+				(port->bulk_in_endpointAddress) + 2),
+			port->bulk_in_buffer,
+			mos7840_port->read_urb->transfer_buffer_length,
+			mos7840_bulk_in_callback, mos7840_port);
+	} else {
+		usb_fill_bulk_urb(mos7840_port->read_urb,
+			serial->dev,
+			usb_rcvbulkpipe(serial->dev,
+				port->bulk_in_endpointAddress),
+			port->bulk_in_buffer,
+			mos7840_port->read_urb->transfer_buffer_length,
+			mos7840_bulk_in_callback, mos7840_port);
+	}
 
 	dbg("mos7840_open: bulkin endpoint is %d",
 	    port->bulk_in_endpointAddress);
@@ -1509,7 +1521,7 @@
 		    kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
 
 		if (urb->transfer_buffer == NULL) {
-			dev_err(&port->dev, "%s no more kernel memory...\n",
+			dev_err_console(port, "%s no more kernel memory...\n",
 				__func__);
 			goto exit;
 		}
@@ -1519,13 +1531,25 @@
 	memcpy(urb->transfer_buffer, current_position, transfer_size);
 
 	/* fill urb with data and submit  */
-	usb_fill_bulk_urb(urb,
-			  serial->dev,
-			  usb_sndbulkpipe(serial->dev,
-					  port->bulk_out_endpointAddress),
-			  urb->transfer_buffer,
-			  transfer_size,
-			  mos7840_bulk_out_data_callback, mos7840_port);
+	if ((serial->num_ports == 2)
+		&& ((((__u16)port->number -
+			(__u16)(port->serial->minor)) % 2) != 0)) {
+		usb_fill_bulk_urb(urb,
+			serial->dev,
+			usb_sndbulkpipe(serial->dev,
+				(port->bulk_out_endpointAddress) + 2),
+			urb->transfer_buffer,
+			transfer_size,
+			mos7840_bulk_out_data_callback, mos7840_port);
+	} else {
+		usb_fill_bulk_urb(urb,
+			serial->dev,
+			usb_sndbulkpipe(serial->dev,
+				port->bulk_out_endpointAddress),
+			urb->transfer_buffer,
+			transfer_size,
+			mos7840_bulk_out_data_callback, mos7840_port);
+	}
 
 	data1 = urb->transfer_buffer;
 	dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress);
@@ -1535,7 +1559,7 @@
 
 	if (status) {
 		mos7840_port->busy[i] = 0;
-		dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+		dev_err_console(port, "%s - usb_submit_urb(write bulk) failed "
 			"with status = %d\n", __func__, status);
 		bytes_sent = status;
 		goto exit;
@@ -1838,7 +1862,7 @@
 
 	} else {
 #ifdef HW_flow_control
-		/ *setting h/w flow control bit to 0 */
+		/* setting h/w flow control bit to 0 */
 		Data = 0xb;
 		mos7840_port->shadowMCR = Data;
 		status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
@@ -2305,19 +2329,26 @@
 
 static int mos7840_calc_num_ports(struct usb_serial *serial)
 {
-	int mos7840_num_ports = 0;
+	__u16 Data = 0x00;
+	int ret = 0;
+	int mos7840_num_ports;
 
-	dbg("numberofendpoints: cur %d, alt %d",
-	    (int)serial->interface->cur_altsetting->desc.bNumEndpoints,
-	    (int)serial->interface->altsetting->desc.bNumEndpoints);
-	if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) {
-		mos7840_num_ports = serial->num_ports = 2;
-	} else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) {
+	ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+		MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &Data,
+		VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+
+	if ((Data & 0x01) == 0) {
+		mos7840_num_ports = 2;
+		serial->num_bulk_in = 2;
+		serial->num_bulk_out = 2;
+		serial->num_ports = 2;
+	} else {
+		mos7840_num_ports = 4;
 		serial->num_bulk_in = 4;
 		serial->num_bulk_out = 4;
-		mos7840_num_ports = serial->num_ports = 4;
+		serial->num_ports = 4;
 	}
-	dbg ("mos7840_num_ports = %d", mos7840_num_ports);
+
 	return mos7840_num_ports;
 }
 
@@ -2638,7 +2669,6 @@
 	.probe = usb_serial_probe,
 	.disconnect = usb_serial_disconnect,
 	.id_table = moschip_id_table_combined,
-	.no_dynamic_id = 1,
 };
 
 static struct usb_serial_driver moschip7840_4port_device = {
@@ -2647,7 +2677,6 @@
 		   .name = "mos7840",
 		   },
 	.description = DRIVER_DESC,
-	.usb_driver = &io_driver,
 	.id_table = moschip_port_id_table,
 	.num_ports = 4,
 	.open = mos7840_open,
@@ -2674,57 +2703,12 @@
 	.read_int_callback = mos7840_interrupt_callback,
 };
 
-/****************************************************************************
- * moschip7840_init
- *	This is called by the module subsystem, or on startup to initialize us
- ****************************************************************************/
-static int __init moschip7840_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&moschip7840_4port_device, NULL
+};
 
-	dbg("%s", " mos7840_init :entering..........");
+module_usb_serial_driver(io_driver, serial_drivers);
 
-	/* Register with the usb serial */
-	retval = usb_serial_register(&moschip7840_4port_device);
-
-	if (retval)
-		goto failed_port_device_register;
-
-	dbg("%s", "Entering...");
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-
-	/* Register with the usb */
-	retval = usb_register(&io_driver);
-	if (retval == 0) {
-		dbg("%s", "Leaving...");
-		return 0;
-	}
-	usb_serial_deregister(&moschip7840_4port_device);
-failed_port_device_register:
-	return retval;
-}
-
-/****************************************************************************
- * moschip7840_exit
- *	Called when the driver is about to be unloaded.
- ****************************************************************************/
-static void __exit moschip7840_exit(void)
-{
-
-	dbg("%s", " mos7840_exit :entering..........");
-
-	usb_deregister(&io_driver);
-
-	usb_serial_deregister(&moschip7840_4port_device);
-
-	dbg("%s", "Entering...");
-}
-
-module_init(moschip7840_init);
-module_exit(moschip7840_exit);
-
-/* Module information */
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c
index e2bfecc..3ab6214 100644
--- a/drivers/usb/serial/moto_modem.c
+++ b/drivers/usb/serial/moto_modem.c
@@ -36,7 +36,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver moto_device = {
@@ -45,29 +44,12 @@
 		.name =		"moto-modem",
 	},
 	.id_table =		id_table,
-	.usb_driver =		&moto_driver,
 	.num_ports =		1,
 };
 
-static int __init moto_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&moto_device, NULL
+};
 
-	retval = usb_serial_register(&moto_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&moto_driver);
-	if (retval)
-		usb_serial_deregister(&moto_device);
-	return retval;
-}
-
-static void __exit moto_exit(void)
-{
-	usb_deregister(&moto_driver);
-	usb_serial_deregister(&moto_device);
-}
-
-module_init(moto_init);
-module_exit(moto_exit);
+module_usb_serial_driver(moto_driver, serial_drivers);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index b28f1db..29ab6eb 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -35,7 +35,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id = 	1,
 };
 
 static void navman_read_int_callback(struct urb *urb)
@@ -122,7 +121,6 @@
 		.name =		"navman",
 	},
 	.id_table =		id_table,
-	.usb_driver =		&navman_driver,
 	.num_ports =		1,
 	.open =			navman_open,
 	.close = 		navman_close,
@@ -130,27 +128,12 @@
 	.read_int_callback =	navman_read_int_callback,
 };
 
-static int __init navman_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&navman_device, NULL
+};
 
-	retval = usb_serial_register(&navman_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&navman_driver);
-	if (retval)
-		usb_serial_deregister(&navman_device);
-	return retval;
-}
+module_usb_serial_driver(navman_driver, serial_drivers);
 
-static void __exit navman_exit(void)
-{
-	usb_deregister(&navman_driver);
-	usb_serial_deregister(&navman_device);
-}
-
-module_init(navman_init);
-module_exit(navman_exit);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 8b8d58a..88dc785 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -62,7 +62,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id = 	1,
 };
 
 
@@ -72,7 +71,6 @@
 		.name =		"omninet",
 	},
 	.description =		"ZyXEL - omni.net lcd plus usb",
-	.usb_driver =		&omninet_driver,
 	.id_table =		id_table,
 	.num_ports =		1,
 	.attach =		omninet_attach,
@@ -86,6 +84,10 @@
 	.release =		omninet_release,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&zyxel_omninet_device, NULL
+};
+
 
 /* The protocol.
  *
@@ -254,7 +256,7 @@
 	result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
 	if (result) {
 		set_bit(0, &wport->write_urbs_free);
-		dev_err(&port->dev,
+		dev_err_console(port,
 			"%s - failed submitting write urb, error %d\n",
 			__func__, result);
 	} else
@@ -319,35 +321,7 @@
 	kfree(usb_get_serial_port_data(port));
 }
 
-
-static int __init omninet_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&zyxel_omninet_device);
-	if (retval)
-		goto failed_usb_serial_register;
-	retval = usb_register(&omninet_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&zyxel_omninet_device);
-failed_usb_serial_register:
-	return retval;
-}
-
-
-static void __exit omninet_exit(void)
-{
-	usb_deregister(&omninet_driver);
-	usb_serial_deregister(&zyxel_omninet_device);
-}
-
-
-module_init(omninet_init);
-module_exit(omninet_exit);
+module_usb_serial_driver(omninet_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 262ded9..82cc9d2 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -604,7 +604,6 @@
 	.suspend =	opticon_suspend,
 	.resume =	opticon_resume,
 	.id_table =	id_table,
-	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver opticon_device = {
@@ -613,7 +612,6 @@
 		.name =		"opticon",
 	},
 	.id_table =		id_table,
-	.usb_driver = 		&opticon_driver,
 	.num_ports =		1,
 	.attach =		opticon_startup,
 	.open =			opticon_open,
@@ -629,27 +627,12 @@
 	.tiocmset =		opticon_tiocmset,
 };
 
-static int __init opticon_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&opticon_device, NULL
+};
 
-	retval = usb_serial_register(&opticon_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&opticon_driver);
-	if (retval)
-		usb_serial_deregister(&opticon_device);
-	return retval;
-}
+module_usb_serial_driver(opticon_driver, serial_drivers);
 
-static void __exit opticon_exit(void)
-{
-	usb_deregister(&opticon_driver);
-	usb_serial_deregister(&opticon_device);
-}
-
-module_init(opticon_init);
-module_exit(opticon_exit);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index b54afce..6815701 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -307,6 +307,9 @@
 #define TELIT_VENDOR_ID				0x1bc7
 #define TELIT_PRODUCT_UC864E			0x1003
 #define TELIT_PRODUCT_UC864G			0x1004
+#define TELIT_PRODUCT_CC864_DUAL		0x1005
+#define TELIT_PRODUCT_CC864_SINGLE		0x1006
+#define TELIT_PRODUCT_DE910_DUAL		0x1010
 
 /* ZTE PRODUCTS */
 #define ZTE_VENDOR_ID				0x19d2
@@ -484,6 +487,9 @@
 #define LG_VENDOR_ID				0x1004
 #define LG_PRODUCT_L02C				0x618f
 
+/* MediaTek products */
+#define MEDIATEK_VENDOR_ID			0x0e8d
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
 		OPTION_BLACKLIST_NONE = 0,
@@ -768,6 +774,9 @@
 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
 		.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
@@ -892,6 +901,8 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0164, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
@@ -1198,6 +1209,10 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) },        /* MediaTek MT6276M modem & app port */
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
@@ -1212,7 +1227,6 @@
 	.supports_autosuspend =	1,
 #endif
 	.id_table   = option_ids,
-	.no_dynamic_id = 	1,
 };
 
 /* The card has three separate interfaces, which the serial driver
@@ -1225,7 +1239,6 @@
 		.name =		"option1",
 	},
 	.description       = "GSM modem (1-port)",
-	.usb_driver        = &option_driver,
 	.id_table          = option_ids,
 	.num_ports         = 1,
 	.probe             = option_probe,
@@ -1249,6 +1262,10 @@
 #endif
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&option_1port_device, NULL
+};
+
 static bool debug;
 
 /* per port private data */
@@ -1280,36 +1297,7 @@
 	unsigned long tx_start_time[N_OUT_URB];
 };
 
-/* Functions used by new usb-serial code. */
-static int __init option_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&option_1port_device);
-	if (retval)
-		goto failed_1port_device_register;
-	retval = usb_register(&option_driver);
-	if (retval)
-		goto failed_driver_register;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-
-	return 0;
-
-failed_driver_register:
-	usb_serial_deregister(&option_1port_device);
-failed_1port_device_register:
-	return retval;
-}
-
-static void __exit option_exit(void)
-{
-	usb_deregister(&option_driver);
-	usb_serial_deregister(&option_1port_device);
-}
-
-module_init(option_init);
-module_exit(option_exit);
+module_usb_serial_driver(option_driver, serial_drivers);
 
 static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason,
 			   const struct option_blacklist_info *blacklist)
@@ -1360,6 +1348,7 @@
 		serial->interface->cur_altsetting->desc.bInterfaceNumber,
 		OPTION_BLACKLIST_RESERVED_IF,
 		(const struct option_blacklist_info *) id->driver_info))
+		return -ENODEV;
 
 	/* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */
 	if (serial->dev->descriptor.idVendor == SAMSUNG_VENDOR_ID &&
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index e287fd3..5fdc33c 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -71,7 +71,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id = 	1,
 };
 
 static bool debug;
@@ -157,7 +156,6 @@
 		.name =		"oti6858",
 	},
 	.id_table =		id_table,
-	.usb_driver =		&oti6858_driver,
 	.num_ports =		1,
 	.open =			oti6858_open,
 	.close =		oti6858_close,
@@ -176,6 +174,10 @@
 	.release =		oti6858_release,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&oti6858_device, NULL
+};
+
 struct oti6858_private {
 	spinlock_t lock;
 
@@ -302,7 +304,7 @@
 	if (count != 0) {
 		allow = kmalloc(1, GFP_KERNEL);
 		if (!allow) {
-			dev_err(&port->dev, "%s(): kmalloc failed\n",
+			dev_err_console(port, "%s(): kmalloc failed\n",
 					__func__);
 			return;
 		}
@@ -334,7 +336,7 @@
 	port->write_urb->transfer_buffer_length = count;
 	result = usb_submit_urb(port->write_urb, GFP_NOIO);
 	if (result != 0) {
-		dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+		dev_err_console(port, "%s(): usb_submit_urb() failed"
 			       " with error %d\n", __func__, result);
 		priv->flags.write_urb_in_use = 0;
 	}
@@ -938,7 +940,7 @@
 		port->write_urb->transfer_buffer_length = 1;
 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 		if (result) {
-			dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+			dev_err_console(port, "%s(): usb_submit_urb() failed,"
 					" error %d\n", __func__, result);
 		} else {
 			return;
@@ -956,29 +958,7 @@
 	}
 }
 
-/* module description and (de)initialization */
-
-static int __init oti6858_init(void)
-{
-	int retval;
-
-	retval = usb_serial_register(&oti6858_device);
-	if (retval == 0) {
-		retval = usb_register(&oti6858_driver);
-		if (retval)
-			usb_serial_deregister(&oti6858_device);
-	}
-	return retval;
-}
-
-static void __exit oti6858_exit(void)
-{
-	usb_deregister(&oti6858_driver);
-	usb_serial_deregister(&oti6858_device);
-}
-
-module_init(oti6858_init);
-module_exit(oti6858_exit);
+module_usb_serial_driver(oti6858_driver, serial_drivers);
 
 MODULE_DESCRIPTION(OTI6858_DESCRIPTION);
 MODULE_AUTHOR(OTI6858_AUTHOR);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 3d8cda5..ff4a174 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -104,7 +104,6 @@
 	.id_table =	id_table,
 	.suspend =      usb_serial_suspend,
 	.resume =       usb_serial_resume,
-	.no_dynamic_id = 	1,
 	.supports_autosuspend =	1,
 };
 
@@ -834,7 +833,6 @@
 		.name =		"pl2303",
 	},
 	.id_table =		id_table,
-	.usb_driver = 		&pl2303_driver,
 	.num_ports =		1,
 	.bulk_in_size =		256,
 	.bulk_out_size =	256,
@@ -853,32 +851,11 @@
 	.release =		pl2303_release,
 };
 
-static int __init pl2303_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&pl2303_device, NULL
+};
 
-	retval = usb_serial_register(&pl2303_device);
-	if (retval)
-		goto failed_usb_serial_register;
-	retval = usb_register(&pl2303_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&pl2303_device);
-failed_usb_serial_register:
-	return retval;
-}
-
-static void __exit pl2303_exit(void)
-{
-	usb_deregister(&pl2303_driver);
-	usb_serial_deregister(&pl2303_device);
-}
-
-module_init(pl2303_init);
-module_exit(pl2303_exit);
+module_usb_serial_driver(pl2303_driver, serial_drivers);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c
index a348198..9662456 100644
--- a/drivers/usb/serial/qcaux.c
+++ b/drivers/usb/serial/qcaux.c
@@ -82,7 +82,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver qcaux_device = {
@@ -91,29 +90,12 @@
 		.name =		"qcaux",
 	},
 	.id_table =		id_table,
-	.usb_driver =		&qcaux_driver,
 	.num_ports =		1,
 };
 
-static int __init qcaux_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&qcaux_device, NULL
+};
 
-	retval = usb_serial_register(&qcaux_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&qcaux_driver);
-	if (retval)
-		usb_serial_deregister(&qcaux_device);
-	return retval;
-}
-
-static void __exit qcaux_exit(void)
-{
-	usb_deregister(&qcaux_driver);
-	usb_serial_deregister(&qcaux_device);
-}
-
-module_init(qcaux_init);
-module_exit(qcaux_exit);
+module_usb_serial_driver(qcaux_driver, serial_drivers);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index f98800f..0206b10 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -24,39 +24,44 @@
 
 static bool debug;
 
+#define DEVICE_G1K(v, p) \
+	USB_DEVICE(v, p), .driver_info = 1
+
 static const struct usb_device_id id_table[] = {
-	{USB_DEVICE(0x05c6, 0x9211)},	/* Acer Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
-	{USB_DEVICE(0x03f0, 0x1f1d)},	/* HP un2400 Gobi Modem Device */
-	{USB_DEVICE(0x03f0, 0x201d)},	/* HP un2400 Gobi QDL Device */
-	{USB_DEVICE(0x03f0, 0x371d)},	/* HP un2430 Mobile Broadband Module */
-	{USB_DEVICE(0x04da, 0x250d)},	/* Panasonic Gobi Modem device */
-	{USB_DEVICE(0x04da, 0x250c)},	/* Panasonic Gobi QDL device */
-	{USB_DEVICE(0x413c, 0x8172)},	/* Dell Gobi Modem device */
-	{USB_DEVICE(0x413c, 0x8171)},	/* Dell Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa001)},	/* Novatel Gobi Modem device */
-	{USB_DEVICE(0x1410, 0xa008)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa010)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa011)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa012)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa013)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa014)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x0b05, 0x1776)},	/* Asus Gobi Modem device */
-	{USB_DEVICE(0x0b05, 0x1774)},	/* Asus Gobi QDL device */
-	{USB_DEVICE(0x19d2, 0xfff3)},	/* ONDA Gobi Modem device */
-	{USB_DEVICE(0x19d2, 0xfff2)},	/* ONDA Gobi QDL device */
-	{USB_DEVICE(0x1557, 0x0a80)},	/* OQO Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9001)},   /* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9002)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9202)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9203)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9222)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9008)},	/* Generic Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9009)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9201)},	/* Generic Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9221)},	/* Generic Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9231)},	/* Generic Gobi QDL device */
-	{USB_DEVICE(0x1f45, 0x0001)},	/* Unknown Gobi QDL device */
+	/* Gobi 1000 devices */
+	{DEVICE_G1K(0x05c6, 0x9211)},	/* Acer Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
+	{DEVICE_G1K(0x03f0, 0x1f1d)},	/* HP un2400 Gobi Modem Device */
+	{DEVICE_G1K(0x03f0, 0x201d)},	/* HP un2400 Gobi QDL Device */
+	{DEVICE_G1K(0x04da, 0x250d)},	/* Panasonic Gobi Modem device */
+	{DEVICE_G1K(0x04da, 0x250c)},	/* Panasonic Gobi QDL device */
+	{DEVICE_G1K(0x413c, 0x8172)},	/* Dell Gobi Modem device */
+	{DEVICE_G1K(0x413c, 0x8171)},	/* Dell Gobi QDL device */
+	{DEVICE_G1K(0x1410, 0xa001)},	/* Novatel Gobi Modem device */
+	{DEVICE_G1K(0x1410, 0xa008)},	/* Novatel Gobi QDL device */
+	{DEVICE_G1K(0x0b05, 0x1776)},	/* Asus Gobi Modem device */
+	{DEVICE_G1K(0x0b05, 0x1774)},	/* Asus Gobi QDL device */
+	{DEVICE_G1K(0x19d2, 0xfff3)},	/* ONDA Gobi Modem device */
+	{DEVICE_G1K(0x19d2, 0xfff2)},	/* ONDA Gobi QDL device */
+	{DEVICE_G1K(0x1557, 0x0a80)},	/* OQO Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9001)},   /* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9002)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9202)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9203)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9222)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9008)},	/* Generic Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9009)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9201)},	/* Generic Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9221)},	/* Generic Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9231)},	/* Generic Gobi QDL device */
+	{DEVICE_G1K(0x1f45, 0x0001)},	/* Unknown Gobi QDL device */
+
+	/* Gobi 2000 devices */
+	{USB_DEVICE(0x1410, 0xa010)},	/* Novatel Gobi 2000 QDL device */
+	{USB_DEVICE(0x1410, 0xa011)},	/* Novatel Gobi 2000 QDL device */
+	{USB_DEVICE(0x1410, 0xa012)},	/* Novatel Gobi 2000 QDL device */
+	{USB_DEVICE(0x1410, 0xa013)},	/* Novatel Gobi 2000 QDL device */
+	{USB_DEVICE(0x1410, 0xa014)},	/* Novatel Gobi 2000 QDL device */
 	{USB_DEVICE(0x413c, 0x8185)},	/* Dell Gobi 2000 QDL device (N0218, VU936) */
 	{USB_DEVICE(0x413c, 0x8186)},	/* Dell Gobi 2000 Modem device (N0218, VU936) */
 	{USB_DEVICE(0x05c6, 0x9208)},	/* Generic Gobi 2000 QDL device */
@@ -92,6 +97,8 @@
 	{USB_DEVICE(0x05c6, 0x9204)},	/* Gobi 2000 QDL device */
 	{USB_DEVICE(0x05c6, 0x9205)},	/* Gobi 2000 Modem device */
 
+	/* Gobi 3000 devices */
+	{USB_DEVICE(0x03f0, 0x371d)},	/* HP un2430 Gobi 3000 QDL */
 	{USB_DEVICE(0x05c6, 0x920c)},	/* Gobi 3000 QDL */
 	{USB_DEVICE(0x05c6, 0x920d)},	/* Gobi 3000 Composite */
 	{USB_DEVICE(0x1410, 0xa020)},   /* Novatel Gobi 3000 QDL */
@@ -122,8 +129,10 @@
 	int retval = -ENODEV;
 	__u8 nintf;
 	__u8 ifnum;
+	bool is_gobi1k = id->driver_info ? true : false;
 
 	dbg("%s", __func__);
+	dbg("Is Gobi 1000 = %d", is_gobi1k);
 
 	nintf = serial->dev->actconfig->desc.bNumInterfaces;
 	dbg("Num Interfaces = %d", nintf);
@@ -169,15 +178,25 @@
 
 	case 3:
 	case 4:
-		/* Composite mode */
-		/* ifnum == 0 is a broadband network adapter */
-		if (ifnum == 1) {
-			/*
-			 * Diagnostics Monitor (serial line 9600 8N1)
-			 * Qualcomm DM protocol
-			 * use "libqcdm" (ModemManager) for communication
-			 */
-			dbg("Diagnostics Monitor found");
+		/* Composite mode; don't bind to the QMI/net interface as that
+		 * gets handled by other drivers.
+		 */
+
+		/* Gobi 1K USB layout:
+		 * 0: serial port (doesn't respond)
+		 * 1: serial port (doesn't respond)
+		 * 2: AT-capable modem port
+		 * 3: QMI/net
+		 *
+		 * Gobi 2K+ USB layout:
+		 * 0: QMI/net
+		 * 1: DM/DIAG (use libqcdm from ModemManager for communication)
+		 * 2: AT-capable modem port
+		 * 3: NMEA
+		 */
+
+		if (ifnum == 1 && !is_gobi1k) {
+			dbg("Gobi 2K+ DM/DIAG interface found");
 			retval = usb_set_interface(serial->dev, ifnum, 0);
 			if (retval < 0) {
 				dev_err(&serial->dev->dev,
@@ -196,13 +215,13 @@
 				retval = -ENODEV;
 				kfree(data);
 			}
-		} else if (ifnum==3) {
+		} else if (ifnum==3 && !is_gobi1k) {
 			/*
 			 * NMEA (serial line 9600 8N1)
 			 * # echo "\$GPS_START" > /dev/ttyUSBx
 			 * # echo "\$GPS_STOP"  > /dev/ttyUSBx
 			 */
-			dbg("NMEA GPS interface found");
+			dbg("Gobi 2K+ NMEA GPS interface found");
 			retval = usb_set_interface(serial->dev, ifnum, 0);
 			if (retval < 0) {
 				dev_err(&serial->dev->dev,
@@ -246,7 +265,6 @@
 	},
 	.description         = "Qualcomm USB modem",
 	.id_table            = id_table,
-	.usb_driver          = &qcdriver,
 	.num_ports           = 1,
 	.probe               = qcprobe,
 	.open		     = usb_wwan_open,
@@ -263,31 +281,11 @@
 #endif
 };
 
-static int __init qcinit(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&qcdevice, NULL
+};
 
-	retval = usb_serial_register(&qcdevice);
-	if (retval)
-		return retval;
-
-	retval = usb_register(&qcdriver);
-	if (retval) {
-		usb_serial_deregister(&qcdevice);
-		return retval;
-	}
-
-	return 0;
-}
-
-static void __exit qcexit(void)
-{
-	usb_deregister(&qcdriver);
-	usb_serial_deregister(&qcdevice);
-}
-
-module_init(qcinit);
-module_exit(qcexit);
+module_usb_serial_driver(qcdriver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index d074b37..ae4ee30 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -156,7 +156,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id = 	1,
 };
 
 static const __u16 crc10_table[256] = {
@@ -309,16 +308,19 @@
 		.name =		"safe_serial",
 	},
 	.id_table =		id_table,
-	.usb_driver =		&safe_driver,
 	.num_ports =		1,
 	.process_read_urb =	safe_process_read_urb,
 	.prepare_write_buffer =	safe_prepare_write_buffer,
 	.attach =		safe_startup,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&safe_device, NULL
+};
+
 static int __init safe_init(void)
 {
-	int i, retval;
+	int i;
 
 	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
 	       DRIVER_DESC "\n");
@@ -337,24 +339,12 @@
 		}
 	}
 
-	retval = usb_serial_register(&safe_device);
-	if (retval)
-		goto failed_usb_serial_register;
-	retval = usb_register(&safe_driver);
-	if (retval)
-		goto failed_usb_register;
-
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&safe_device);
-failed_usb_serial_register:
-	return retval;
+	return usb_serial_register_drivers(&safe_driver, serial_drivers);
 }
 
 static void __exit safe_exit(void)
 {
-	usb_deregister(&safe_driver);
-	usb_serial_deregister(&safe_device);
+	usb_serial_deregister_drivers(&safe_driver, serial_drivers);
 }
 
 module_init(safe_init);
diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c
index 74cd4cc..46c0430 100644
--- a/drivers/usb/serial/siemens_mpi.c
+++ b/drivers/usb/serial/siemens_mpi.c
@@ -42,37 +42,15 @@
 		.name =		"siemens_mpi",
 	},
 	.id_table =		id_table,
-	.usb_driver =		&siemens_usb_mpi_driver,
 	.num_ports =		1,
 };
 
-static int __init siemens_usb_mpi_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&siemens_usb_mpi_device, NULL
+};
 
-	retval = usb_serial_register(&siemens_usb_mpi_device);
-	if (retval)
-		goto failed_usb_serial_register;
-	retval = usb_register(&siemens_usb_mpi_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO DRIVER_DESC "\n");
-	printk(KERN_INFO DRIVER_VERSION " " DRIVER_AUTHOR "\n");
-	return retval;
-failed_usb_register:
-	usb_serial_deregister(&siemens_usb_mpi_device);
-failed_usb_serial_register:
-	return retval;
-}
+module_usb_serial_driver(siemens_usb_mpi_driver, serial_drivers);
 
-static void __exit siemens_usb_mpi_exit(void)
-{
-	usb_deregister(&siemens_usb_mpi_driver);
-	usb_serial_deregister(&siemens_usb_mpi_device);
-}
-
-module_init(siemens_usb_mpi_init);
-module_exit(siemens_usb_mpi_exit);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index fdae0a4..f14465a 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -1084,7 +1084,6 @@
 	.resume     = usb_serial_resume,
 	.reset_resume = sierra_reset_resume,
 	.id_table   = id_table,
-	.no_dynamic_id = 	1,
 	.supports_autosuspend =	1,
 };
 
@@ -1095,7 +1094,6 @@
 	},
 	.description       = "Sierra USB modem",
 	.id_table          = id_table,
-	.usb_driver        = &sierra_driver,
 	.calc_num_ports	   = sierra_calc_num_ports,
 	.probe		   = sierra_probe,
 	.open              = sierra_open,
@@ -1113,38 +1111,11 @@
 	.read_int_callback = sierra_instat_callback,
 };
 
-/* Functions used by new usb-serial code. */
-static int __init sierra_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&sierra_device);
-	if (retval)
-		goto failed_device_register;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&sierra_device, NULL
+};
 
-
-	retval = usb_register(&sierra_driver);
-	if (retval)
-		goto failed_driver_register;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-
-	return 0;
-
-failed_driver_register:
-	usb_serial_deregister(&sierra_device);
-failed_device_register:
-	return retval;
-}
-
-static void __exit sierra_exit(void)
-{
-	usb_deregister(&sierra_driver);
-	usb_serial_deregister(&sierra_device);
-}
-
-module_init(sierra_init);
-module_exit(sierra_exit);
+module_usb_serial_driver(sierra_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index d7f5eee..f06c9a8 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -156,7 +156,6 @@
 	.probe =		usb_serial_probe,
 	.disconnect =		usb_serial_disconnect,
 	.id_table =		id_table,
-	.no_dynamic_id =	1,
 };
 
 
@@ -649,7 +648,6 @@
 		.name =		"SPCP8x5",
 	},
 	.id_table		= id_table,
-	.usb_driver		= &spcp8x5_driver,
 	.num_ports		= 1,
 	.open 			= spcp8x5_open,
 	.dtr_rts		= spcp8x5_dtr_rts,
@@ -664,32 +662,11 @@
 	.process_read_urb	= spcp8x5_process_read_urb,
 };
 
-static int __init spcp8x5_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&spcp8x5_device);
-	if (retval)
-		goto failed_usb_serial_register;
-	retval = usb_register(&spcp8x5_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&spcp8x5_device);
-failed_usb_serial_register:
-	return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+	&spcp8x5_device, NULL
+};
 
-static void __exit spcp8x5_exit(void)
-{
-	usb_deregister(&spcp8x5_driver);
-	usb_serial_deregister(&spcp8x5_device);
-}
-
-module_init(spcp8x5_init);
-module_exit(spcp8x5_exit);
+module_usb_serial_driver(spcp8x5_driver, serial_drivers);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 7697858..3cdc8a5 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -70,7 +70,6 @@
 	.id_table		       = id_table,
 	.suspend		       = usb_serial_suspend,
 	.resume			       = usb_serial_resume,
-	.no_dynamic_id		       = 1,
 	.supports_autosuspend	       = 1,
 };
 
@@ -677,7 +676,6 @@
 	},
 	.description	     = DRIVER_DESC,
 	.id_table	     = id_table,
-	.usb_driver	     = &ssu100_driver,
 	.num_ports	     = 1,
 	.open		     = ssu100_open,
 	.close		     = ssu100_close,
@@ -693,41 +691,11 @@
 	.disconnect          = usb_serial_generic_disconnect,
 };
 
-static int __init ssu100_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&ssu100_device, NULL
+};
 
-	dbg("%s", __func__);
-
-	/* register with usb-serial */
-	retval = usb_serial_register(&ssu100_device);
-
-	if (retval)
-		goto failed_usb_sio_register;
-
-	retval = usb_register(&ssu100_driver);
-	if (retval)
-		goto failed_usb_register;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-
-	return 0;
-
-failed_usb_register:
-	usb_serial_deregister(&ssu100_device);
-failed_usb_sio_register:
-	return retval;
-}
-
-static void __exit ssu100_exit(void)
-{
-	usb_deregister(&ssu100_driver);
-	usb_serial_deregister(&ssu100_device);
-}
-
-module_init(ssu100_init);
-module_exit(ssu100_exit);
+module_usb_serial_driver(ssu100_driver, serial_drivers);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
index 50651cf..1a5be13 100644
--- a/drivers/usb/serial/symbolserial.c
+++ b/drivers/usb/serial/symbolserial.c
@@ -287,7 +287,6 @@
 	.probe =		usb_serial_probe,
 	.disconnect =		usb_serial_disconnect,
 	.id_table =		id_table,
-	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver symbol_device = {
@@ -296,7 +295,6 @@
 		.name =		"symbol",
 	},
 	.id_table =		id_table,
-	.usb_driver = 		&symbol_driver,
 	.num_ports =		1,
 	.attach =		symbol_startup,
 	.open =			symbol_open,
@@ -307,27 +305,12 @@
 	.unthrottle =		symbol_unthrottle,
 };
 
-static int __init symbol_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&symbol_device, NULL
+};
 
-	retval = usb_serial_register(&symbol_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&symbol_driver);
-	if (retval)
-		usb_serial_deregister(&symbol_device);
-	return retval;
-}
+module_usb_serial_driver(symbol_driver, serial_drivers);
 
-static void __exit symbol_exit(void)
-{
-	usb_deregister(&symbol_driver);
-	usb_serial_deregister(&symbol_device);
-}
-
-module_init(symbol_init);
-module_exit(symbol_exit);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 75b838e..ab74123 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -216,7 +216,6 @@
 	.probe			= usb_serial_probe,
 	.disconnect		= usb_serial_disconnect,
 	.id_table		= ti_id_table_combined,
-	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver ti_1port_device = {
@@ -225,7 +224,6 @@
 		.name		= "ti_usb_3410_5052_1",
 	},
 	.description		= "TI USB 3410 1 port adapter",
-	.usb_driver		= &ti_usb_driver,
 	.id_table		= ti_id_table_3410,
 	.num_ports		= 1,
 	.attach			= ti_startup,
@@ -254,7 +252,6 @@
 		.name		= "ti_usb_3410_5052_2",
 	},
 	.description		= "TI USB 5052 2 port adapter",
-	.usb_driver		= &ti_usb_driver,
 	.id_table		= ti_id_table_5052,
 	.num_ports		= 2,
 	.attach			= ti_startup,
@@ -277,6 +274,9 @@
 	.write_bulk_callback	= ti_bulk_out_callback,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&ti_1port_device, &ti_2port_device, NULL
+};
 
 /* Module */
 
@@ -344,36 +344,17 @@
 		ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
 	}
 
-	ret = usb_serial_register(&ti_1port_device);
-	if (ret)
-		goto failed_1port;
-	ret = usb_serial_register(&ti_2port_device);
-	if (ret)
-		goto failed_2port;
-
-	ret = usb_register(&ti_usb_driver);
-	if (ret)
-		goto failed_usb;
-
-	printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":"
-	       TI_DRIVER_DESC "\n");
-
-	return 0;
-
-failed_usb:
-	usb_serial_deregister(&ti_2port_device);
-failed_2port:
-	usb_serial_deregister(&ti_1port_device);
-failed_1port:
+	ret = usb_serial_register_drivers(&ti_usb_driver, serial_drivers);
+	if (ret == 0)
+		printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":"
+			       TI_DRIVER_DESC "\n");
 	return ret;
 }
 
 
 static void __exit ti_exit(void)
 {
-	usb_deregister(&ti_usb_driver);
-	usb_serial_deregister(&ti_1port_device);
-	usb_serial_deregister(&ti_2port_device);
+	usb_serial_deregister_drivers(&ti_usb_driver, serial_drivers);
 }
 
 
@@ -1250,7 +1231,6 @@
 {
 	struct ti_port *tport = urb->context;
 	struct usb_serial_port *port = tport->tp_port;
-	struct device *dev = &urb->dev->dev;
 	int status = urb->status;
 
 	dbg("%s - port %d", __func__, port->number);
@@ -1268,7 +1248,7 @@
 		wake_up_interruptible(&tport->tp_write_wait);
 		return;
 	default:
-		dev_err(dev, "%s - nonzero urb status, %d\n",
+		dev_err_console(port, "%s - nonzero urb status, %d\n",
 			__func__, status);
 		tport->tp_tdev->td_urb_error = 1;
 		wake_up_interruptible(&tport->tp_write_wait);
@@ -1337,7 +1317,7 @@
 
 	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 	if (result) {
-		dev_err(&port->dev, "%s - submit write urb failed, %d\n",
+		dev_err_console(port, "%s - submit write urb failed, %d\n",
 							__func__, result);
 		tport->tp_write_urb_in_use = 0;
 		/* TODO: reschedule ti_send */
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index d4e724d..69230f0 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1333,7 +1333,7 @@
 	set_to_generic_if_null(device, prepare_write_buffer);
 }
 
-int usb_serial_register(struct usb_serial_driver *driver)
+static int usb_serial_register(struct usb_serial_driver *driver)
 {
 	int retval;
 
@@ -1367,10 +1367,8 @@
 	mutex_unlock(&table_lock);
 	return retval;
 }
-EXPORT_SYMBOL_GPL(usb_serial_register);
 
-
-void usb_serial_deregister(struct usb_serial_driver *device)
+static void usb_serial_deregister(struct usb_serial_driver *device)
 {
 	printk(KERN_INFO "USB Serial deregistering driver %s\n",
 	       device->description);
@@ -1379,7 +1377,76 @@
 	usb_serial_bus_deregister(device);
 	mutex_unlock(&table_lock);
 }
-EXPORT_SYMBOL_GPL(usb_serial_deregister);
+
+/**
+ * usb_serial_register_drivers - register drivers for a usb-serial module
+ * @udriver: usb_driver used for matching devices/interfaces
+ * @serial_drivers: NULL-terminated array of pointers to drivers to be registered
+ *
+ * Registers @udriver and all the drivers in the @serial_drivers array.
+ * Automatically fills in the .no_dynamic_id field in @udriver and
+ * the .usb_driver field in each serial driver.
+ */
+int usb_serial_register_drivers(struct usb_driver *udriver,
+		struct usb_serial_driver * const serial_drivers[])
+{
+	int rc;
+	const struct usb_device_id *saved_id_table;
+	struct usb_serial_driver * const *sd;
+
+	/*
+	 * udriver must be registered before any of the serial drivers,
+	 * because the store_new_id() routine for the serial drivers (in
+	 * bus.c) probes udriver.
+	 *
+	 * Performance hack: We don't want udriver to be probed until
+	 * the serial drivers are registered, because the probe would
+	 * simply fail for lack of a matching serial driver.
+	 * Therefore save off udriver's id_table until we are all set.
+	 */
+	saved_id_table = udriver->id_table;
+	udriver->id_table = NULL;
+
+	udriver->no_dynamic_id = 1;
+	rc = usb_register(udriver);
+	if (rc)
+		return rc;
+
+	for (sd = serial_drivers; *sd; ++sd) {
+		(*sd)->usb_driver = udriver;
+		rc = usb_serial_register(*sd);
+		if (rc)
+			goto failed;
+	}
+
+	/* Now restore udriver's id_table and look for matches */
+	udriver->id_table = saved_id_table;
+	rc = driver_attach(&udriver->drvwrap.driver);
+	return 0;
+
+ failed:
+	while (sd-- > serial_drivers)
+		usb_serial_deregister(*sd);
+	usb_deregister(udriver);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(usb_serial_register_drivers);
+
+/**
+ * usb_serial_deregister_drivers - deregister drivers for a usb-serial module
+ * @udriver: usb_driver to unregister
+ * @serial_drivers: NULL-terminated array of pointers to drivers to be deregistered
+ *
+ * Deregisters @udriver and all the drivers in the @serial_drivers array.
+ */
+void usb_serial_deregister_drivers(struct usb_driver *udriver,
+		struct usb_serial_driver * const serial_drivers[])
+{
+	for (; *serial_drivers; ++serial_drivers)
+		usb_serial_deregister(*serial_drivers);
+	usb_deregister(udriver);
+}
+EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers);
 
 /* Module information */
 MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
index 9b632e7..e3e8995 100644
--- a/drivers/usb/serial/usb_debug.c
+++ b/drivers/usb/serial/usb_debug.c
@@ -40,7 +40,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id =	1,
 };
 
 /* This HW really does not support a serial break, so one will be
@@ -74,32 +73,15 @@
 		.name =		"debug",
 	},
 	.id_table =		id_table,
-	.usb_driver =		&debug_driver,
 	.num_ports =		1,
 	.bulk_out_size =	USB_DEBUG_MAX_PACKET_SIZE,
 	.break_ctl =		usb_debug_break_ctl,
 	.process_read_urb =	usb_debug_process_read_urb,
 };
 
-static int __init debug_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&debug_device, NULL
+};
 
-	retval = usb_serial_register(&debug_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&debug_driver);
-	if (retval)
-		usb_serial_deregister(&debug_device);
-	return retval;
-}
-
-static void __exit debug_exit(void)
-{
-	usb_deregister(&debug_driver);
-	usb_serial_deregister(&debug_device);
-}
-
-module_init(debug_init);
-module_exit(debug_exit);
+module_usb_serial_driver(debug_driver, serial_drivers);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 210e4b1..71d6964 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -173,7 +173,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
-	.no_dynamic_id = 	1,
 };
 
 /* All of the device info needed for the Handspring Visor,
@@ -184,7 +183,6 @@
 		.name =		"visor",
 	},
 	.description =		"Handspring Visor / Palm OS",
-	.usb_driver =		&visor_driver,
 	.id_table =		id_table,
 	.num_ports =		2,
 	.bulk_out_size =	256,
@@ -205,7 +203,6 @@
 		.name =		"clie_5",
 	},
 	.description =		"Sony Clie 5.0",
-	.usb_driver =		&visor_driver,
 	.id_table =		clie_id_5_table,
 	.num_ports =		2,
 	.bulk_out_size =	256,
@@ -226,7 +223,6 @@
 		.name =		"clie_3.5",
 	},
 	.description =		"Sony Clie 3.5",
-	.usb_driver =		&visor_driver,
 	.id_table =		clie_id_3_5_table,
 	.num_ports =		1,
 	.bulk_out_size =	256,
@@ -237,6 +233,10 @@
 	.attach =		clie_3_5_startup,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&handspring_device, &clie_5_device, &clie_3_5_device, NULL
+};
+
 /******************************************************************************
  * Handspring Visor specific driver functions
  ******************************************************************************/
@@ -685,38 +685,17 @@
 		       ": Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x\n",
 			vendor, product);
 	}
-	retval = usb_serial_register(&handspring_device);
-	if (retval)
-		goto failed_handspring_register;
-	retval = usb_serial_register(&clie_3_5_device);
-	if (retval)
-		goto failed_clie_3_5_register;
-	retval = usb_serial_register(&clie_5_device);
-	if (retval)
-		goto failed_clie_5_register;
-	retval = usb_register(&visor_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
 
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&clie_5_device);
-failed_clie_5_register:
-	usb_serial_deregister(&clie_3_5_device);
-failed_clie_3_5_register:
-	usb_serial_deregister(&handspring_device);
-failed_handspring_register:
+	retval = usb_serial_register_drivers(&visor_driver, serial_drivers);
+	if (retval == 0)
+		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
 	return retval;
 }
 
 
 static void __exit visor_exit (void)
 {
-	usb_deregister(&visor_driver);
-	usb_serial_deregister(&handspring_device);
-	usb_serial_deregister(&clie_3_5_device);
-	usb_serial_deregister(&clie_5_device);
+	usb_serial_deregister_drivers(&visor_driver, serial_drivers);
 }
 
 
diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c
index f719d00..078f338 100644
--- a/drivers/usb/serial/vivopay-serial.c
+++ b/drivers/usb/serial/vivopay-serial.c
@@ -30,7 +30,6 @@
 	.probe =		usb_serial_probe,
 	.disconnect =		usb_serial_disconnect,
 	.id_table =		id_table,
-	.no_dynamic_id =	1,
 };
 
 static struct usb_serial_driver vivopay_serial_device = {
@@ -39,36 +38,14 @@
 		.name =		"vivopay-serial",
 	},
 	.id_table =		id_table,
-	.usb_driver =		&vivopay_serial_driver,
 	.num_ports =		1,
 };
 
-static int __init vivopay_serial_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&vivopay_serial_device);
-	if (retval)
-		goto failed_usb_serial_register;
-	retval = usb_register(&vivopay_serial_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	    DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&vivopay_serial_device);
-failed_usb_serial_register:
-	return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+	&vivopay_serial_device, NULL
+};
 
-static void __exit vivopay_serial_exit(void)
-{
-	usb_deregister(&vivopay_serial_driver);
-	usb_serial_deregister(&vivopay_serial_device);
-}
-
-module_init(vivopay_serial_init);
-module_exit(vivopay_serial_exit);
+module_usb_serial_driver(vivopay_serial_driver, serial_drivers);
 
 MODULE_AUTHOR("Forest Bond <forest.bond@outpostembedded.com>");
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 7e0acf5..407e23c 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -83,7 +83,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
-	.no_dynamic_id = 	1,
 };
 
 /* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
@@ -121,7 +120,6 @@
 		.name =		"whiteheatnofirm",
 	},
 	.description =		"Connect Tech - WhiteHEAT - (prerenumeration)",
-	.usb_driver =		&whiteheat_driver,
 	.id_table =		id_table_prerenumeration,
 	.num_ports =		1,
 	.probe =		whiteheat_firmware_download,
@@ -134,7 +132,6 @@
 		.name =		"whiteheat",
 	},
 	.description =		"Connect Tech - WhiteHEAT",
-	.usb_driver =		&whiteheat_driver,
 	.id_table =		id_table_std,
 	.num_ports =		4,
 	.attach =		whiteheat_attach,
@@ -155,6 +152,9 @@
 	.write_bulk_callback =	whiteheat_write_callback,
 };
 
+static struct usb_serial_driver * const serial_drivers[] = {
+	&whiteheat_fake_device, &whiteheat_device, NULL
+};
 
 struct whiteheat_command_private {
 	struct mutex		mutex;
@@ -740,7 +740,7 @@
 		urb->transfer_buffer_length = bytes;
 		result = usb_submit_urb(urb, GFP_ATOMIC);
 		if (result) {
-			dev_err(&port->dev,
+			dev_err_console(port,
 				"%s - failed submitting write urb, error %d\n",
 				__func__, result);
 			sent = result;
@@ -1454,44 +1454,7 @@
 	tty_kref_put(tty);
 }
 
-
-/*****************************************************************************
- * Connect Tech's White Heat module functions
- *****************************************************************************/
-static int __init whiteheat_init(void)
-{
-	int retval;
-	retval = usb_serial_register(&whiteheat_fake_device);
-	if (retval)
-		goto failed_fake_register;
-	retval = usb_serial_register(&whiteheat_device);
-	if (retval)
-		goto failed_device_register;
-	retval = usb_register(&whiteheat_driver);
-	if (retval)
-		goto failed_usb_register;
-	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
-	       DRIVER_DESC "\n");
-	return 0;
-failed_usb_register:
-	usb_serial_deregister(&whiteheat_device);
-failed_device_register:
-	usb_serial_deregister(&whiteheat_fake_device);
-failed_fake_register:
-	return retval;
-}
-
-
-static void __exit whiteheat_exit(void)
-{
-	usb_deregister(&whiteheat_driver);
-	usb_serial_deregister(&whiteheat_fake_device);
-	usb_serial_deregister(&whiteheat_device);
-}
-
-
-module_init(whiteheat_init);
-module_exit(whiteheat_exit);
+module_usb_serial_driver(whiteheat_driver, serial_drivers);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/zio.c b/drivers/usb/serial/zio.c
index f579672..9d0bb37 100644
--- a/drivers/usb/serial/zio.c
+++ b/drivers/usb/serial/zio.c
@@ -27,7 +27,6 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id =	1,
 };
 
 static struct usb_serial_driver zio_device = {
@@ -36,29 +35,12 @@
 		.name =		"zio",
 	},
 	.id_table =		id_table,
-	.usb_driver =		&zio_driver,
 	.num_ports =		1,
 };
 
-static int __init zio_init(void)
-{
-	int retval;
+static struct usb_serial_driver * const serial_drivers[] = {
+	&zio_device, NULL
+};
 
-	retval = usb_serial_register(&zio_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&zio_driver);
-	if (retval)
-		usb_serial_deregister(&zio_device);
-	return retval;
-}
-
-static void __exit zio_exit(void)
-{
-	usb_deregister(&zio_driver);
-	usb_serial_deregister(&zio_device);
-}
-
-module_init(zio_init);
-module_exit(zio_exit);
+module_usb_serial_driver(zio_driver, serial_drivers);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
index 51af2fe..bab8c8f 100644
--- a/drivers/usb/storage/alauda.c
+++ b/drivers/usb/storage/alauda.c
@@ -1276,6 +1276,7 @@
 	.post_reset =	usb_stor_post_reset,
 	.id_table =	alauda_usb_ids,
 	.soft_unbind =	1,
+	.no_dynamic_id = 1,
 };
 
 module_usb_driver(alauda_driver);
diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
index 387cbd47..5fe451d 100644
--- a/drivers/usb/storage/cypress_atacb.c
+++ b/drivers/usb/storage/cypress_atacb.c
@@ -272,6 +272,7 @@
 	.post_reset =	usb_stor_post_reset,
 	.id_table =	cypress_usb_ids,
 	.soft_unbind =	1,
+	.no_dynamic_id = 1,
 };
 
 module_usb_driver(cypress_driver);
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index 15d41f2..35e9c51 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -751,6 +751,7 @@
 	.post_reset =	usb_stor_post_reset,
 	.id_table =	datafab_usb_ids,
 	.soft_unbind =	1,
+	.no_dynamic_id = 1,
 };
 
 module_usb_driver(datafab_driver);
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
index a6ade40..e7e6781 100644
--- a/drivers/usb/storage/ene_ub6250.c
+++ b/drivers/usb/storage/ene_ub6250.c
@@ -674,7 +674,7 @@
 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = blenByte;
-	bcb->Flags  = 0x80;
+	bcb->Flags  = US_BULK_FLAG_IN;
 	bcb->CDB[0] = 0xF1;
 	bcb->CDB[5] = (unsigned char)(bnByte);
 	bcb->CDB[4] = (unsigned char)(bnByte>>8);
@@ -858,7 +858,7 @@
 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = 0x200;
-	bcb->Flags      = 0x80;
+	bcb->Flags      = US_BULK_FLAG_IN;
 	bcb->CDB[0]     = 0xF1;
 
 	bcb->CDB[1]     = 0x02; /* in init.c ENE_MSInit() is 0x01 */
@@ -877,7 +877,7 @@
 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = 0x4;
-	bcb->Flags      = 0x80;
+	bcb->Flags      = US_BULK_FLAG_IN;
 	bcb->CDB[0]     = 0xF1;
 	bcb->CDB[1]     = 0x03;
 
@@ -1170,7 +1170,7 @@
 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = 0x200;
-	bcb->Flags = 0x80;
+	bcb->Flags = US_BULK_FLAG_IN;
 	bcb->CDB[0] = 0xF2;
 	bcb->CDB[1] = 0x06;
 	bcb->CDB[4] = (unsigned char)(bn);
@@ -1249,7 +1249,7 @@
 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = 0x4;
-	bcb->Flags = 0x80;
+	bcb->Flags = US_BULK_FLAG_IN;
 	bcb->CDB[0] = 0xF2;
 	bcb->CDB[1] = 0x05;
 	bcb->CDB[5] = (unsigned char)(PageNum);
@@ -1331,7 +1331,7 @@
 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = 0x4;
-	bcb->Flags      = 0x80;
+	bcb->Flags      = US_BULK_FLAG_IN;
 	bcb->CDB[0]     = 0xF1;
 	bcb->CDB[1]     = 0x03;
 	bcb->CDB[5]     = (unsigned char)(PageNum);
@@ -1533,7 +1533,7 @@
 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = 0x4 * blen;
-	bcb->Flags      = 0x80;
+	bcb->Flags      = US_BULK_FLAG_IN;
 	bcb->CDB[0]     = 0xF1;
 	bcb->CDB[1]     = 0x03;
 	bcb->CDB[5]     = (unsigned char)(PageNum);
@@ -1650,7 +1650,7 @@
 		memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 		bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 		bcb->DataTransferLength = blenByte;
-		bcb->Flags  = 0x80;
+		bcb->Flags  = US_BULK_FLAG_IN;
 		bcb->CDB[0] = 0xF1;
 		bcb->CDB[1] = 0x02;
 		bcb->CDB[5] = (unsigned char)(bn);
@@ -1694,7 +1694,7 @@
 			memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 			bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 			bcb->DataTransferLength = 0x200 * len;
-			bcb->Flags  = 0x80;
+			bcb->Flags  = US_BULK_FLAG_IN;
 			bcb->CDB[0] = 0xF1;
 			bcb->CDB[1] = 0x02;
 			bcb->CDB[5] = (unsigned char)(blkno);
@@ -1827,7 +1827,7 @@
 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength	= 0x01;
-	bcb->Flags			= 0x80;
+	bcb->Flags			= US_BULK_FLAG_IN;
 	bcb->CDB[0]			= 0xED;
 	bcb->CDB[2]			= (unsigned char)(index>>8);
 	bcb->CDB[3]			= (unsigned char)index;
@@ -2083,7 +2083,7 @@
 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = 0x200;
-	bcb->Flags      = 0x80;
+	bcb->Flags      = US_BULK_FLAG_IN;
 	bcb->CDB[0]     = 0xF1;
 	bcb->CDB[1]     = 0x01;
 
@@ -2134,7 +2134,7 @@
 
 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->Flags = 0x80;
+	bcb->Flags = US_BULK_FLAG_IN;
 	bcb->CDB[0] = 0xF2;
 
 	result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0);
@@ -2153,7 +2153,7 @@
 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = 0x200;
-	bcb->Flags              = 0x80;
+	bcb->Flags              = US_BULK_FLAG_IN;
 	bcb->CDB[0]             = 0xF1;
 
 	result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
@@ -2407,6 +2407,7 @@
 	.post_reset =	usb_stor_post_reset,
 	.id_table =	ene_ub6250_usb_ids,
 	.soft_unbind =	1,
+	.no_dynamic_id = 1,
 };
 
 module_usb_driver(ene_ub6250_driver);
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index fa16157..042cf9e 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -553,6 +553,7 @@
 	.post_reset =	usb_stor_post_reset,
 	.id_table =	freecom_usb_ids,
 	.soft_unbind =	1,
+	.no_dynamic_id = 1,
 };
 
 module_usb_driver(freecom_driver);
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index bd55027..31fa24e 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -1566,6 +1566,7 @@
 	.post_reset =	usb_stor_post_reset,
 	.id_table =	isd200_usb_ids,
 	.soft_unbind =	1,
+	.no_dynamic_id = 1,
 };
 
 module_usb_driver(isd200_driver);
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index a19211b..e3b9738 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -677,6 +677,7 @@
 	.post_reset =	usb_stor_post_reset,
 	.id_table =	jumpshot_usb_ids,
 	.soft_unbind =	1,
+	.no_dynamic_id = 1,
 };
 
 module_usb_driver(jumpshot_driver);
diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c
index e720f8e..a8708ea 100644
--- a/drivers/usb/storage/karma.c
+++ b/drivers/usb/storage/karma.c
@@ -230,6 +230,7 @@
 	.post_reset =	usb_stor_post_reset,
 	.id_table =	karma_usb_ids,
 	.soft_unbind =	1,
+	.no_dynamic_id = 1,
 };
 
 module_usb_driver(karma_driver);
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index d75155c..886567a 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -312,6 +312,7 @@
 	.post_reset =	usb_stor_post_reset,
 	.id_table =	onetouch_usb_ids,
 	.soft_unbind =	1,
+	.no_dynamic_id = 1,
 };
 
 module_usb_driver(onetouch_driver);
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index d32f720..63cf282 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -219,7 +219,7 @@
 	/* set up the command wrapper */
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = cpu_to_le32(buf_len);
-	bcb->Flags = (dir == DMA_FROM_DEVICE) ? 1 << 7 : 0;
+	bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0;
 	bcb->Tag = ++us->tag;
 	bcb->Lun = lun;
 	bcb->Length = cmd_len;
@@ -305,7 +305,7 @@
 	/* set up the command wrapper */
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = cpu_to_le32(buf_len);
-	bcb->Flags = (dir == DMA_FROM_DEVICE) ? 1 << 7 : 0;
+	bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0;
 	bcb->Tag = ++us->tag;
 	bcb->Lun = lun;
 	bcb->Length = cmd_len;
@@ -507,9 +507,14 @@
 {
 	int retval;
 	u8 cmnd[12] = {0};
+	u8 *buf;
 
 	US_DEBUGP("%s, addr = 0xfe47, len = %d\n", __FUNCTION__, len);
 
+	buf = kmemdup(data, len, GFP_NOIO);
+	if (!buf)
+		return USB_STOR_TRANSPORT_ERROR;
+
 	cmnd[0] = 0xF0;
 	cmnd[1] = 0x0E;
 	cmnd[2] = 0xfe;
@@ -517,7 +522,8 @@
 	cmnd[4] = (u8)(len >> 8);
 	cmnd[5] = (u8)len;
 
-	retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, data, len, DMA_TO_DEVICE, NULL);
+	retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, buf, len, DMA_TO_DEVICE, NULL);
+	kfree(buf);
 	if (retval != USB_STOR_TRANSPORT_GOOD) {
 		return -EIO;
 	}
@@ -1100,6 +1106,7 @@
 	.id_table = realtek_cr_ids,
 	.soft_unbind = 1,
 	.supports_autosuspend = 1,
+	.no_dynamic_id = 1,
 };
 
 module_usb_driver(realtek_cr_driver);
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 13b8bcd..a324a5d 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -78,8 +78,6 @@
 
 static int slave_alloc (struct scsi_device *sdev)
 {
-	struct us_data *us = host_to_us(sdev->host);
-
 	/*
 	 * Set the INQUIRY transfer length to 36.  We don't use any of
 	 * the extra data and many devices choke if asked for more or
@@ -104,18 +102,6 @@
 	 */
 	blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
 
-	/*
-	 * The UFI spec treates the Peripheral Qualifier bits in an
-	 * INQUIRY result as reserved and requires devices to set them
-	 * to 0.  However the SCSI spec requires these bits to be set
-	 * to 3 to indicate when a LUN is not present.
-	 *
-	 * Let the scanning code know if this target merely sets
-	 * Peripheral Device Type to 0x1f to indicate no LUN.
-	 */
-	if (us->subclass == USB_SC_UFI)
-		sdev->sdev_target->pdt_1f_for_no_lun = 1;
-
 	return 0;
 }
 
@@ -197,6 +183,9 @@
 		 * page x08, so we will skip it. */
 		sdev->skip_ms_page_8 = 1;
 
+		/* Some devices don't handle VPD pages correctly */
+		sdev->skip_vpd_pages = 1;
+
 		/* Some disks return the total number of blocks in response
 		 * to READ CAPACITY rather than the highest block number.
 		 * If this device makes that mistake, tell the sd driver. */
@@ -217,16 +206,6 @@
 		if (sdev->scsi_level > SCSI_SPC_2)
 			us->fflags |= US_FL_SANE_SENSE;
 
-		/* Some devices report a SCSI revision level above 2 but are
-		 * unable to handle the REPORT LUNS command (for which
-		 * support is mandatory at level 3).  Since we already have
-		 * a Get-Max-LUN request, we won't lose much by setting the
-		 * revision level down to 2.  The only devices that would be
-		 * affected are those with sparse LUNs. */
-		if (sdev->scsi_level > SCSI_2)
-			sdev->sdev_target->scsi_level =
-					sdev->scsi_level = SCSI_2;
-
 		/* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable
 		 * Hardware Error) when any low-level error occurs,
 		 * recoverable or not.  Setting this flag tells the SCSI
@@ -283,6 +262,33 @@
 	return 0;
 }
 
+static int target_alloc(struct scsi_target *starget)
+{
+	struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
+
+	/*
+	 * Some USB drives don't support REPORT LUNS, even though they
+	 * report a SCSI revision level above 2.  Tell the SCSI layer
+	 * not to issue that command; it will perform a normal sequential
+	 * scan instead.
+	 */
+	starget->no_report_luns = 1;
+
+	/*
+	 * The UFI spec treats the Peripheral Qualifier bits in an
+	 * INQUIRY result as reserved and requires devices to set them
+	 * to 0.  However the SCSI spec requires these bits to be set
+	 * to 3 to indicate when a LUN is not present.
+	 *
+	 * Let the scanning code know if this target merely sets
+	 * Peripheral Device Type to 0x1f to indicate no LUN.
+	 */
+	if (us->subclass == USB_SC_UFI)
+		starget->pdt_1f_for_no_lun = 1;
+
+	return 0;
+}
+
 /* queue a command */
 /* This is always called with scsi_lock(host) held */
 static int queuecommand_lck(struct scsi_cmnd *srb,
@@ -546,6 +552,7 @@
 
 	.slave_alloc =			slave_alloc,
 	.slave_configure =		slave_configure,
+	.target_alloc =			target_alloc,
 
 	/* lots of sg segments can be handled */
 	.sg_tablesize =			SCSI_MAX_SG_CHAIN_SEGMENTS,
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 425df7d..3252a62 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -1787,6 +1787,7 @@
 	.post_reset =	usb_stor_post_reset,
 	.id_table =	sddr09_usb_ids,
 	.soft_unbind =	1,
+	.no_dynamic_id = 1,
 };
 
 module_usb_driver(sddr09_driver);
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index e4ca5fc..c144078 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -1006,6 +1006,7 @@
 	.post_reset =	usb_stor_post_reset,
 	.id_table =	sddr55_usb_ids,
 	.soft_unbind =	1,
+	.no_dynamic_id = 1,
 };
 
 module_usb_driver(sddr55_driver);
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index 1369d25..fa1ceeb 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -1863,6 +1863,7 @@
 	.post_reset =	usb_stor_post_reset,
 	.id_table =	usbat_usb_ids,
 	.soft_unbind =	1,
+	.no_dynamic_id = 1,
 };
 
 module_usb_driver(usbat_driver);
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 0e5c91c..c70109e 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -1071,7 +1071,8 @@
 	/* set up the command wrapper */
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = cpu_to_le32(transfer_length);
-	bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
+	bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ?
+		US_BULK_FLAG_IN : 0;
 	bcb->Tag = ++us->tag;
 	bcb->Lun = srb->device->lun;
 	if (us->fflags & US_FL_SCM_MULT_TARG)
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 242ff5e..9369d75 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -42,45 +42,6 @@
 #include <linux/blkdev.h>
 
 /*
- * Bulk only data structures
- */
-
-/* command block wrapper */
-struct bulk_cb_wrap {
-	__le32	Signature;		/* contains 'USBC' */
-	__u32	Tag;			/* unique per command id */
-	__le32	DataTransferLength;	/* size of data */
-	__u8	Flags;			/* direction in bit 0 */
-	__u8	Lun;			/* LUN normally 0 */
-	__u8	Length;			/* of of the CDB */
-	__u8	CDB[16];		/* max command */
-};
-
-#define US_BULK_CB_WRAP_LEN	31
-#define US_BULK_CB_SIGN		0x43425355	/*spells out USBC */
-#define US_BULK_FLAG_IN		1
-#define US_BULK_FLAG_OUT	0
-
-/* command status wrapper */
-struct bulk_cs_wrap {
-	__le32	Signature;		/* should = 'USBS' */
-	__u32	Tag;			/* same as original command */
-	__le32	Residue;		/* amount not transferred */
-	__u8	Status;			/* see below */
-	__u8	Filler[18];
-};
-
-#define US_BULK_CS_WRAP_LEN	13
-#define US_BULK_CS_SIGN		0x53425355	/* spells out 'USBS' */
-#define US_BULK_STAT_OK		0
-#define US_BULK_STAT_FAIL	1
-#define US_BULK_STAT_PHASE	2
-
-/* bulk-only class specific requests */
-#define US_BULK_RESET_REQUEST	0xff
-#define US_BULK_GET_MAX_LUN	0xfe
-
-/*
  * usb_stor_bulk_transfer_xxx() return codes, in order of severity
  */
 
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index a33ead5..8ec8a6e 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -13,7 +13,9 @@
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/usb.h>
+#include <linux/usb/hcd.h>
 #include <linux/usb/storage.h>
+#include <linux/usb/uas.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_dbg.h>
@@ -22,49 +24,6 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
 
-/* Common header for all IUs */
-struct iu {
-	__u8 iu_id;
-	__u8 rsvd1;
-	__be16 tag;
-};
-
-enum {
-	IU_ID_COMMAND		= 0x01,
-	IU_ID_STATUS		= 0x03,
-	IU_ID_RESPONSE		= 0x04,
-	IU_ID_TASK_MGMT		= 0x05,
-	IU_ID_READ_READY	= 0x06,
-	IU_ID_WRITE_READY	= 0x07,
-};
-
-struct command_iu {
-	__u8 iu_id;
-	__u8 rsvd1;
-	__be16 tag;
-	__u8 prio_attr;
-	__u8 rsvd5;
-	__u8 len;
-	__u8 rsvd7;
-	struct scsi_lun lun;
-	__u8 cdb[16];	/* XXX: Overflow-checking tools may misunderstand */
-};
-
-/*
- * Also used for the Read Ready and Write Ready IUs since they have the
- * same first four bytes
- */
-struct sense_iu {
-	__u8 iu_id;
-	__u8 rsvd1;
-	__be16 tag;
-	__be16 status_qual;
-	__u8 status;
-	__u8 rsvd7[7];
-	__be16 len;
-	__u8 sense[SCSI_SENSE_BUFFERSIZE];
-};
-
 /*
  * The r00-r01c specs define this version of the SENSE IU data structure.
  * It's still in use by several different firmware releases.
@@ -79,18 +38,6 @@
 	__u8 sense[SCSI_SENSE_BUFFERSIZE];
 };
 
-enum {
-	CMD_PIPE_ID		= 1,
-	STATUS_PIPE_ID		= 2,
-	DATA_IN_PIPE_ID		= 3,
-	DATA_OUT_PIPE_ID	= 4,
-
-	UAS_SIMPLE_TAG		= 0,
-	UAS_HEAD_TAG		= 1,
-	UAS_ORDERED_TAG		= 2,
-	UAS_ACA			= 4,
-};
-
 struct uas_dev_info {
 	struct usb_interface *intf;
 	struct usb_device *udev;
@@ -98,6 +45,8 @@
 	unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
 	unsigned use_streams:1;
 	unsigned uas_sense_old:1;
+	struct scsi_cmnd *cmnd;
+	struct urb *status_urb; /* used only if stream support is available */
 };
 
 enum {
@@ -109,6 +58,9 @@
 	SUBMIT_DATA_OUT_URB	= (1 << 5),
 	ALLOC_CMD_URB		= (1 << 6),
 	SUBMIT_CMD_URB		= (1 << 7),
+	COMPLETED_DATA_IN	= (1 << 8),
+	COMPLETED_DATA_OUT	= (1 << 9),
+	DATA_COMPLETES_CMD	= (1 << 10),
 };
 
 /* Overrides scsi_pointer */
@@ -116,6 +68,7 @@
 	unsigned int state;
 	unsigned int stream;
 	struct urb *cmd_urb;
+	/* status_urb is used only if stream support isn't available */
 	struct urb *status_urb;
 	struct urb *data_in_urb;
 	struct urb *data_out_urb;
@@ -125,33 +78,43 @@
 /* I hate forward declarations, but I actually have a loop */
 static int uas_submit_urbs(struct scsi_cmnd *cmnd,
 				struct uas_dev_info *devinfo, gfp_t gfp);
+static void uas_do_work(struct work_struct *work);
 
+static DECLARE_WORK(uas_work, uas_do_work);
 static DEFINE_SPINLOCK(uas_work_lock);
 static LIST_HEAD(uas_work_list);
 
 static void uas_do_work(struct work_struct *work)
 {
 	struct uas_cmd_info *cmdinfo;
+	struct uas_cmd_info *temp;
 	struct list_head list;
+	int err;
 
 	spin_lock_irq(&uas_work_lock);
 	list_replace_init(&uas_work_list, &list);
 	spin_unlock_irq(&uas_work_lock);
 
-	list_for_each_entry(cmdinfo, &list, list) {
+	list_for_each_entry_safe(cmdinfo, temp, &list, list) {
 		struct scsi_pointer *scp = (void *)cmdinfo;
 		struct scsi_cmnd *cmnd = container_of(scp,
 							struct scsi_cmnd, SCp);
-		uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
+		err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
+		if (err) {
+			list_del(&cmdinfo->list);
+			spin_lock_irq(&uas_work_lock);
+			list_add_tail(&cmdinfo->list, &uas_work_list);
+			spin_unlock_irq(&uas_work_lock);
+			schedule_work(&uas_work);
+		}
 	}
 }
 
-static DECLARE_WORK(uas_work, uas_do_work);
-
 static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
 {
 	struct sense_iu *sense_iu = urb->transfer_buffer;
 	struct scsi_device *sdev = cmnd->device;
+	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 
 	if (urb->actual_length > 16) {
 		unsigned len = be16_to_cpup(&sense_iu->len);
@@ -169,16 +132,15 @@
 	}
 
 	cmnd->result = sense_iu->status;
-	if (sdev->current_cmnd)
-		sdev->current_cmnd = NULL;
-	cmnd->scsi_done(cmnd);
-	usb_free_urb(urb);
+	if (!(cmdinfo->state & DATA_COMPLETES_CMD))
+		cmnd->scsi_done(cmnd);
 }
 
 static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
 {
 	struct sense_iu_old *sense_iu = urb->transfer_buffer;
 	struct scsi_device *sdev = cmnd->device;
+	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 
 	if (urb->actual_length > 8) {
 		unsigned len = be16_to_cpup(&sense_iu->len) - 2;
@@ -196,10 +158,8 @@
 	}
 
 	cmnd->result = sense_iu->status;
-	if (sdev->current_cmnd)
-		sdev->current_cmnd = NULL;
-	cmnd->scsi_done(cmnd);
-	usb_free_urb(urb);
+	if (!(cmdinfo->state & DATA_COMPLETES_CMD))
+		cmnd->scsi_done(cmnd);
 }
 
 static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
@@ -208,7 +168,7 @@
 	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 	int err;
 
-	cmdinfo->state = direction | SUBMIT_STATUS_URB;
+	cmdinfo->state = direction;
 	err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
 	if (err) {
 		spin_lock(&uas_work_lock);
@@ -221,27 +181,61 @@
 static void uas_stat_cmplt(struct urb *urb)
 {
 	struct iu *iu = urb->transfer_buffer;
-	struct scsi_device *sdev = urb->context;
-	struct uas_dev_info *devinfo = sdev->hostdata;
+	struct Scsi_Host *shost = urb->context;
+	struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
 	struct scsi_cmnd *cmnd;
+	struct uas_cmd_info *cmdinfo;
 	u16 tag;
+	int ret;
 
 	if (urb->status) {
 		dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status);
-		usb_free_urb(urb);
+		if (devinfo->use_streams)
+			usb_free_urb(urb);
 		return;
 	}
 
 	tag = be16_to_cpup(&iu->tag) - 1;
-	if (sdev->current_cmnd)
-		cmnd = sdev->current_cmnd;
+	if (tag == 0)
+		cmnd = devinfo->cmnd;
 	else
-		cmnd = scsi_find_tag(sdev, tag);
-	if (!cmnd)
+		cmnd = scsi_host_find_tag(shost, tag - 1);
+	if (!cmnd) {
+		if (devinfo->use_streams) {
+			usb_free_urb(urb);
+			return;
+		}
+		ret = usb_submit_urb(urb, GFP_ATOMIC);
+		if (ret)
+			dev_err(&urb->dev->dev, "failed submit status urb\n");
 		return;
+	}
+	cmdinfo = (void *)&cmnd->SCp;
 
 	switch (iu->iu_id) {
 	case IU_ID_STATUS:
+		if (devinfo->cmnd == cmnd)
+			devinfo->cmnd = NULL;
+
+		if (!(cmdinfo->state & COMPLETED_DATA_IN) &&
+				cmdinfo->data_in_urb) {
+		       if (devinfo->use_streams) {
+			       cmdinfo->state |= DATA_COMPLETES_CMD;
+			       usb_unlink_urb(cmdinfo->data_in_urb);
+		       } else {
+			       usb_free_urb(cmdinfo->data_in_urb);
+		       }
+		}
+		if (!(cmdinfo->state & COMPLETED_DATA_OUT) &&
+				cmdinfo->data_out_urb) {
+			if (devinfo->use_streams) {
+				cmdinfo->state |= DATA_COMPLETES_CMD;
+				usb_unlink_urb(cmdinfo->data_in_urb);
+			} else {
+				usb_free_urb(cmdinfo->data_out_urb);
+			}
+		}
+
 		if (urb->actual_length < 16)
 			devinfo->uas_sense_old = 1;
 		if (devinfo->uas_sense_old)
@@ -259,29 +253,70 @@
 		scmd_printk(KERN_ERR, cmnd,
 			"Bogus IU (%d) received on status pipe\n", iu->iu_id);
 	}
+
+	if (devinfo->use_streams) {
+		usb_free_urb(urb);
+		return;
+	}
+
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret)
+		dev_err(&urb->dev->dev, "failed submit status urb\n");
 }
 
-static void uas_data_cmplt(struct urb *urb)
+static void uas_data_out_cmplt(struct urb *urb)
 {
-	struct scsi_data_buffer *sdb = urb->context;
+	struct scsi_cmnd *cmnd = urb->context;
+	struct scsi_data_buffer *sdb = scsi_out(cmnd);
+	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+
+	cmdinfo->state |= COMPLETED_DATA_OUT;
+
 	sdb->resid = sdb->length - urb->actual_length;
 	usb_free_urb(urb);
+
+	if (cmdinfo->state & DATA_COMPLETES_CMD)
+		cmnd->scsi_done(cmnd);
+}
+
+static void uas_data_in_cmplt(struct urb *urb)
+{
+	struct scsi_cmnd *cmnd = urb->context;
+	struct scsi_data_buffer *sdb = scsi_in(cmnd);
+	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+
+	cmdinfo->state |= COMPLETED_DATA_IN;
+
+	sdb->resid = sdb->length - urb->actual_length;
+	usb_free_urb(urb);
+
+	if (cmdinfo->state & DATA_COMPLETES_CMD)
+		cmnd->scsi_done(cmnd);
 }
 
 static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
-				unsigned int pipe, u16 stream_id,
-				struct scsi_data_buffer *sdb,
-				enum dma_data_direction dir)
+		unsigned int pipe, struct scsi_cmnd *cmnd,
+		enum dma_data_direction dir)
 {
+	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 	struct usb_device *udev = devinfo->udev;
 	struct urb *urb = usb_alloc_urb(0, gfp);
+	struct scsi_data_buffer *sdb;
+	usb_complete_t complete_fn;
+	u16 stream_id = cmdinfo->stream;
 
 	if (!urb)
 		goto out;
-	usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, uas_data_cmplt,
-									sdb);
-	if (devinfo->use_streams)
-		urb->stream_id = stream_id;
+	if (dir == DMA_FROM_DEVICE) {
+		sdb = scsi_in(cmnd);
+		complete_fn = uas_data_in_cmplt;
+	} else {
+		sdb = scsi_out(cmnd);
+		complete_fn = uas_data_out_cmplt;
+	}
+	usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length,
+			complete_fn, cmnd);
+	urb->stream_id = stream_id;
 	urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0;
 	urb->sg = sdb->table.sgl;
  out:
@@ -289,7 +324,7 @@
 }
 
 static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
-					struct scsi_cmnd *cmnd, u16 stream_id)
+		struct Scsi_Host *shost, u16 stream_id)
 {
 	struct usb_device *udev = devinfo->udev;
 	struct urb *urb = usb_alloc_urb(0, gfp);
@@ -303,7 +338,7 @@
 		goto free;
 
 	usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
-						uas_stat_cmplt, cmnd->device);
+						uas_stat_cmplt, shost);
 	urb->stream_id = stream_id;
 	urb->transfer_flags |= URB_FREE_BUFFER;
  out:
@@ -334,7 +369,10 @@
 		goto free;
 
 	iu->iu_id = IU_ID_COMMAND;
-	iu->tag = cpu_to_be16(stream_id);
+	if (blk_rq_tagged(cmnd->request))
+		iu->tag = cpu_to_be16(cmnd->request->tag + 2);
+	else
+		iu->tag = cpu_to_be16(1);
 	iu->prio_attr = UAS_SIMPLE_TAG;
 	iu->len = len;
 	int_to_scsilun(sdev->lun, &iu->lun);
@@ -362,8 +400,8 @@
 	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 
 	if (cmdinfo->state & ALLOC_STATUS_URB) {
-		cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd,
-							  cmdinfo->stream);
+		cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp,
+				cmnd->device->host, cmdinfo->stream);
 		if (!cmdinfo->status_urb)
 			return SCSI_MLQUEUE_DEVICE_BUSY;
 		cmdinfo->state &= ~ALLOC_STATUS_URB;
@@ -380,8 +418,8 @@
 
 	if (cmdinfo->state & ALLOC_DATA_IN_URB) {
 		cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp,
-					devinfo->data_in_pipe, cmdinfo->stream,
-					scsi_in(cmnd), DMA_FROM_DEVICE);
+					devinfo->data_in_pipe, cmnd,
+					DMA_FROM_DEVICE);
 		if (!cmdinfo->data_in_urb)
 			return SCSI_MLQUEUE_DEVICE_BUSY;
 		cmdinfo->state &= ~ALLOC_DATA_IN_URB;
@@ -398,8 +436,8 @@
 
 	if (cmdinfo->state & ALLOC_DATA_OUT_URB) {
 		cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp,
-					devinfo->data_out_pipe, cmdinfo->stream,
-					scsi_out(cmnd), DMA_TO_DEVICE);
+					devinfo->data_out_pipe, cmnd,
+					DMA_TO_DEVICE);
 		if (!cmdinfo->data_out_urb)
 			return SCSI_MLQUEUE_DEVICE_BUSY;
 		cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
@@ -444,13 +482,13 @@
 
 	BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
 
-	if (!cmdinfo->status_urb && sdev->current_cmnd)
+	if (devinfo->cmnd)
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 
 	if (blk_rq_tagged(cmnd->request)) {
-		cmdinfo->stream = cmnd->request->tag + 1;
+		cmdinfo->stream = cmnd->request->tag + 2;
 	} else {
-		sdev->current_cmnd = cmnd;
+		devinfo->cmnd = cmnd;
 		cmdinfo->stream = 1;
 	}
 
@@ -472,7 +510,8 @@
 	}
 
 	if (!devinfo->use_streams) {
-		cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
+		cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB |
+				ALLOC_STATUS_URB | SUBMIT_STATUS_URB);
 		cmdinfo->stream = 0;
 	}
 
@@ -551,7 +590,7 @@
 {
 	struct uas_dev_info *devinfo = sdev->hostdata;
 	scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
-	scsi_activate_tcq(sdev, devinfo->qdepth - 1);
+	scsi_activate_tcq(sdev, devinfo->qdepth - 2);
 	return 0;
 }
 
@@ -589,22 +628,34 @@
 		intf->desc.bInterfaceProtocol == USB_PR_UAS);
 }
 
+static int uas_isnt_supported(struct usb_device *udev)
+{
+	struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
+	dev_warn(&udev->dev, "The driver for the USB controller %s does not "
+			"support scatter-gather which is\n",
+			hcd->driver->description);
+	dev_warn(&udev->dev, "required by the UAS driver. Please try an"
+			"alternative USB controller if you wish to use UAS.\n");
+	return -ENODEV;
+}
+
 static int uas_switch_interface(struct usb_device *udev,
 						struct usb_interface *intf)
 {
 	int i;
-
-	if (uas_is_interface(intf->cur_altsetting))
-		return 0;
+	int sg_supported = udev->bus->sg_tablesize != 0;
 
 	for (i = 0; i < intf->num_altsetting; i++) {
 		struct usb_host_interface *alt = &intf->altsetting[i];
-		if (alt == intf->cur_altsetting)
-			continue;
-		if (uas_is_interface(alt))
+
+		if (uas_is_interface(alt)) {
+			if (!sg_supported)
+				return uas_isnt_supported(udev);
 			return usb_set_interface(udev,
 						alt->desc.bInterfaceNumber,
 						alt->desc.bAlternateSetting);
+		}
 	}
 
 	return -ENODEV;
@@ -619,6 +670,7 @@
 	unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints;
 
 	devinfo->uas_sense_old = 0;
+	devinfo->cmnd = NULL;
 
 	for (i = 0; i < n_endpoints; i++) {
 		unsigned char *extra = endpoint[i].extra;
@@ -670,6 +722,40 @@
 	}
 }
 
+static int uas_alloc_status_urb(struct uas_dev_info *devinfo,
+		struct Scsi_Host *shost)
+{
+	if (devinfo->use_streams) {
+		devinfo->status_urb = NULL;
+		return 0;
+	}
+
+	devinfo->status_urb = uas_alloc_sense_urb(devinfo, GFP_KERNEL,
+			shost, 0);
+	if (!devinfo->status_urb)
+		goto err_s_urb;
+
+	if (usb_submit_urb(devinfo->status_urb, GFP_KERNEL))
+		goto err_submit_urb;
+
+	return 0;
+err_submit_urb:
+	usb_free_urb(devinfo->status_urb);
+err_s_urb:
+	return -ENOMEM;
+}
+
+static void uas_free_streams(struct uas_dev_info *devinfo)
+{
+	struct usb_device *udev = devinfo->udev;
+	struct usb_host_endpoint *eps[3];
+
+	eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
+	eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
+	eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
+	usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL);
+}
+
 /*
  * XXX: What I'd like to do here is register a SCSI host for each USB host in
  * the system.  Follow usb-storage's design of registering a SCSI host for
@@ -699,18 +785,33 @@
 	shost->max_id = 1;
 	shost->sg_tablesize = udev->bus->sg_tablesize;
 
-	result = scsi_add_host(shost, &intf->dev);
-	if (result)
-		goto free;
-	shost->hostdata[0] = (unsigned long)devinfo;
-
 	devinfo->intf = intf;
 	devinfo->udev = udev;
 	uas_configure_endpoints(devinfo);
 
+	result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2);
+	if (result)
+		goto free;
+
+	result = scsi_add_host(shost, &intf->dev);
+	if (result)
+		goto deconfig_eps;
+
+	shost->hostdata[0] = (unsigned long)devinfo;
+
+	result = uas_alloc_status_urb(devinfo, shost);
+	if (result)
+		goto err_alloc_status;
+
 	scsi_scan_host(shost);
 	usb_set_intfdata(intf, shost);
 	return result;
+
+err_alloc_status:
+	scsi_remove_host(shost);
+	shost = NULL;
+deconfig_eps:
+	uas_free_streams(devinfo);
  free:
 	kfree(devinfo);
 	if (shost)
@@ -732,18 +833,13 @@
 
 static void uas_disconnect(struct usb_interface *intf)
 {
-	struct usb_device *udev = interface_to_usbdev(intf);
-	struct usb_host_endpoint *eps[3];
 	struct Scsi_Host *shost = usb_get_intfdata(intf);
 	struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
 
 	scsi_remove_host(shost);
-
-	eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
-	eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
-	eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
-	usb_free_streams(intf, eps, 3, GFP_KERNEL);
-
+	usb_kill_urb(devinfo->status_urb);
+	usb_free_urb(devinfo->status_urb);
+	uas_free_streams(devinfo);
 	kfree(devinfo);
 }
 
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index db51ba1..c18538e 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -125,6 +125,9 @@
 	{ }		/* Terminating entry */
 };
 
+static struct us_unusual_dev for_dynamic_ids =
+		USUAL_DEV(USB_SC_SCSI, USB_PR_BULK, 0);
+
 #undef UNUSUAL_DEV
 #undef COMPLIANT_DEV
 #undef USUAL_DEV
@@ -999,8 +1002,10 @@
 static int storage_probe(struct usb_interface *intf,
 			 const struct usb_device_id *id)
 {
+	struct us_unusual_dev *unusual_dev;
 	struct us_data *us;
 	int result;
+	int size;
 
 	/*
 	 * If libusual is configured, let it decide whether a standard
@@ -1019,8 +1024,19 @@
 	 * table, so we use the index of the id entry to find the
 	 * corresponding unusual_devs entry.
 	 */
-	result = usb_stor_probe1(&us, intf, id,
-			(id - usb_storage_usb_ids) + us_unusual_dev_list);
+
+	size = ARRAY_SIZE(us_unusual_dev_list);
+	if (id >= usb_storage_usb_ids && id < usb_storage_usb_ids + size) {
+		unusual_dev = (id - usb_storage_usb_ids) + us_unusual_dev_list;
+	} else {
+		unusual_dev = &for_dynamic_ids;
+
+		US_DEBUGP("%s %s 0x%04x 0x%04x\n", "Use Bulk-Only transport",
+			"with the Transparent SCSI protocol for dynamic id:",
+			id->idVendor, id->idProduct);
+	}
+
+	result = usb_stor_probe1(&us, intf, id, unusual_dev);
 	if (result)
 		return result;
 
@@ -1046,7 +1062,6 @@
 	.id_table =	usb_storage_usb_ids,
 	.supports_autosuspend = 1,
 	.soft_unbind =	1,
-	.no_dynamic_id = 1,
 };
 
 static int __init usb_stor_init(void)
diff --git a/include/linux/device.h b/include/linux/device.h
index f62e216..7c46bc3 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -1005,19 +1005,20 @@
  * @__driver: driver name
  * @__register: register function for this driver type
  * @__unregister: unregister function for this driver type
+ * @...: Additional arguments to be passed to __register and __unregister.
  *
  * Use this macro to construct bus specific macros for registering
  * drivers, and do not use it on its own.
  */
-#define module_driver(__driver, __register, __unregister) \
+#define module_driver(__driver, __register, __unregister, ...) \
 static int __init __driver##_init(void) \
 { \
-	return __register(&(__driver)); \
+	return __register(&(__driver) , ##__VA_ARGS__); \
 } \
 module_init(__driver##_init); \
 static void __exit __driver##_exit(void) \
 { \
-	__unregister(&(__driver)); \
+	__unregister(&(__driver) , ##__VA_ARGS__); \
 } \
 module_exit(__driver##_exit);
 
diff --git a/include/linux/platform_data/dwc3-exynos.h b/include/linux/platform_data/dwc3-exynos.h
new file mode 100644
index 0000000..5eb7da9b
--- /dev/null
+++ b/include/linux/platform_data/dwc3-exynos.h
@@ -0,0 +1,24 @@
+/**
+ * dwc3-exynos.h - Samsung EXYNOS DWC3 Specific Glue layer, header.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Author: Anton Tikhomirov <av.tikhomirov@samsung.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.
+ */
+
+#ifndef _DWC3_EXYNOS_H_
+#define _DWC3_EXYNOS_H_
+
+struct dwc3_exynos_data {
+	int phy_type;
+	int (*phy_init)(struct platform_device *pdev, int type);
+	int (*phy_exit)(struct platform_device *pdev, int type);
+};
+
+#endif /* _DWC3_EXYNOS_H_ */
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 69d8457..73b68d1 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -376,6 +376,12 @@
 
 struct usb_tt;
 
+enum usb_device_removable {
+	USB_DEVICE_REMOVABLE_UNKNOWN = 0,
+	USB_DEVICE_REMOVABLE,
+	USB_DEVICE_FIXED,
+};
+
 /**
  * struct usb_device - kernel's representation of a USB device
  * @devnum: device number; address on a USB bus
@@ -432,6 +438,7 @@
  * @wusb_dev: if this is a Wireless USB device, link to the WUSB
  *	specific data for the device.
  * @slot_id: Slot ID assigned by xHCI
+ * @removable: Device can be physically removed from this port
  *
  * Notes:
  * Usbcore drivers should not set usbdev->state directly.  Instead use
@@ -494,7 +501,7 @@
 #endif
 
 	int maxchild;
-	struct usb_device *children[USB_MAXCHILDREN];
+	struct usb_device **children;
 
 	u32 quirks;
 	atomic_t urbnum;
@@ -509,6 +516,7 @@
 #endif
 	struct wusb_dev *wusb_dev;
 	int slot_id;
+	enum usb_device_removable removable;
 };
 #define	to_usb_device(d) container_of(d, struct usb_device, dev)
 
diff --git a/include/linux/usb/audio-v2.h b/include/linux/usb/audio-v2.h
index 964cb60..ed13053 100644
--- a/include/linux/usb/audio-v2.h
+++ b/include/linux/usb/audio-v2.h
@@ -43,6 +43,27 @@
 	return (bmControls >> (control * 2)) & 0x2;
 }
 
+/* 4.7.2 Class-Specific AC Interface Descriptor */
+struct uac2_ac_header_descriptor {
+	__u8  bLength;			/* 9 */
+	__u8  bDescriptorType;		/* USB_DT_CS_INTERFACE */
+	__u8  bDescriptorSubtype;	/* UAC_MS_HEADER */
+	__le16 bcdADC;			/* 0x0200 */
+	__u8  bCategory;
+	__le16 wTotalLength;		/* includes Unit and Terminal desc. */
+	__u8  bmControls;
+} __packed;
+
+/* 2.3.1.6 Type I Format Type Descriptor (Frmts20 final.pdf)*/
+struct uac2_format_type_i_descriptor {
+	__u8  bLength;			/* in bytes: 6 */
+	__u8  bDescriptorType;		/* USB_DT_CS_INTERFACE */
+	__u8  bDescriptorSubtype;	/* FORMAT_TYPE */
+	__u8  bFormatType;		/* FORMAT_TYPE_1 */
+	__u8  bSubslotSize;		/* {1,2,3,4} */
+	__u8  bBitResolution;
+} __packed;
+
 /* 4.7.2.1 Clock Source Descriptor */
 
 struct uac_clock_source_descriptor {
diff --git a/include/linux/usb/cdc-wdm.h b/include/linux/usb/cdc-wdm.h
new file mode 100644
index 0000000..719c332
--- /dev/null
+++ b/include/linux/usb/cdc-wdm.h
@@ -0,0 +1,19 @@
+/*
+ * USB CDC Device Management subdriver
+ *
+ * Copyright (c) 2012  Bjørn Mork <bjorn@mork.no>
+ *
+ * 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 __LINUX_USB_CDC_WDM_H
+#define __LINUX_USB_CDC_WDM_H
+
+extern struct usb_driver *usb_cdc_wdm_register(struct usb_interface *intf,
+					struct usb_endpoint_descriptor *ep,
+					int bufsize,
+					int (*manage_power)(struct usb_interface *, int));
+
+#endif /* __LINUX_USB_CDC_WDM_H */
diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h
index 0b83acd..f1d26b6 100644
--- a/include/linux/usb/ch11.h
+++ b/include/linux/usb/ch11.h
@@ -76,6 +76,11 @@
 #define USB_PORT_FEAT_C_BH_PORT_RESET		29
 #define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT	30
 
+/* USB 3.0 hub remote wake mask bits, see table 10-14 */
+#define USB_PORT_FEAT_REMOTE_WAKE_CONNECT	(1 << 8)
+#define USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT	(1 << 9)
+#define USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT	(1 << 10)
+
 /*
  * Hub Status and Hub Change results
  * See USB 2.0 spec Table 11-19 and Table 11-20
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index 3b6f628..af21f31 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -789,6 +789,11 @@
 	__u8  bDevCapabilityType;
 	__le32 bmAttributes;
 #define USB_LPM_SUPPORT			(1 << 1)	/* supports LPM */
+#define USB_BESL_SUPPORT		(1 << 2)	/* supports BESL */
+#define USB_BESL_BASELINE_VALID		(1 << 3)	/* Baseline BESL valid*/
+#define USB_BESL_DEEP_VALID		(1 << 4)	/* Deep BESL valid */
+#define USB_GET_BESL_BASELINE(p)	(((p) & (0xf << 8)) >> 8)
+#define USB_GET_BESL_DEEP(p)		(((p) & (0xf << 12)) >> 12)
 } __attribute__((packed));
 
 #define USB_DT_USB_EXT_CAP_SIZE	7
diff --git a/include/linux/usb/ehci_pdriver.h b/include/linux/usb/ehci_pdriver.h
new file mode 100644
index 0000000..1894f42
--- /dev/null
+++ b/include/linux/usb/ehci_pdriver.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __USB_CORE_EHCI_PDRIVER_H
+#define __USB_CORE_EHCI_PDRIVER_H
+
+/**
+ * struct usb_ehci_pdata - platform_data for generic ehci driver
+ *
+ * @caps_offset:	offset of the EHCI Capability Registers to the start of
+ *			the io memory region provided to the driver.
+ * @has_tt:		set to 1 if TT is integrated in root hub.
+ * @port_power_on:	set to 1 if the controller needs a power up after
+ *			initialization.
+ * @port_power_off:	set to 1 if the controller needs to be powered down
+ *			after initialization.
+ *
+ * These are general configuration options for the EHCI controller. All of
+ * these options are activating more or less workarounds for some hardware.
+ */
+struct usb_ehci_pdata {
+	int		caps_offset;
+	unsigned	has_tt:1;
+	unsigned	has_synopsys_hc_bug:1;
+	unsigned	big_endian_desc:1;
+	unsigned	big_endian_mmio:1;
+	unsigned	port_power_on:1;
+	unsigned	port_power_off:1;
+};
+
+#endif /* __USB_CORE_EHCI_PDRIVER_H */
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index da653b5..9517466 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -950,6 +950,16 @@
 
 /*-------------------------------------------------------------------------*/
 
+/* utility to simplify map/unmap of usb_requests to/from DMA */
+
+extern int usb_gadget_map_request(struct usb_gadget *gadget,
+		struct usb_request *req, int is_in);
+
+extern void usb_gadget_unmap_request(struct usb_gadget *gadget,
+		struct usb_request *req, int is_in);
+
+/*-------------------------------------------------------------------------*/
+
 /* utility wrapping a simple endpoint selection policy */
 
 extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index b2f62f3..5de4157 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -127,7 +127,7 @@
 	unsigned		authorized_default:1;
 	unsigned		has_tt:1;	/* Integrated TT in root hub */
 
-	int			irq;		/* irq allocated */
+	unsigned int		irq;		/* irq allocated */
 	void __iomem		*regs;		/* device memory/io */
 	u64			rsrc_start;	/* memory/io resource start */
 	u64			rsrc_len;	/* memory/io resource length */
@@ -412,6 +412,8 @@
 
 extern void usb_hc_died(struct usb_hcd *hcd);
 extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
+extern void usb_wakeup_notification(struct usb_device *hdev,
+		unsigned int portnum);
 
 /* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
 #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
diff --git a/include/linux/usb/intel_mid_otg.h b/include/linux/usb/intel_mid_otg.h
index a0ccf79..756cf55 100644
--- a/include/linux/usb/intel_mid_otg.h
+++ b/include/linux/usb/intel_mid_otg.h
@@ -104,11 +104,11 @@
 /*
  * the Intel MID (Langwell/Penwell) otg transceiver driver needs to interact
  * with device and host drivers to implement the USB OTG related feature. More
- * function members are added based on otg_transceiver data structure for this
+ * function members are added based on usb_phy data structure for this
  * purpose.
  */
 struct intel_mid_otg_xceiv {
-	struct otg_transceiver	otg;
+	struct usb_phy		otg;
 	struct otg_hsm		hsm;
 
 	/* base address */
@@ -147,7 +147,7 @@
 
 };
 static inline
-struct intel_mid_otg_xceiv *otg_to_mid_xceiv(struct otg_transceiver *otg)
+struct intel_mid_otg_xceiv *otg_to_mid_xceiv(struct usb_phy *otg)
 {
 	return container_of(otg, struct intel_mid_otg_xceiv, otg);
 }
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 00311fe..22a396c 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -160,7 +160,7 @@
  *               detection process.
  */
 struct msm_otg {
-	struct otg_transceiver otg;
+	struct usb_phy phy;
 	struct msm_otg_platform_data *pdata;
 	int irq;
 	struct clk *clk;
diff --git a/include/linux/usb/ohci_pdriver.h b/include/linux/usb/ohci_pdriver.h
new file mode 100644
index 0000000..2808f2a
--- /dev/null
+++ b/include/linux/usb/ohci_pdriver.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __USB_CORE_OHCI_PDRIVER_H
+#define __USB_CORE_OHCI_PDRIVER_H
+
+/**
+ * struct usb_ohci_pdata - platform_data for generic ohci driver
+ *
+ * @big_endian_desc:	BE descriptors
+ * @big_endian_mmio:	BE registers
+ * @no_big_frame_no:	no big endian frame_no shift
+ *
+ * These are general configuration options for the OHCI controller. All of
+ * these options are activating more or less workarounds for some hardware.
+ */
+struct usb_ohci_pdata {
+	unsigned	big_endian_desc:1;
+	unsigned	big_endian_mmio:1;
+	unsigned	no_big_frame_no:1;
+};
+
+#endif /* __USB_CORE_OHCI_PDRIVER_H */
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index d87f44f..f67810f 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -35,7 +35,7 @@
 	OTG_STATE_A_VBUS_ERR,
 };
 
-enum usb_xceiv_events {
+enum usb_phy_events {
 	USB_EVENT_NONE,         /* no events or cable disconnected */
 	USB_EVENT_VBUS,         /* vbus valid event */
 	USB_EVENT_ID,           /* id was grounded */
@@ -43,14 +43,39 @@
 	USB_EVENT_ENUMERATED,   /* gadget driver enumerated */
 };
 
-struct otg_transceiver;
+struct usb_phy;
 
 /* for transceivers connected thru an ULPI interface, the user must
  * provide access ops
  */
-struct otg_io_access_ops {
-	int (*read)(struct otg_transceiver *otg, u32 reg);
-	int (*write)(struct otg_transceiver *otg, u32 val, u32 reg);
+struct usb_phy_io_ops {
+	int (*read)(struct usb_phy *x, u32 reg);
+	int (*write)(struct usb_phy *x, u32 val, u32 reg);
+};
+
+struct usb_otg {
+	u8			default_a;
+
+	struct usb_phy		*phy;
+	struct usb_bus		*host;
+	struct usb_gadget	*gadget;
+
+	/* bind/unbind the host controller */
+	int	(*set_host)(struct usb_otg *otg, struct usb_bus *host);
+
+	/* bind/unbind the peripheral controller */
+	int	(*set_peripheral)(struct usb_otg *otg,
+					struct usb_gadget *gadget);
+
+	/* effective for A-peripheral, ignored for B devices */
+	int	(*set_vbus)(struct usb_otg *otg, bool enabled);
+
+	/* for B devices only:  start session with A-Host */
+	int	(*start_srp)(struct usb_otg *otg);
+
+	/* start or continue HNP role switch */
+	int	(*start_hnp)(struct usb_otg *otg);
+
 };
 
 /*
@@ -59,22 +84,20 @@
  * moment, using the transceiver, ID signal, HNP and sometimes static
  * configuration information (including "board isn't wired for otg").
  */
-struct otg_transceiver {
+struct usb_phy {
 	struct device		*dev;
 	const char		*label;
 	unsigned int		 flags;
 
-	u8			default_a;
 	enum usb_otg_state	state;
-	enum usb_xceiv_events	last_event;
+	enum usb_phy_events	last_event;
 
-	struct usb_bus		*host;
-	struct usb_gadget	*gadget;
+	struct usb_otg		*otg;
 
-	struct otg_io_access_ops	*io_ops;
-	void __iomem			*io_priv;
+	struct usb_phy_io_ops	*io_ops;
+	void __iomem		*io_priv;
 
-	/* for notification of usb_xceiv_events */
+	/* for notification of usb_phy_events */
 	struct atomic_notifier_head	notifier;
 
 	/* to pass extra port status to the root hub */
@@ -82,40 +105,22 @@
 	u16			port_change;
 
 	/* initialize/shutdown the OTG controller */
-	int	(*init)(struct otg_transceiver *otg);
-	void	(*shutdown)(struct otg_transceiver *otg);
-
-	/* bind/unbind the host controller */
-	int	(*set_host)(struct otg_transceiver *otg,
-				struct usb_bus *host);
-
-	/* bind/unbind the peripheral controller */
-	int	(*set_peripheral)(struct otg_transceiver *otg,
-				struct usb_gadget *gadget);
+	int	(*init)(struct usb_phy *x);
+	void	(*shutdown)(struct usb_phy *x);
 
 	/* effective for B devices, ignored for A-peripheral */
-	int	(*set_power)(struct otg_transceiver *otg,
+	int	(*set_power)(struct usb_phy *x,
 				unsigned mA);
 
-	/* effective for A-peripheral, ignored for B devices */
-	int	(*set_vbus)(struct otg_transceiver *otg,
-				bool enabled);
-
 	/* for non-OTG B devices: set transceiver into suspend mode */
-	int	(*set_suspend)(struct otg_transceiver *otg,
+	int	(*set_suspend)(struct usb_phy *x,
 				int suspend);
 
-	/* for B devices only:  start session with A-Host */
-	int	(*start_srp)(struct otg_transceiver *otg);
-
-	/* start or continue HNP role switch */
-	int	(*start_hnp)(struct otg_transceiver *otg);
-
 };
 
 
 /* for board-specific init logic */
-extern int otg_set_transceiver(struct otg_transceiver *);
+extern int usb_set_transceiver(struct usb_phy *);
 
 #if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE))
 /* sometimes transceivers are accessed only through e.g. ULPI */
@@ -132,50 +137,50 @@
 #endif
 
 /* helpers for direct access thru low-level io interface */
-static inline int otg_io_read(struct otg_transceiver *otg, u32 reg)
+static inline int usb_phy_io_read(struct usb_phy *x, u32 reg)
 {
-	if (otg->io_ops && otg->io_ops->read)
-		return otg->io_ops->read(otg, reg);
+	if (x->io_ops && x->io_ops->read)
+		return x->io_ops->read(x, reg);
 
 	return -EINVAL;
 }
 
-static inline int otg_io_write(struct otg_transceiver *otg, u32 val, u32 reg)
+static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg)
 {
-	if (otg->io_ops && otg->io_ops->write)
-		return otg->io_ops->write(otg, val, reg);
+	if (x->io_ops && x->io_ops->write)
+		return x->io_ops->write(x, val, reg);
 
 	return -EINVAL;
 }
 
 static inline int
-otg_init(struct otg_transceiver *otg)
+usb_phy_init(struct usb_phy *x)
 {
-	if (otg->init)
-		return otg->init(otg);
+	if (x->init)
+		return x->init(x);
 
 	return 0;
 }
 
 static inline void
-otg_shutdown(struct otg_transceiver *otg)
+usb_phy_shutdown(struct usb_phy *x)
 {
-	if (otg->shutdown)
-		otg->shutdown(otg);
+	if (x->shutdown)
+		x->shutdown(x);
 }
 
 /* for usb host and peripheral controller drivers */
 #ifdef CONFIG_USB_OTG_UTILS
-extern struct otg_transceiver *otg_get_transceiver(void);
-extern void otg_put_transceiver(struct otg_transceiver *);
+extern struct usb_phy *usb_get_transceiver(void);
+extern void usb_put_transceiver(struct usb_phy *);
 extern const char *otg_state_string(enum usb_otg_state state);
 #else
-static inline struct otg_transceiver *otg_get_transceiver(void)
+static inline struct usb_phy *usb_get_transceiver(void)
 {
 	return NULL;
 }
 
-static inline void otg_put_transceiver(struct otg_transceiver *x)
+static inline void usb_put_transceiver(struct usb_phy *x)
 {
 }
 
@@ -187,67 +192,84 @@
 
 /* Context: can sleep */
 static inline int
-otg_start_hnp(struct otg_transceiver *otg)
+otg_start_hnp(struct usb_otg *otg)
 {
-	return otg->start_hnp(otg);
+	if (otg && otg->start_hnp)
+		return otg->start_hnp(otg);
+
+	return -ENOTSUPP;
 }
 
 /* Context: can sleep */
 static inline int
-otg_set_vbus(struct otg_transceiver *otg, bool enabled)
+otg_set_vbus(struct usb_otg *otg, bool enabled)
 {
-	return otg->set_vbus(otg, enabled);
+	if (otg && otg->set_vbus)
+		return otg->set_vbus(otg, enabled);
+
+	return -ENOTSUPP;
 }
 
 /* for HCDs */
 static inline int
-otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+otg_set_host(struct usb_otg *otg, struct usb_bus *host)
 {
-	return otg->set_host(otg, host);
+	if (otg && otg->set_host)
+		return otg->set_host(otg, host);
+
+	return -ENOTSUPP;
 }
 
 /* for usb peripheral controller drivers */
 
 /* Context: can sleep */
 static inline int
-otg_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *periph)
+otg_set_peripheral(struct usb_otg *otg, struct usb_gadget *periph)
 {
-	return otg->set_peripheral(otg, periph);
+	if (otg && otg->set_peripheral)
+		return otg->set_peripheral(otg, periph);
+
+	return -ENOTSUPP;
 }
 
 static inline int
-otg_set_power(struct otg_transceiver *otg, unsigned mA)
+usb_phy_set_power(struct usb_phy *x, unsigned mA)
 {
-	return otg->set_power(otg, mA);
+	if (x && x->set_power)
+		return x->set_power(x, mA);
+	return 0;
 }
 
 /* Context: can sleep */
 static inline int
-otg_set_suspend(struct otg_transceiver *otg, int suspend)
+usb_phy_set_suspend(struct usb_phy *x, int suspend)
 {
-	if (otg->set_suspend != NULL)
-		return otg->set_suspend(otg, suspend);
+	if (x->set_suspend != NULL)
+		return x->set_suspend(x, suspend);
 	else
 		return 0;
 }
 
 static inline int
-otg_start_srp(struct otg_transceiver *otg)
+otg_start_srp(struct usb_otg *otg)
 {
-	return otg->start_srp(otg);
+	if (otg && otg->start_srp)
+		return otg->start_srp(otg);
+
+	return -ENOTSUPP;
 }
 
 /* notifiers */
 static inline int
-otg_register_notifier(struct otg_transceiver *otg, struct notifier_block *nb)
+usb_register_notifier(struct usb_phy *x, struct notifier_block *nb)
 {
-	return atomic_notifier_chain_register(&otg->notifier, nb);
+	return atomic_notifier_chain_register(&x->notifier, nb);
 }
 
 static inline void
-otg_unregister_notifier(struct otg_transceiver *otg, struct notifier_block *nb)
+usb_unregister_notifier(struct usb_phy *x, struct notifier_block *nb)
 {
-	atomic_notifier_chain_unregister(&otg->notifier, nb);
+	atomic_notifier_chain_unregister(&x->notifier, nb);
 }
 
 /* for OTG controller drivers (and maybe other stuff) */
diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h
index 0d3f988..547e59c 100644
--- a/include/linux/usb/renesas_usbhs.h
+++ b/include/linux/usb/renesas_usbhs.h
@@ -149,6 +149,7 @@
 	 * option:
 	 */
 	u32 has_otg:1; /* for controlling PWEN/EXTLP */
+	u32 has_sudmac:1; /* for SUDMAC */
 };
 
 /*
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 4267a9c..fbb666b 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -300,8 +300,10 @@
 #define to_usb_serial_driver(d) \
 	container_of(d, struct usb_serial_driver, driver)
 
-extern int  usb_serial_register(struct usb_serial_driver *driver);
-extern void usb_serial_deregister(struct usb_serial_driver *driver);
+extern int usb_serial_register_drivers(struct usb_driver *udriver,
+		struct usb_serial_driver * const serial_drivers[]);
+extern void usb_serial_deregister_drivers(struct usb_driver *udriver,
+		struct usb_serial_driver * const serial_drivers[]);
 extern void usb_serial_port_softint(struct usb_serial_port *port);
 
 extern int usb_serial_probe(struct usb_interface *iface,
@@ -389,5 +391,35 @@
 		printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg);	\
 } while (0)
 
+/*
+ * Macro for reporting errors in write path to avoid inifinite loop
+ * when port is used as a console.
+ */
+#define dev_err_console(usport, fmt, ...)				\
+do {									\
+	static bool __print_once;					\
+	struct usb_serial_port *__port = (usport);			\
+									\
+	if (!__port->port.console || !__print_once) {			\
+		__print_once = true;					\
+		dev_err(&__port->dev, fmt, ##__VA_ARGS__);		\
+	}								\
+} while (0)
+
+/*
+ * module_usb_serial_driver() - Helper macro for registering a USB Serial driver
+ * @__usb_driver: usb_driver struct to register
+ * @__serial_drivers: list of usb_serial drivers to register
+ *
+ * Helper macro for USB serial drivers which do not do anything special
+ * in module init/exit. This eliminates a lot of boilerplate. Each
+ * module may only use this macro once, and calling it replaces
+ * module_init() and module_exit()
+ *
+ */
+#define module_usb_serial_driver(__usb_driver, __serial_drivers)	\
+	module_driver(__usb_driver, usb_serial_register_drivers,	\
+		       usb_serial_deregister_drivers, __serial_drivers)
+
 #endif /* __LINUX_USB_SERIAL_H */
 
diff --git a/include/linux/usb/storage.h b/include/linux/usb/storage.h
index d7fc910..cb33fff 100644
--- a/include/linux/usb/storage.h
+++ b/include/linux/usb/storage.h
@@ -45,4 +45,42 @@
 
 #define USB_PR_DEVICE	0xff		/* Use device's value */
 
+ /*
+  * Bulk only data structures
+  */
+
+/* command block wrapper */
+struct bulk_cb_wrap {
+	__le32	Signature;		/* contains 'USBC' */
+	__u32	Tag;			/* unique per command id */
+	__le32	DataTransferLength;	/* size of data */
+	__u8	Flags;			/* direction in bit 0 */
+	__u8	Lun;			/* LUN normally 0 */
+	__u8	Length;			/* of of the CDB */
+	__u8	CDB[16];		/* max command */
+};
+
+#define US_BULK_CB_WRAP_LEN	31
+#define US_BULK_CB_SIGN		0x43425355	/*spells out USBC */
+#define US_BULK_FLAG_IN		(1 << 7)
+#define US_BULK_FLAG_OUT	0
+
+/* command status wrapper */
+struct bulk_cs_wrap {
+	__le32	Signature;	/* should = 'USBS' */
+	__u32	Tag;		/* same as original command */
+	__le32	Residue;	/* amount not transferred */
+	__u8	Status;		/* see below */
+};
+
+#define US_BULK_CS_WRAP_LEN	13
+#define US_BULK_CS_SIGN		0x53425355      /* spells out 'USBS' */
+#define US_BULK_STAT_OK		0
+#define US_BULK_STAT_FAIL	1
+#define US_BULK_STAT_PHASE	2
+
+/* bulk-only class specific requests */
+#define US_BULK_RESET_REQUEST   0xff
+#define US_BULK_GET_MAX_LUN     0xfe
+
 #endif
diff --git a/include/linux/usb/uas.h b/include/linux/usb/uas.h
new file mode 100644
index 0000000..9a988e4
--- /dev/null
+++ b/include/linux/usb/uas.h
@@ -0,0 +1,69 @@
+#ifndef __USB_UAS_H__
+#define __USB_UAS_H__
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
+/* Common header for all IUs */
+struct iu {
+	__u8 iu_id;
+	__u8 rsvd1;
+	__be16 tag;
+};
+
+enum {
+	IU_ID_COMMAND		= 0x01,
+	IU_ID_STATUS		= 0x03,
+	IU_ID_RESPONSE		= 0x04,
+	IU_ID_TASK_MGMT		= 0x05,
+	IU_ID_READ_READY	= 0x06,
+	IU_ID_WRITE_READY	= 0x07,
+};
+
+struct command_iu {
+	__u8 iu_id;
+	__u8 rsvd1;
+	__be16 tag;
+	__u8 prio_attr;
+	__u8 rsvd5;
+	__u8 len;
+	__u8 rsvd7;
+	struct scsi_lun lun;
+	__u8 cdb[16];	/* XXX: Overflow-checking tools may misunderstand */
+};
+
+/*
+ * Also used for the Read Ready and Write Ready IUs since they have the
+ * same first four bytes
+ */
+struct sense_iu {
+	__u8 iu_id;
+	__u8 rsvd1;
+	__be16 tag;
+	__be16 status_qual;
+	__u8 status;
+	__u8 rsvd7[7];
+	__be16 len;
+	__u8 sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+struct usb_pipe_usage_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+
+	__u8  bPipeID;
+	__u8  Reserved;
+} __attribute__((__packed__));
+
+enum {
+	CMD_PIPE_ID		= 1,
+	STATUS_PIPE_ID		= 2,
+	DATA_IN_PIPE_ID		= 3,
+	DATA_OUT_PIPE_ID	= 4,
+
+	UAS_SIMPLE_TAG		= 0,
+	UAS_HEAD_TAG		= 1,
+	UAS_ORDERED_TAG		= 2,
+	UAS_ACA			= 4,
+};
+#endif
diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h
index 9595796..6f033a4 100644
--- a/include/linux/usb/ulpi.h
+++ b/include/linux/usb/ulpi.h
@@ -181,12 +181,12 @@
 
 /*-------------------------------------------------------------------------*/
 
-struct otg_transceiver *otg_ulpi_create(struct otg_io_access_ops *ops,
+struct usb_phy *otg_ulpi_create(struct usb_phy_io_ops *ops,
 					unsigned int flags);
 
 #ifdef CONFIG_USB_ULPI_VIEWPORT
 /* access ops for controllers with a viewport register */
-extern struct otg_io_access_ops ulpi_viewport_access_ops;
+extern struct usb_phy_io_ops ulpi_viewport_access_ops;
 #endif
 
 #endif /* __LINUX_USB_ULPI_H */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 77273f2..b3a1c2d 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -136,6 +136,7 @@
 	unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
 	unsigned skip_ms_page_8:1;	/* do not use MODE SENSE page 0x08 */
 	unsigned skip_ms_page_3f:1;	/* do not use MODE SENSE page 0x3f */
+	unsigned skip_vpd_pages:1;	/* do not read VPD pages */
 	unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */
 	unsigned no_start_on_add:1;	/* do not issue start on add */
 	unsigned allow_restart:1; /* issue START_UNIT in error handler */
@@ -246,8 +247,10 @@
 	unsigned int		single_lun:1;	/* Indicates we should only
 						 * allow I/O to one of the luns
 						 * for the device at a time. */
-	unsigned int		pdt_1f_for_no_lun;	/* PDT = 0x1f */
-						/* means no lun present */
+	unsigned int		pdt_1f_for_no_lun:1;	/* PDT = 0x1f
+						 * means no lun present. */
+	unsigned int		no_report_luns:1;	/* Don't use
+						 * REPORT LUNS for scanning. */
 	/* commands actually active on LLD. protected by host lock. */
 	unsigned int		target_busy;
 	/*
diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c
index b9c7986..53452c3 100644
--- a/tools/usb/ffs-test.c
+++ b/tools/usb/ffs-test.c
@@ -2,7 +2,7 @@
  * ffs-test.c.c -- user mode filesystem api for usb composite function
  *
  * Copyright (C) 2010 Samsung Electronics
- *                    Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
+ *                    Author: Michal Nazarewicz <mina86@mina86.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
diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c
index f08e894..6e0f567 100644
--- a/tools/usb/testusb.c
+++ b/tools/usb/testusb.c
@@ -3,7 +3,7 @@
 /*
  * Copyright (c) 2002 by David Brownell
  * Copyright (c) 2010 by Samsung Electronics
- * Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
+ * Author: Michal Nazarewicz <mina86@mina86.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