summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-davinci/usb.c4
-rw-r--r--arch/arm/mach-omap2/Makefile6
-rw-r--r--arch/arm/mach-omap2/board-4430sdp.c17
-rw-r--r--arch/arm/mach-omap2/board-n8x0.c5
-rw-r--r--arch/arm/mach-omap2/board-omap4panda.c14
-rw-r--r--arch/arm/mach-omap2/clock2420_data.c2
-rw-r--r--arch/arm/mach-omap2/clock2430_data.c2
-rw-r--r--arch/arm/mach-omap2/clock3xxx_data.c8
-rw-r--r--arch/arm/mach-omap2/clock44xx_data.c2
-rw-r--r--arch/arm/mach-omap2/omap_phy_internal.c149
-rw-r--r--arch/arm/mach-omap2/usb-musb.c102
-rw-r--r--arch/arm/mach-omap2/usb-tusb6010.c2
-rw-r--r--arch/arm/plat-omap/include/plat/usb.h9
-rw-r--r--arch/blackfin/mach-bf527/boards/ad7160eval.c2
-rw-r--r--arch/blackfin/mach-bf527/boards/cm_bf527.c2
-rw-r--r--arch/blackfin/mach-bf527/boards/ezbrd.c2
-rw-r--r--arch/blackfin/mach-bf527/boards/ezkit.c2
-rw-r--r--arch/blackfin/mach-bf527/boards/tll6527m.c2
-rw-r--r--arch/blackfin/mach-bf548/boards/cm_bf548.c2
-rw-r--r--arch/blackfin/mach-bf548/boards/ezkit.c2
-rw-r--r--drivers/mfd/twl-core.c44
-rw-r--r--drivers/mfd/twl6030-irq.c9
-rw-r--r--drivers/usb/gadget/gadget_chips.h2
-rw-r--r--drivers/usb/musb/Kconfig77
-rw-r--r--drivers/usb/musb/Makefile21
-rw-r--r--drivers/usb/musb/am35x.c410
-rw-r--r--drivers/usb/musb/blackfin.c229
-rw-r--r--drivers/usb/musb/da8xx.c170
-rw-r--r--drivers/usb/musb/davinci.c174
-rw-r--r--drivers/usb/musb/musb_core.c191
-rw-r--r--drivers/usb/musb/musb_core.h190
-rw-r--r--drivers/usb/musb/musb_io.h4
-rw-r--r--drivers/usb/musb/musb_regs.h4
-rw-r--r--drivers/usb/musb/musb_virthub.c2
-rw-r--r--drivers/usb/musb/omap2430.c374
-rw-r--r--drivers/usb/musb/tusb6010.c181
-rw-r--r--drivers/usb/musb/ux500.c216
-rw-r--r--drivers/usb/otg/Kconfig12
-rw-r--r--drivers/usb/otg/Makefile1
-rw-r--r--drivers/usb/otg/twl6030-usb.c493
-rw-r--r--include/linux/i2c/twl.h7
-rw-r--r--include/linux/usb/musb.h8
42 files changed, 2526 insertions, 629 deletions
diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c
index b0d6b07431c0..23d2b6d9fa63 100644
--- a/arch/arm/mach-davinci/usb.c
+++ b/arch/arm/mach-davinci/usb.c
@@ -76,7 +76,7 @@ static struct resource usb_resources[] = {
 static u64 usb_dmamask = DMA_BIT_MASK(32);
 
 static struct platform_device usb_dev = {
-	.name           = "musb_hdrc",
+	.name           = "musb-davinci",
 	.id             = -1,
 	.dev = {
 		.platform_data		= &usb_data,
@@ -112,6 +112,7 @@ static struct resource da8xx_usb20_resources[] = {
 	{
 		.start		= IRQ_DA8XX_USB_INT,
 		.flags		= IORESOURCE_IRQ,
+		.name		= "mc",
 	},
 };
 
@@ -123,6 +124,7 @@ int __init da8xx_register_usb20(unsigned mA, unsigned potpgt)
 
 	usb_dev.resource = da8xx_usb20_resources;
 	usb_dev.num_resources = ARRAY_SIZE(da8xx_usb20_resources);
+	usb_dev.name = "musb-da8xx";
 
 	return platform_device_register(&usb_dev);
 }
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 60e51bcf53bd..194863680fe0 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -168,9 +168,11 @@ obj-$(CONFIG_MACH_IGEP0030)		+= board-igep0030.o \
 obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)	+= board-omap3touchbook.o \
 					   hsmmc.o
 obj-$(CONFIG_MACH_OMAP_4430SDP)		+= board-4430sdp.o \
-					   hsmmc.o
+					   hsmmc.o \
+					   omap_phy_internal.o
 obj-$(CONFIG_MACH_OMAP4_PANDA)		+= board-omap4panda.o \
-					   hsmmc.o
+					   hsmmc.o \
+					   omap_phy_internal.o
 
 obj-$(CONFIG_MACH_OMAP3517EVM)		+= board-am3517evm.o
 
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index d7cb9680b4fa..5aef69521e36 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -238,10 +238,17 @@ static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
 
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type		= MUSB_INTERFACE_UTMI,
-	.mode			= MUSB_PERIPHERAL,
+	.mode			= MUSB_OTG,
 	.power			= 100,
 };
 
+static struct twl4030_usb_data omap4_usbphy_data = {
+	.phy_init	= omap4430_phy_init,
+	.phy_exit	= omap4430_phy_exit,
+	.phy_power	= omap4430_phy_power,
+	.phy_set_clock	= omap4430_phy_set_clk,
+};
+
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
@@ -461,6 +468,7 @@ static struct twl4030_platform_data sdp4430_twldata = {
 	.vaux1		= &sdp4430_vaux1,
 	.vaux2		= &sdp4430_vaux2,
 	.vaux3		= &sdp4430_vaux3,
+	.usb		= &omap4_usbphy_data
 };
 
 static struct i2c_board_info __initdata sdp4430_i2c_boardinfo[] = {
@@ -533,12 +541,7 @@ static void __init omap_4430sdp_init(void)
 		gpio_direction_output(OMAP4SDP_MDM_PWR_EN_GPIO, 1);
 	}
 	usb_ehci_init(&ehci_pdata);
-
-	/* OMAP4 SDP uses internal transceiver so register nop transceiver */
-	usb_nop_xceiv_register();
-	/* FIXME: allow multi-omap to boot until musb is updated for omap4 */
-	if (!cpu_is_omap44xx())
-		usb_musb_init(&musb_board_data);
+	usb_musb_init(&musb_board_data);
 
 	status = omap_ethernet_init();
 	if (status) {
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index e823c7042ab3..62e3ea007c76 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -46,8 +46,7 @@ static struct device *mmc_device;
 #define TUSB6010_GPIO_ENABLE	0
 #define TUSB6010_DMACHAN	0x3f
 
-#if defined(CONFIG_USB_TUSB6010) || \
-	defined(CONFIG_USB_TUSB6010_MODULE)
+#ifdef CONFIG_USB_MUSB_TUSB6010
 /*
  * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
  * 1.5 V voltage regulators of PM companion chip. Companion chip will then
@@ -134,7 +133,7 @@ err:
 
 static void __init n8x0_usb_init(void) {}
 
-#endif /*CONFIG_USB_TUSB6010 */
+#endif /*CONFIG_USB_MUSB_TUSB6010 */
 
 
 static struct omap2_mcspi_device_config p54spi_mcspi_config = {
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 1ecd0a6cefb7..9207c5849c0e 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -133,10 +133,17 @@ error1:
 
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type		= MUSB_INTERFACE_UTMI,
-	.mode			= MUSB_PERIPHERAL,
+	.mode			= MUSB_OTG,
 	.power			= 100,
 };
 
+static struct twl4030_usb_data omap4_usbphy_data = {
+	.phy_init	= omap4430_phy_init,
+	.phy_exit	= omap4430_phy_exit,
+	.phy_power	= omap4430_phy_power,
+	.phy_set_clock	= omap4430_phy_set_clk,
+};
+
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
@@ -345,6 +352,7 @@ static struct twl4030_platform_data omap4_panda_twldata = {
 	.vaux1		= &omap4_panda_vaux1,
 	.vaux2		= &omap4_panda_vaux2,
 	.vaux3		= &omap4_panda_vaux3,
+	.usb		= &omap4_usbphy_data,
 };
 
 static struct i2c_board_info __initdata omap4_panda_i2c_boardinfo[] = {
@@ -377,9 +385,7 @@ static void __init omap4_panda_init(void)
 	/* OMAP4 Panda uses internal transceiver so register nop transceiver */
 	usb_nop_xceiv_register();
 	omap4_ehci_init();
-	/* FIXME: allow multi-omap to boot until musb is updated for omap4 */
-	if (!cpu_is_omap44xx())
-		usb_musb_init(&musb_board_data);
+	usb_musb_init(&musb_board_data);
 }
 
 static void __init omap4_panda_map_io(void)
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index 21f856252ad8..831e25c89d2d 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1877,7 +1877,7 @@ static struct omap_clk omap2420_clks[] = {
 	CLK("omap-aes",	"ick",	&aes_ick,	CK_242X),
 	CLK(NULL,	"pka_ick",	&pka_ick,	CK_242X),
 	CLK(NULL,	"usb_fck",	&usb_fck,	CK_242X),
-	CLK("musb_hdrc",	"fck",	&osc_ck,	CK_242X),
+	CLK("musb-hdrc",	"fck",	&osc_ck,	CK_242X),
 };
 
 /*
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index e32afcbdfb88..a9c60b7843e2 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -1983,7 +1983,7 @@ static struct omap_clk omap2430_clks[] = {
 	CLK("omap-aes",	"ick",	&aes_ick,	CK_243X),
 	CLK(NULL,	"pka_ick",	&pka_ick,	CK_243X),
 	CLK(NULL,	"usb_fck",	&usb_fck,	CK_243X),
-	CLK("musb_hdrc",	"ick",	&usbhs_ick,	CK_243X),
+	CLK("musb-omap2430",	"ick",	&usbhs_ick,	CK_243X),
 	CLK("mmci-omap-hs.0", "ick",	&mmchs1_ick,	CK_243X),
 	CLK("mmci-omap-hs.0", "fck",	&mmchs1_fck,	CK_243X),
 	CLK("mmci-omap-hs.1", "ick",	&mmchs2_ick,	CK_243X),
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index a04cb03db51f..0579604d4f25 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -3306,8 +3306,8 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck_3430es1,	CK_3430ES1),
 	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck_3430es2,	CK_3430ES2),
 	CLK(NULL,	"core_l3_ick",	&core_l3_ick,	CK_3XXX),
-	CLK("musb_hdrc",	"ick",	&hsotgusb_ick_3430es1,	CK_3430ES1),
-	CLK("musb_hdrc",	"ick",	&hsotgusb_ick_3430es2,	CK_3430ES2),
+	CLK("musb-omap2430",	"ick",	&hsotgusb_ick_3430es1,	CK_3430ES1),
+	CLK("musb-omap2430",	"ick",	&hsotgusb_ick_3430es2,	CK_3430ES2),
 	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_3XXX),
 	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_3XXX),
 	CLK(NULL,	"security_l3_ick", &security_l3_ick, CK_343X),
@@ -3442,8 +3442,8 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK("davinci_emac",	"phy_clk",	&emac_fck,	CK_AM35XX),
 	CLK("vpfe-capture",	"master",	&vpfe_ick,	CK_AM35XX),
 	CLK("vpfe-capture",	"slave",	&vpfe_fck,	CK_AM35XX),
-	CLK("musb_hdrc",	"ick",		&hsotgusb_ick_am35xx,	CK_AM35XX),
-	CLK("musb_hdrc",	"fck",		&hsotgusb_fck_am35xx,	CK_AM35XX),
+	CLK("musb-am35x",	"ick",		&hsotgusb_ick_am35xx,	CK_AM35XX),
+	CLK("musb-am35x",	"fck",		&hsotgusb_fck_am35xx,	CK_AM35XX),
 	CLK(NULL,	"hecc_ck",	&hecc_ck,	CK_AM35XX),
 	CLK(NULL,	"uart4_ick",	&uart4_ick_am35xx,	CK_AM35XX),
 };
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index f473e8922664..bfcd19f8368c 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -2953,7 +2953,7 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK("ehci-omap.0",	"usbhost_ick",		&dummy_ck,		CK_443X),
 	CLK(NULL,	"otg_60m_gfclk",		&otg_60m_gfclk,	CK_443X),
 	CLK(NULL,	"usb_otg_hs_xclk",		&usb_otg_hs_xclk,	CK_443X),
-	CLK("musb_hdrc",	"ick",				&usb_otg_hs_ick,	CK_443X),
+	CLK("musb-omap2430",	"ick",				&usb_otg_hs_ick,	CK_443X),
 	CLK(NULL,	"usb_phy_cm_clk32k",		&usb_phy_cm_clk32k,	CK_443X),
 	CLK(NULL,	"usb_tll_hs_usb_ch2_clk",	&usb_tll_hs_usb_ch2_clk,	CK_443X),
 	CLK(NULL,	"usb_tll_hs_usb_ch0_clk",	&usb_tll_hs_usb_ch0_clk,	CK_443X),
diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c
new file mode 100644
index 000000000000..745252c60e32
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_phy_internal.c
@@ -0,0 +1,149 @@
+/*
+  * This file configures the internal USB PHY in OMAP4430. Used
+  * with TWL6030 transceiver and MUSB on OMAP4430.
+  *
+  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+  * (at your option) any later version.
+  *
+  * Author: Hema HK <hemahk@ti.com>
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  *
+  * You should have received a copy of the GNU General Public License
+  * along with this program; if not, write to the Free Software
+  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  *
+  */
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/usb.h>
+
+#include <plat/usb.h>
+
+/* OMAP control module register for UTMI PHY */
+#define CONTROL_DEV_CONF		0x300
+#define PHY_PD				0x1
+
+#define USBOTGHS_CONTROL		0x33c
+#define	AVALID				BIT(0)
+#define	BVALID				BIT(1)
+#define	VBUSVALID			BIT(2)
+#define	SESSEND				BIT(3)
+#define	IDDIG				BIT(4)
+
+static struct clk *phyclk, *clk48m, *clk32k;
+static void __iomem *ctrl_base;
+
+int omap4430_phy_init(struct device *dev)
+{
+	ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
+	if (!ctrl_base) {
+		dev_err(dev, "control module ioremap failed\n");
+		return -ENOMEM;
+	}
+	/* Power down the phy */
+	__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
+	phyclk = clk_get(dev, "ocp2scp_usb_phy_ick");
+
+	if (IS_ERR(phyclk)) {
+		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_ick\n");
+		iounmap(ctrl_base);
+		return PTR_ERR(phyclk);
+	}
+
+	clk48m = clk_get(dev, "ocp2scp_usb_phy_phy_48m");
+	if (IS_ERR(clk48m)) {
+		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_phy_48m\n");
+		clk_put(phyclk);
+		iounmap(ctrl_base);
+		return PTR_ERR(clk48m);
+	}
+
+	clk32k = clk_get(dev, "usb_phy_cm_clk32k");
+	if (IS_ERR(clk32k)) {
+		dev_err(dev, "cannot clk_get usb_phy_cm_clk32k\n");
+		clk_put(phyclk);
+		clk_put(clk48m);
+		iounmap(ctrl_base);
+		return PTR_ERR(clk32k);
+	}
+	return 0;
+}
+
+int omap4430_phy_set_clk(struct device *dev, int on)
+{
+	static int state;
+
+	if (on && !state) {
+		/* Enable the phy clocks */
+		clk_enable(phyclk);
+		clk_enable(clk48m);
+		clk_enable(clk32k);
+		state = 1;
+	} else if (state) {
+		/* Disable the phy clocks */
+		clk_disable(phyclk);
+		clk_disable(clk48m);
+		clk_disable(clk32k);
+		state = 0;
+	}
+	return 0;
+}
+
+int omap4430_phy_power(struct device *dev, int ID, int on)
+{
+	if (on) {
+		/* enabled the clocks */
+		omap4430_phy_set_clk(dev, 1);
+		/* power on the phy */
+		if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) {
+			__raw_writel(~PHY_PD, ctrl_base + CONTROL_DEV_CONF);
+			mdelay(200);
+		}
+		if (ID)
+			/* enable VBUS valid, IDDIG groung */
+			__raw_writel(AVALID | VBUSVALID, ctrl_base +
+							USBOTGHS_CONTROL);
+		else
+			/*
+			 * Enable VBUS Valid, AValid and IDDIG
+			 * high impedence
+			 */
+			__raw_writel(IDDIG | AVALID | VBUSVALID,
+						ctrl_base + USBOTGHS_CONTROL);
+	} else {
+		/* Enable session END and IDIG to high impedence. */
+		__raw_writel(SESSEND | IDDIG, ctrl_base +
+					USBOTGHS_CONTROL);
+		/* Disable the clocks */
+		omap4430_phy_set_clk(dev, 0);
+		/* Power down the phy */
+		__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
+	}
+
+	return 0;
+}
+
+int omap4430_phy_exit(struct device *dev)
+{
+	if (ctrl_base)
+		iounmap(ctrl_base);
+	if (phyclk)
+		clk_put(phyclk);
+	if (clk48m)
+		clk_put(clk48m);
+	if (clk32k)
+		clk_put(clk32k);
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 8dae0fa5905e..5298949d4b11 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -30,8 +30,101 @@
 #include <mach/irqs.h>
 #include <mach/am35xx.h>
 #include <plat/usb.h>
+#include "control.h"
 
-#ifdef CONFIG_USB_MUSB_SOC
+#if defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined (CONFIG_USB_MUSB_AM35X)
+
+static void am35x_musb_reset(void)
+{
+	u32	regval;
+
+	/* Reset the musb interface */
+	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
+
+	regval |= AM35XX_USBOTGSS_SW_RST;
+	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
+
+	regval &= ~AM35XX_USBOTGSS_SW_RST;
+	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
+
+	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
+}
+
+static void am35x_musb_phy_power(u8 on)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(100);
+	u32 devconf2;
+
+	if (on) {
+		/*
+		 * Start the on-chip PHY and its PLL.
+		 */
+		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+		devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
+		devconf2 |= CONF2_PHY_PLLON;
+
+		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+
+		pr_info(KERN_INFO "Waiting for PHY clock good...\n");
+		while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
+				& CONF2_PHYCLKGD)) {
+			cpu_relax();
+
+			if (time_after(jiffies, timeout)) {
+				pr_err(KERN_ERR "musb PHY clock good timed out\n");
+				break;
+			}
+		}
+	} else {
+		/*
+		 * Power down the on-chip PHY.
+		 */
+		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+		devconf2 &= ~CONF2_PHY_PLLON;
+		devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN;
+		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+	}
+}
+
+static void am35x_musb_clear_irq(void)
+{
+	u32 regval;
+
+	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+	regval |= AM35XX_USBOTGSS_INT_CLR;
+	omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
+	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+}
+
+static void am35x_musb_set_mode(u8 musb_mode)
+{
+	u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+	devconf2 &= ~CONF2_OTGMODE;
+	switch (musb_mode) {
+#ifdef	CONFIG_USB_MUSB_HDRC_HCD
+	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
+		devconf2 |= CONF2_FORCE_HOST;
+		break;
+#endif
+#ifdef	CONFIG_USB_GADGET_MUSB_HDRC
+	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
+		devconf2 |= CONF2_FORCE_DEVICE;
+		break;
+#endif
+#ifdef	CONFIG_USB_MUSB_OTG
+	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
+		devconf2 |= CONF2_NO_OVERRIDE;
+		break;
+#endif
+	default:
+		pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode);
+	}
+
+	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+}
 
 static struct resource musb_resources[] = {
 	[0] = { /* start and end set dynamically */
@@ -77,7 +170,7 @@ static struct musb_hdrc_platform_data musb_plat = {
 static u64 musb_dmamask = DMA_BIT_MASK(32);
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-omap2430",
 	.id		= -1,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
@@ -93,8 +186,13 @@ void __init usb_musb_init(struct omap_musb_board_data *board_data)
 	if (cpu_is_omap243x()) {
 		musb_resources[0].start = OMAP243X_HS_BASE;
 	} else if (cpu_is_omap3517() || cpu_is_omap3505()) {
+		musb_device.name = "musb-am35x";
 		musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE;
 		musb_resources[1].start = INT_35XX_USBOTG_IRQ;
+		board_data->set_phy_power = am35x_musb_phy_power;
+		board_data->clear_irq = am35x_musb_clear_irq;
+		board_data->set_mode = am35x_musb_set_mode;
+		board_data->reset = am35x_musb_reset;
 	} else if (cpu_is_omap34xx()) {
 		musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
 	} else if (cpu_is_omap44xx()) {
diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
index 64a0112b70a5..7cb3c18a5e20 100644
--- a/arch/arm/mach-omap2/usb-tusb6010.c
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -223,7 +223,7 @@ static struct resource tusb_resources[] = {
 static u64 tusb_dmamask = ~(u32)0;
 
 static struct platform_device tusb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-tusb",
 	.id		= -1,
 	.dev = {
 		.dma_mask		= &tusb_dmamask,
diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
index 9b1893f31fc8..450a332f1009 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -70,6 +70,10 @@ struct omap_musb_board_data {
 	u8	mode;
 	u16	power;
 	unsigned extvbus:1;
+	void	(*set_phy_power)(u8 on);
+	void	(*clear_irq)(void);
+	void	(*set_mode)(u8 mode);
+	void	(*reset)(void);
 };
 
 enum musb_interface    {MUSB_INTERFACE_ULPI, MUSB_INTERFACE_UTMI};
@@ -80,6 +84,11 @@ extern void usb_ehci_init(const struct ehci_hcd_omap_platform_data *pdata);
 
 extern void usb_ohci_init(const struct ohci_hcd_omap_platform_data *pdata);
 
+extern int omap4430_phy_power(struct device *dev, int ID, int on);
+extern int omap4430_phy_set_clk(struct device *dev, int on);
+extern int omap4430_phy_init(struct device *dev);
+extern int omap4430_phy_exit(struct device *dev);
+
 #endif
 
 
diff --git a/arch/blackfin/mach-bf527/boards/ad7160eval.c b/arch/blackfin/mach-bf527/boards/ad7160eval.c
index fc767ac76381..52295fff5577 100644
--- a/arch/blackfin/mach-bf527/boards/ad7160eval.c
+++ b/arch/blackfin/mach-bf527/boards/ad7160eval.c
@@ -83,7 +83,7 @@ static struct musb_hdrc_platform_data musb_plat = {
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c
index f714d7be35b9..50533edc3994 100644
--- a/arch/blackfin/mach-bf527/boards/cm_bf527.c
+++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c
@@ -120,7 +120,7 @@ static struct musb_hdrc_platform_data musb_plat = {
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c
index 315eec930604..d06177b5fe22 100644
--- a/arch/blackfin/mach-bf527/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf527/boards/ezbrd.c
@@ -84,7 +84,7 @@ static struct musb_hdrc_platform_data musb_plat = {
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index 273731279740..35a88a5a5013 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -124,7 +124,7 @@ static struct musb_hdrc_platform_data musb_plat = {
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
diff --git a/arch/blackfin/mach-bf527/boards/tll6527m.c b/arch/blackfin/mach-bf527/boards/tll6527m.c
index 9ec575729e2c..130861bd2589 100644
--- a/arch/blackfin/mach-bf527/boards/tll6527m.c
+++ b/arch/blackfin/mach-bf527/boards/tll6527m.c
@@ -91,7 +91,7 @@ static struct musb_hdrc_platform_data musb_plat = {
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c
index 3e3dfb23f94e..4c2ee6789099 100644
--- a/arch/blackfin/mach-bf548/boards/cm_bf548.c
+++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c
@@ -520,7 +520,7 @@ static struct musb_hdrc_platform_data musb_plat = {
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
index 9ff166d6f00d..4f03fbc4c9be 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -625,7 +625,7 @@ static struct musb_hdrc_platform_data musb_plat = {
 static u64 musb_dmamask = ~(u32)0;
 
 static struct platform_device musb_device = {
-	.name		= "musb_hdrc",
+	.name		= "musb-blackfin",
 	.id		= 0,
 	.dev = {
 		.dma_mask		= &musb_dmamask,
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 35275ba7096f..12abd5b924b3 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -95,7 +95,8 @@
 #define twl_has_rtc()	false
 #endif
 
-#if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE)
+#if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE) ||\
+	defined(CONFIG_TWL6030_USB) || defined(CONFIG_TWL6030_USB_MODULE)
 #define twl_has_usb()	true
 #else
 #define twl_has_usb()	false
@@ -682,6 +683,43 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
 			usb3v1.dev = child;
 		}
 	}
+	if (twl_has_usb() && pdata->usb && twl_class_is_6030()) {
+
+		static struct regulator_consumer_supply usb3v3 = {
+			.supply =	"vusb",
+		};
+
+		if (twl_has_regulator()) {
+			/* this is a template that gets copied */
+			struct regulator_init_data usb_fixed = {
+				.constraints.valid_modes_mask =
+					REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+				.constraints.valid_ops_mask =
+					REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+			};
+
+			child = add_regulator_linked(TWL6030_REG_VUSB,
+						      &usb_fixed, &usb3v3, 1);
+			if (IS_ERR(child))
+				return PTR_ERR(child);
+		}
+
+		child = add_child(0, "twl6030_usb",
+			pdata->usb, sizeof(*pdata->usb),
+			true,
+			/* irq1 = VBUS_PRES, irq0 = USB ID */
+			pdata->irq_base + USBOTG_INTR_OFFSET,
+			pdata->irq_base + USB_PRES_INTR_OFFSET);
+
+		if (IS_ERR(child))
+			return PTR_ERR(child);
+		/* we need to connect regulators to this transceiver */
+		if (twl_has_regulator() && child)
+			usb3v3.dev = child;
+
+	}
 
 	if (twl_has_watchdog()) {
 		child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0);
@@ -815,10 +853,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
 		if (IS_ERR(child))
 			return PTR_ERR(child);
 
-		child = add_regulator(TWL6030_REG_VUSB, pdata->vusb);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
 		child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1);
 		if (IS_ERR(child))
 			return PTR_ERR(child);
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index aaedb11d9d2c..06c8955907e9 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -74,7 +74,7 @@ static int twl6030_interrupt_mapping[24] = {
 	USBOTG_INTR_OFFSET,	/* Bit 16	ID_WKUP			*/
 	USBOTG_INTR_OFFSET,	/* Bit 17	VBUS_WKUP		*/
 	USBOTG_INTR_OFFSET,	/* Bit 18	ID			*/
-	USBOTG_INTR_OFFSET,	/* Bit 19	VBUS			*/
+	USB_PRES_INTR_OFFSET,	/* Bit 19	VBUS			*/
 	CHARGER_INTR_OFFSET,	/* Bit 20	CHRG_CTRL		*/
 	CHARGER_INTR_OFFSET,	/* Bit 21	EXT_CHRG		*/
 	CHARGER_INTR_OFFSET,	/* Bit 22	INT_CHRG		*/
@@ -128,6 +128,13 @@ static int twl6030_irq_thread(void *data)
 
 		sts.bytes[3] = 0; /* Only 24 bits are valid*/
 
+		/*
+		 * Since VBUS status bit is not reliable for VBUS disconnect
+		 * use CHARGER VBUS detection status bit instead.
+		 */
+		if (sts.bytes[2] & 0x10)
+			sts.bytes[2] |= 0x08;
+
 		for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++) {
 			local_irq_disable();
 			if (sts.int_sts & 0x1) {
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index ad2114e87511..5c2720d64ffa 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -96,7 +96,7 @@
 
 /* Mentor high speed "dual role" controller, in peripheral role */
 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
-#define gadget_is_musbhdrc(g)	!strcmp("musb_hdrc", (g)->name)
+#define gadget_is_musbhdrc(g)	!strcmp("musb-hdrc", (g)->name)
 #else
 #define gadget_is_musbhdrc(g)	0
 #endif
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 341a37a469bd..4cbb7e4b368d 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -12,6 +12,7 @@ config USB_MUSB_HDRC
 	depends on (ARM || (BF54x && !BF544) || (BF52x && !BF522 && !BF523))
 	select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN)
 	select TWL4030_USB if MACH_OMAP_3430SDP
+	select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
 	select USB_OTG_UTILS
 	tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
 	help
@@ -30,57 +31,41 @@ config USB_MUSB_HDRC
 	  If you do not know what this is, please say N.
 
 	  To compile this driver as a module, choose M here; the
-	  module will be called "musb_hdrc".
+	  module will be called "musb-hdrc".
 
-config USB_MUSB_SOC
-	boolean
+choice
+	prompt "Platform Glue Layer"
 	depends on USB_MUSB_HDRC
-	default y if ARCH_DAVINCI
-	default y if ARCH_OMAP2430
-	default y if ARCH_OMAP3
-	default y if ARCH_OMAP4
-	default y if (BF54x && !BF544)
-	default y if (BF52x && !BF522 && !BF523)
 
-comment "DaVinci 35x and 644x USB support"
-	depends on USB_MUSB_HDRC && ARCH_DAVINCI_DMx
+config USB_MUSB_DAVINCI
+	bool "DaVinci"
+	depends on ARCH_DAVINCI_DMx
 
-comment "DA8xx/OMAP-L1x USB support"
-	depends on USB_MUSB_HDRC && ARCH_DAVINCI_DA8XX
+config USB_MUSB_DA8XX
+	bool "DA8xx/OMAP-L1x"
+	depends on ARCH_DAVINCI_DA8XX
 
-comment "OMAP 243x high speed USB support"
-	depends on USB_MUSB_HDRC && ARCH_OMAP2430
+config USB_MUSB_TUSB6010
+	bool "TUSB6010"
+	depends on ARCH_OMAP
 
-comment "OMAP 343x high speed USB support"
-	depends on USB_MUSB_HDRC && ARCH_OMAP3
+config USB_MUSB_OMAP2PLUS
+	bool "OMAP2430 and onwards"
+	depends on ARCH_OMAP2PLUS
 
-comment "OMAP 44xx high speed USB support"
-	depends on USB_MUSB_HDRC && ARCH_OMAP4
+config USB_MUSB_AM35X
+	bool "AM35x"
+	depends on ARCH_OMAP
 
-comment "Blackfin high speed USB Support"
-	depends on USB_MUSB_HDRC && ((BF54x && !BF544) || (BF52x && !BF522 && !BF523))
+config USB_MUSB_BLACKFIN
+	bool "Blackfin"
+	depends on (BF54x && !BF544) || (BF52x && ! BF522 && !BF523)
 
-config USB_MUSB_AM35X
-	bool
-	depends on USB_MUSB_HDRC && !ARCH_OMAP2430 && !ARCH_OMAP4
-	select NOP_USB_XCEIV
-	default MACH_OMAP3517EVM
-	help
-	  Select this option if your platform is based on AM35x. As
-	  AM35x has an updated MUSB with CPPI4.1 DMA so this config
-	  is introduced to differentiate musb ip between OMAP3x and
-	  AM35x platforms.
-
-config USB_TUSB6010
-	boolean "TUSB 6010 support"
-	depends on USB_MUSB_HDRC && !USB_MUSB_SOC
-	select NOP_USB_XCEIV
-	default y
-	help
-	  The TUSB 6010 chip, from Texas Instruments, connects a discrete
-	  HDRC core using a 16-bit parallel bus (NOR flash style) or VLYNQ
-	  (a high speed serial link).  It can use system-specific external
-	  DMA controllers.
+config USB_MUSB_UX500
+	bool "U8500 and U5500"
+	depends on (ARCH_U8500 && AB8500_USB) || (ARCH_U5500)
+
+endchoice
 
 choice
 	prompt "Driver Mode"
@@ -158,7 +143,7 @@ config USB_MUSB_HDRC_HCD
 config MUSB_PIO_ONLY
 	bool 'Disable DMA (always use PIO)'
 	depends on USB_MUSB_HDRC
-	default USB_TUSB6010 || ARCH_DAVINCI_DA8XX || USB_MUSB_AM35X
+	default USB_MUSB_TUSB6010 || USB_MUSB_DA8XX || USB_MUSB_AM35X
 	help
 	  All data is copied between memory and FIFO by the CPU.
 	  DMA controllers are ignored.
@@ -171,21 +156,21 @@ config MUSB_PIO_ONLY
 config USB_INVENTRA_DMA
 	bool
 	depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY
-	default ARCH_OMAP2430 || ARCH_OMAP3 || BLACKFIN || ARCH_OMAP4
+	default USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
 	help
 	  Enable DMA transfers using Mentor's engine.
 
 config USB_TI_CPPI_DMA
 	bool
 	depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY
-	default ARCH_DAVINCI
+	default USB_MUSB_DAVINCI
 	help
 	  Enable DMA transfers when TI CPPI DMA is available.
 
 config USB_TUSB_OMAP_DMA
 	bool
 	depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY
-	depends on USB_TUSB6010
+	depends on USB_MUSB_TUSB6010
 	depends on ARCH_OMAP
 	default y
 	help
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index ce164e8998d8..74df5284894f 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -8,22 +8,19 @@ obj-$(CONFIG_USB_MUSB_HDRC) += musb_hdrc.o
 
 musb_hdrc-y := musb_core.o
 
-musb_hdrc-$(CONFIG_ARCH_DAVINCI_DMx)		+= davinci.o
-musb_hdrc-$(CONFIG_ARCH_DAVINCI_DA8XX)		+= da8xx.o
-musb_hdrc-$(CONFIG_USB_TUSB6010)		+= tusb6010.o
-musb_hdrc-$(CONFIG_ARCH_OMAP2430)		+= omap2430.o
-ifeq ($(CONFIG_USB_MUSB_AM35X),y)
-	musb_hdrc-$(CONFIG_ARCH_OMAP3430)	+= am35x.o
-else
-	musb_hdrc-$(CONFIG_ARCH_OMAP3430)	+= omap2430.o
-endif
-musb_hdrc-$(CONFIG_ARCH_OMAP4)			+= omap2430.o
-musb_hdrc-$(CONFIG_BF54x)			+= blackfin.o
-musb_hdrc-$(CONFIG_BF52x)			+= blackfin.o
 musb_hdrc-$(CONFIG_USB_GADGET_MUSB_HDRC)	+= musb_gadget_ep0.o musb_gadget.o
 musb_hdrc-$(CONFIG_USB_MUSB_HDRC_HCD)		+= musb_virthub.o musb_host.o
 musb_hdrc-$(CONFIG_DEBUG_FS)			+= musb_debugfs.o
 
+# Hardware Glue Layer
+obj-$(CONFIG_USB_MUSB_OMAP2PLUS)		+= omap2430.o
+obj-$(CONFIG_USB_MUSB_AM35X)			+= am35x.o
+obj-$(CONFIG_USB_MUSB_TUSB6010)			+= tusb6010.o
+obj-$(CONFIG_USB_MUSB_DAVINCI)			+= davinci.o
+obj-$(CONFIG_USB_MUSB_DA8XX)			+= da8xx.o
+obj-$(CONFIG_USB_MUSB_BLACKFIN)			+= blackfin.o
+obj-$(CONFIG_USB_MUSB_UX500)			+= ux500.o
+
 # the kconfig must guarantee that only one of the
 # possible I/O schemes will be enabled at a time ...
 # PIO only, or DMA (several potential schemes).
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index b0aabf3a606f..d5a3da37c90c 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -29,8 +29,9 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 
-#include <plat/control.h>
 #include <plat/usb.h>
 
 #include "musb_core.h"
@@ -80,51 +81,18 @@
 
 #define USB_MENTOR_CORE_OFFSET	0x400
 
-static inline void phy_on(void)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(100);
-	u32 devconf2;
-
-	/*
-	 * Start the on-chip PHY and its PLL.
-	 */
-	devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
-
-	devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
-	devconf2 |= CONF2_PHY_PLLON;
-
-	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
-
-	DBG(1, "Waiting for PHY clock good...\n");
-	while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
-			& CONF2_PHYCLKGD)) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout)) {
-			DBG(1, "musb PHY clock good timed out\n");
-			break;
-		}
-	}
-}
-
-static inline void phy_off(void)
-{
-	u32 devconf2;
-
-	/*
-	 * Power down the on-chip PHY.
-	 */
-	devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
-
-	devconf2 &= ~CONF2_PHY_PLLON;
-	devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN;
-	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
-}
+struct am35x_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+	struct clk		*phy_clk;
+	struct clk		*clk;
+};
+#define glue_to_musb(g)		platform_get_drvdata(g->musb)
 
 /*
- * musb_platform_enable - enable interrupts
+ * am35x_musb_enable - enable interrupts
  */
-void musb_platform_enable(struct musb *musb)
+static void am35x_musb_enable(struct musb *musb)
 {
 	void __iomem *reg_base = musb->ctrl_base;
 	u32 epmask;
@@ -143,9 +111,9 @@ void musb_platform_enable(struct musb *musb)
 }
 
 /*
- * musb_platform_disable - disable HDRC and flush interrupts
+ * am35x_musb_disable - disable HDRC and flush interrupts
  */
-void musb_platform_disable(struct musb *musb)
+static void am35x_musb_disable(struct musb *musb)
 {
 	void __iomem *reg_base = musb->ctrl_base;
 
@@ -162,7 +130,7 @@ void musb_platform_disable(struct musb *musb)
 #define portstate(stmt)
 #endif
 
-static void am35x_set_vbus(struct musb *musb, int is_on)
+static void am35x_musb_set_vbus(struct musb *musb, int is_on)
 {
 	WARN_ON(is_on && is_peripheral_active(musb));
 }
@@ -221,7 +189,7 @@ static void otg_timer(unsigned long _musb)
 	spin_unlock_irqrestore(&musb->lock, flags);
 }
 
-void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
 {
 	static unsigned long last_timer;
 
@@ -251,13 +219,16 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
 	mod_timer(&otg_workaround, timeout);
 }
 
-static irqreturn_t am35x_interrupt(int irq, void *hci)
+static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
 {
 	struct musb  *musb = hci;
 	void __iomem *reg_base = musb->ctrl_base;
+	struct device *dev = musb->controller;
+	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct omap_musb_board_data *data = plat->board_data;
 	unsigned long flags;
 	irqreturn_t ret = IRQ_NONE;
-	u32 epintr, usbintr, lvl_intr;
+	u32 epintr, usbintr;
 
 	spin_lock_irqsave(&musb->lock, flags);
 
@@ -346,9 +317,8 @@ eoi:
 	/* EOI needs to be written for the IRQ to be re-asserted. */
 	if (ret == IRQ_HANDLED || epintr || usbintr) {
 		/* clear level interrupt */
-		lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
-		lvl_intr |= AM35XX_USBOTGSS_INT_CLR;
-		omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR);
+		if (data->clear_irq)
+			data->clear_irq();
 		/* write EOI */
 		musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
 	}
@@ -362,137 +332,85 @@ eoi:
 	return ret;
 }
 
-int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode)
 {
-	u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+	struct device *dev = musb->controller;
+	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct omap_musb_board_data *data = plat->board_data;
+	int     retval = 0;
 
-	devconf2 &= ~CONF2_OTGMODE;
-	switch (musb_mode) {
-#ifdef	CONFIG_USB_MUSB_HDRC_HCD
-	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
-		devconf2 |= CONF2_FORCE_HOST;
-		break;
-#endif
-#ifdef	CONFIG_USB_GADGET_MUSB_HDRC
-	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
-		devconf2 |= CONF2_FORCE_DEVICE;
-		break;
-#endif
-#ifdef	CONFIG_USB_MUSB_OTG
-	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
-		devconf2 |= CONF2_NO_OVERRIDE;
-		break;
-#endif
-	default:
-		DBG(2, "Trying to set unsupported mode %u\n", musb_mode);
-	}
+	if (data->set_mode)
+		data->set_mode(musb_mode);
+	else
+		retval = -EIO;
 
-	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
-	return 0;
+	return retval;
 }
 
-int __init musb_platform_init(struct musb *musb, void *board_data)
+static int am35x_musb_init(struct musb *musb)
 {
+	struct device *dev = musb->controller;
+	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct omap_musb_board_data *data = plat->board_data;
 	void __iomem *reg_base = musb->ctrl_base;
-	u32 rev, lvl_intr, sw_reset;
-	int status;
+	u32 rev;
 
 	musb->mregs += USB_MENTOR_CORE_OFFSET;
 
-	clk_enable(musb->clock);
-	DBG(2, "musb->clock=%lud\n", clk_get_rate(musb->clock));
-
-	musb->phy_clock = clk_get(musb->controller, "fck");
-	if (IS_ERR(musb->phy_clock)) {
-		status = PTR_ERR(musb->phy_clock);
-		goto exit0;
-	}
-	clk_enable(musb->phy_clock);
-	DBG(2, "musb->phy_clock=%lud\n", clk_get_rate(musb->phy_clock));
-
 	/* Returns zero if e.g. not clocked */
 	rev = musb_readl(reg_base, USB_REVISION_REG);
-	if (!rev) {
-		status = -ENODEV;
-		goto exit1;
-	}
+	if (!rev)
+		return -ENODEV;
 
 	usb_nop_xceiv_register();
 	musb->xceiv = otg_get_transceiver();
-	if (!musb->xceiv) {
-		status = -ENODEV;
-		goto exit1;
-	}
+	if (!musb->xceiv)
+		return -ENODEV;
 
 	if (is_host_enabled(musb))
 		setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
 
-	musb->board_set_vbus = am35x_set_vbus;
-
-	/* Global reset */
-	sw_reset = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
-
-	sw_reset |= AM35XX_USBOTGSS_SW_RST;
-	omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
-
-	sw_reset &= ~AM35XX_USBOTGSS_SW_RST;
-	omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
+	/* Reset the musb */
+	if (data->reset)
+		data->reset();
 
 	/* Reset the controller */
 	musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK);
 
 	/* Start the on-chip PHY and its PLL. */
-	phy_on();
+	if (data->set_phy_power)
+		data->set_phy_power(1);
 
 	msleep(5);
 
-	musb->isr = am35x_interrupt;
+	musb->isr = am35x_musb_interrupt;
 
 	/* clear level interrupt */
-	lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
-	lvl_intr |= AM35XX_USBOTGSS_INT_CLR;
-	omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR);
+	if (data->clear_irq)
+		data->clear_irq();
+
 	return 0;
-exit1:
-	clk_disable(musb->phy_clock);
-	clk_put(musb->phy_clock);
-exit0:
-	clk_disable(musb->clock);
-	return status;
 }
 
-int musb_platform_exit(struct musb *musb)
+static int am35x_musb_exit(struct musb *musb)
 {
+	struct device *dev = musb->controller;
+	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct omap_musb_board_data *data = plat->board_data;
+
 	if (is_host_enabled(musb))
 		del_timer_sync(&otg_workaround);
 
-	phy_off();
+	/* Shutdown the on-chip PHY and its PLL. */
+	if (data->set_phy_power)
+		data->set_phy_power(0);
 
 	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 
-	clk_disable(musb->clock);
-
-	clk_disable(musb->phy_clock);
-	clk_put(musb->phy_clock);
-
 	return 0;
 }
 
-#ifdef CONFIG_PM
-void musb_platform_save_context(struct musb *musb,
-	struct musb_context_registers *musb_context)
-{
-	phy_off();
-}
-
-void musb_platform_restore_context(struct musb *musb,
-	struct musb_context_registers *musb_context)
-{
-	phy_on();
-}
-#endif
-
 /* AM35x supports only 32bit read operation */
 void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
 {
@@ -522,3 +440,215 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
 		memcpy(dst, &val, len);
 	}
 }
+
+static const struct musb_platform_ops am35x_ops = {
+	.init		= am35x_musb_init,
+	.exit		= am35x_musb_exit,
+
+	.enable		= am35x_musb_enable,
+	.disable	= am35x_musb_disable,
+
+	.set_mode	= am35x_musb_set_mode,
+	.try_idle	= am35x_musb_try_idle,
+
+	.set_vbus	= am35x_musb_set_vbus,
+};
+
+static u64 am35x_dmamask = DMA_BIT_MASK(32);
+
+static int __init am35x_probe(struct platform_device *pdev)
+{
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct am35x_glue		*glue;
+
+	struct clk			*phy_clk;
+	struct clk			*clk;
+
+	int				ret = -ENOMEM;
+
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
+
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
+
+	phy_clk = clk_get(&pdev->dev, "fck");
+	if (IS_ERR(phy_clk)) {
+		dev_err(&pdev->dev, "failed to get PHY clock\n");
+		ret = PTR_ERR(phy_clk);
+		goto err2;
+	}
+
+	clk = clk_get(&pdev->dev, "ick");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		ret = PTR_ERR(clk);
+		goto err3;
+	}
+
+	ret = clk_enable(phy_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable PHY clock\n");
+		goto err4;
+	}
+
+	ret = clk_enable(clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clock\n");
+		goto err5;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+	musb->dev.dma_mask		= &am35x_dmamask;
+	musb->dev.coherent_dma_mask	= am35x_dmamask;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+	glue->phy_clk			= phy_clk;
+	glue->clk			= clk;
+
+	pdata->platform_ops		= &am35x_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err6;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err6;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err6;
+	}
+
+	return 0;
+
+err6:
+	clk_disable(clk);
+
+err5:
+	clk_disable(phy_clk);
+
+err4:
+	clk_put(clk);
+
+err3:
+	clk_put(phy_clk);
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
+}
+
+static int __exit am35x_remove(struct platform_device *pdev)
+{
+	struct am35x_glue	*glue = platform_get_drvdata(pdev);
+
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	clk_disable(glue->clk);
+	clk_disable(glue->phy_clk);
+	clk_put(glue->clk);
+	clk_put(glue->phy_clk);
+	kfree(glue);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int am35x_suspend(struct device *dev)
+{
+	struct am35x_glue	*glue = dev_get_drvdata(dev);
+	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct omap_musb_board_data *data = plat->board_data;
+
+	/* Shutdown the on-chip PHY and its PLL. */
+	if (data->set_phy_power)
+		data->set_phy_power(0);
+
+	clk_disable(glue->phy_clk);
+	clk_disable(glue->clk);
+
+	return 0;
+}
+
+static int am35x_resume(struct device *dev)
+{
+	struct am35x_glue	*glue = dev_get_drvdata(dev);
+	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct omap_musb_board_data *data = plat->board_data;
+	int			ret;
+
+	/* Start the on-chip PHY and its PLL. */
+	if (data->set_phy_power)
+		data->set_phy_power(1);
+
+	ret = clk_enable(glue->phy_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable PHY clock\n");
+		return ret;
+	}
+
+	ret = clk_enable(glue->clk);
+	if (ret) {
+		dev_err(dev, "failed to enable clock\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct dev_pm_ops am35x_pm_ops = {
+	.suspend	= am35x_suspend,
+	.resume		= am35x_resume,
+};
+
+#define DEV_PM_OPS	&am35x_pm_ops
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
+static struct platform_driver am35x_driver = {
+	.remove		= __exit_p(am35x_remove),
+	.driver		= {
+		.name	= "musb-am35x",
+		.pm	= DEV_PM_OPS,
+	},
+};
+
+MODULE_DESCRIPTION("AM35x MUSB Glue Layer");
+MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init am35x_init(void)
+{
+	return platform_driver_probe(&am35x_driver, am35x_probe);
+}
+subsys_initcall(am35x_init);
+
+static void __exit am35x_exit(void)
+{
+	platform_driver_unregister(&am35x_driver);
+}
+module_exit(am35x_exit);
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index e8cbcc59c419..e72f762d214d 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -15,12 +15,20 @@
 #include <linux/list.h>
 #include <linux/gpio.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/cacheflush.h>
 
 #include "musb_core.h"
 #include "blackfin.h"
 
+struct bfin_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+};
+#define glue_to_musb(g)		platform_get_drvdata(g->musb)
+
 /*
  * Load an endpoint's FIFO
  */
@@ -277,7 +285,7 @@ static void musb_conn_timer_handler(unsigned long _musb)
 	DBG(4, "state is %s\n", otg_state_string(musb));
 }
 
-void musb_platform_enable(struct musb *musb)
+static void bfin_musb_enable(struct musb *musb)
 {
 	if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
 		mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
@@ -285,11 +293,11 @@ void musb_platform_enable(struct musb *musb)
 	}
 }
 
-void musb_platform_disable(struct musb *musb)
+static void bfin_musb_disable(struct musb *musb)
 {
 }
 
-static void bfin_set_vbus(struct musb *musb, int is_on)
+static void bfin_musb_set_vbus(struct musb *musb, int is_on)
 {
 	int value = musb->config->gpio_vrsel_active;
 	if (!is_on)
@@ -302,51 +310,29 @@ static void bfin_set_vbus(struct musb *musb, int is_on)
 		musb_readb(musb->mregs, MUSB_DEVCTL));
 }
 
-static int bfin_set_power(struct otg_transceiver *x, unsigned mA)
+static int bfin_musb_set_power(struct otg_transceiver *x, unsigned mA)
 {
 	return 0;
 }
 
-void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+static void bfin_musb_try_idle(struct musb *musb, unsigned long timeout)
 {
 	if (!is_otg_enabled(musb) && is_host_enabled(musb))
 		mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
 }
 
-int musb_platform_get_vbus_status(struct musb *musb)
+static int bfin_musb_get_vbus_status(struct musb *musb)
 {
 	return 0;
 }
 
-int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+static int bfin_musb_set_mode(struct musb *musb, u8 musb_mode)
 {
 	return -EIO;
 }
 
-int __init musb_platform_init(struct musb *musb)
+static void bfin_musb_reg_init(struct musb *musb)
 {
-
-	/*
-	 * Rev 1.0 BF549 EZ-KITs require PE7 to be high for both DEVICE
-	 * and OTG HOST modes, while rev 1.1 and greater require PE7 to
-	 * be low for DEVICE mode and high for HOST mode. We set it high
-	 * here because we are in host mode
-	 */
-
-	if (gpio_request(musb->config->gpio_vrsel, "USB_VRSEL")) {
-		printk(KERN_ERR "Failed ro request USB_VRSEL GPIO_%d \n",
-			musb->config->gpio_vrsel);
-		return -ENODEV;
-	}
-	gpio_direction_output(musb->config->gpio_vrsel, 0);
-
-	usb_nop_xceiv_register();
-	musb->xceiv = otg_get_transceiver();
-	if (!musb->xceiv) {
-		gpio_free(musb->config->gpio_vrsel);
-		return -ENODEV;
-	}
-
 	if (ANOMALY_05000346) {
 		bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value);
 		SSYNC();
@@ -380,21 +366,47 @@ int __init musb_platform_init(struct musb *musb)
 				EP2_RX_ENA | EP3_RX_ENA | EP4_RX_ENA |
 				EP5_RX_ENA | EP6_RX_ENA | EP7_RX_ENA);
 	SSYNC();
+}
+
+static int bfin_musb_init(struct musb *musb)
+{
+
+	/*
+	 * Rev 1.0 BF549 EZ-KITs require PE7 to be high for both DEVICE
+	 * and OTG HOST modes, while rev 1.1 and greater require PE7 to
+	 * be low for DEVICE mode and high for HOST mode. We set it high
+	 * here because we are in host mode
+	 */
+
+	if (gpio_request(musb->config->gpio_vrsel, "USB_VRSEL")) {
+		printk(KERN_ERR "Failed ro request USB_VRSEL GPIO_%d\n",
+			musb->config->gpio_vrsel);
+		return -ENODEV;
+	}
+	gpio_direction_output(musb->config->gpio_vrsel, 0);
+
+	usb_nop_xceiv_register();
+	musb->xceiv = otg_get_transceiver();
+	if (!musb->xceiv) {
+		gpio_free(musb->config->gpio_vrsel);
+		return -ENODEV;
+	}
+
+	bfin_musb_reg_init(musb);
 
 	if (is_host_enabled(musb)) {
-		musb->board_set_vbus = bfin_set_vbus;
 		setup_timer(&musb_conn_timer,
 			musb_conn_timer_handler, (unsigned long) musb);
 	}
 	if (is_peripheral_enabled(musb))
-		musb->xceiv->set_power = bfin_set_power;
+		musb->xceiv->set_power = bfin_musb_set_power;
 
 	musb->isr = blackfin_interrupt;
 
 	return 0;
 }
 
-int musb_platform_exit(struct musb *musb)
+static int bfin_musb_exit(struct musb *musb)
 {
 	gpio_free(musb->config->gpio_vrsel);
 
@@ -402,3 +414,154 @@ int musb_platform_exit(struct musb *musb)
 	usb_nop_xceiv_unregister();
 	return 0;
 }
+
+static const struct musb_platform_ops bfin_ops = {
+	.init		= bfin_musb_init,
+	.exit		= bfin_musb_exit,
+
+	.enable		= bfin_musb_enable,
+	.disable	= bfin_musb_disable,
+
+	.set_mode	= bfin_musb_set_mode,
+	.try_idle	= bfin_musb_try_idle,
+
+	.vbus_status	= bfin_musb_vbus_status,
+	.set_vbus	= bfin_musb_set_vbus,
+};
+
+static u64 bfin_dmamask = DMA_BIT_MASK(32);
+
+static int __init bfin_probe(struct platform_device *pdev)
+{
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct bfin_glue		*glue;
+
+	int				ret = -ENOMEM;
+
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
+
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+	musb->dev.dma_mask		= &bfin_dmamask;
+	musb->dev.coherent_dma_mask	= bfin_dmamask;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+
+	pdata->platform_ops		= &bfin_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err2;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err2;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err2;
+	}
+
+	return 0;
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
+}
+
+static int __exit bfin_remove(struct platform_device *pdev)
+{
+	struct bfin_glue		*glue = platform_get_drvdata(pdev);
+
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	kfree(glue);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_suspend(struct device *dev)
+{
+	struct bfin_glue	*glue = dev_get_drvdata(dev);
+	struct musb		*musb = glue_to_musb(glue);
+
+	if (is_host_active(musb))
+		/*
+		 * During hibernate gpio_vrsel will change from high to low
+		 * low which will generate wakeup event resume the system
+		 * immediately.  Set it to 0 before hibernate to avoid this
+		 * wakeup event.
+		 */
+		gpio_set_value(musb->config->gpio_vrsel, 0);
+
+	return 0;
+}
+
+static int bfin_resume(struct device *dev)
+{
+	struct bfin_glue	*glue = dev_get_drvdata(dev);
+	struct musb		*musb = glue_to_musb(glue);
+
+	bfin_musb_reg_init(musb);
+
+	return 0;
+}
+
+static struct dev_pm_ops bfin_pm_ops = {
+	.suspend	= bfin_suspend,
+	.resume		= bfin_resume,
+};
+
+#define DEV_PM_OPS	&bfin_pm_op,
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
+static struct platform_driver bfin_driver = {
+	.remove		= __exit_p(bfin_remove),
+	.driver		= {
+		.name	= "musb-bfin",
+		.pm	= DEV_PM_OPS,
+	},
+};
+
+MODULE_DESCRIPTION("Blackfin MUSB Glue Layer");
+MODULE_AUTHOR("Bryan Wy <cooloney@kernel.org>");
+MODULE_LICENSE("GPL v2");
+
+static int __init bfin_init(void)
+{
+	return platform_driver_probe(&bfin_driver, bfin_probe);
+}
+subsys_initcall(bfin_init);
+
+static void __exit bfin_exit(void)
+{
+	platform_driver_unregister(&bfin_driver);
+}
+module_exit(bfin_exit);
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 84427bebbf62..69a0da3c8f09 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -29,6 +29,8 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 
 #include <mach/da8xx.h>
 #include <mach/usb.h>
@@ -78,6 +80,12 @@
 
 #define CFGCHIP2	IO_ADDRESS(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG)
 
+struct da8xx_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+	struct clk		*clk;
+};
+
 /*
  * REVISIT (PM): we should be able to keep the PHY in low power mode most
  * of the time (24 MHz oscillator and PLL off, etc.) by setting POWER.D0
@@ -131,9 +139,9 @@ static inline void phy_off(void)
  */
 
 /**
- * musb_platform_enable - enable interrupts
+ * da8xx_musb_enable - enable interrupts
  */
-void musb_platform_enable(struct musb *musb)
+static void da8xx_musb_enable(struct musb *musb)
 {
 	void __iomem *reg_base = musb->ctrl_base;
 	u32 mask;
@@ -151,9 +159,9 @@ void musb_platform_enable(struct musb *musb)
 }
 
 /**
- * musb_platform_disable - disable HDRC and flush interrupts
+ * da8xx_musb_disable - disable HDRC and flush interrupts
  */
-void musb_platform_disable(struct musb *musb)
+static void da8xx_musb_disable(struct musb *musb)
 {
 	void __iomem *reg_base = musb->ctrl_base;
 
@@ -170,7 +178,7 @@ void musb_platform_disable(struct musb *musb)
 #define portstate(stmt)
 #endif
 
-static void da8xx_set_vbus(struct musb *musb, int is_on)
+static void da8xx_musb_set_vbus(struct musb *musb, int is_on)
 {
 	WARN_ON(is_on && is_peripheral_active(musb));
 }
@@ -252,7 +260,7 @@ static void otg_timer(unsigned long _musb)
 	spin_unlock_irqrestore(&musb->lock, flags);
 }
 
-void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
 {
 	static unsigned long last_timer;
 
@@ -282,7 +290,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
 	mod_timer(&otg_workaround, timeout);
 }
 
-static irqreturn_t da8xx_interrupt(int irq, void *hci)
+static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
 {
 	struct musb		*musb = hci;
 	void __iomem		*reg_base = musb->ctrl_base;
@@ -380,7 +388,7 @@ static irqreturn_t da8xx_interrupt(int irq, void *hci)
 	return ret;
 }
 
-int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+static int da8xx_musb_set_mode(struct musb *musb, u8 musb_mode)
 {
 	u32 cfgchip2 = __raw_readl(CFGCHIP2);
 
@@ -409,15 +417,13 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
 	return 0;
 }
 
-int __init musb_platform_init(struct musb *musb, void *board_data)
+static int da8xx_musb_init(struct musb *musb)
 {
 	void __iomem *reg_base = musb->ctrl_base;
 	u32 rev;
 
 	musb->mregs += DA8XX_MENTOR_CORE_OFFSET;
 
-	clk_enable(musb->clock);
-
 	/* Returns zero if e.g. not clocked */
 	rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG);
 	if (!rev)
@@ -431,8 +437,6 @@ int __init musb_platform_init(struct musb *musb, void *board_data)
 	if (is_host_enabled(musb))
 		setup_timer(&otg_workaround, otg_timer, (unsigned long)musb);
 
-	musb->board_set_vbus = da8xx_set_vbus;
-
 	/* Reset the controller */
 	musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK);
 
@@ -446,14 +450,13 @@ int __init musb_platform_init(struct musb *musb, void *board_data)
 		 rev, __raw_readl(CFGCHIP2),
 		 musb_readb(reg_base, DA8XX_USB_CTRL_REG));
 
-	musb->isr = da8xx_interrupt;
+	musb->isr = da8xx_musb_interrupt;
 	return 0;
 fail:
-	clk_disable(musb->clock);
 	return -ENODEV;
 }
 
-int musb_platform_exit(struct musb *musb)
+static int da8xx_musb_exit(struct musb *musb)
 {
 	if (is_host_enabled(musb))
 		del_timer_sync(&otg_workaround);
@@ -463,7 +466,140 @@ int musb_platform_exit(struct musb *musb)
 	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 
-	clk_disable(musb->clock);
+	return 0;
+}
+
+static const struct musb_platform_ops da8xx_ops = {
+	.init		= da8xx_musb_init,
+	.exit		= da8xx_musb_exit,
+
+	.enable		= da8xx_musb_enable,
+	.disable	= da8xx_musb_disable,
+
+	.set_mode	= da8xx_musb_set_mode,
+	.try_idle	= da8xx_musb_try_idle,
+
+	.set_vbus	= da8xx_musb_set_vbus,
+};
+
+static u64 da8xx_dmamask = DMA_BIT_MASK(32);
+
+static int __init da8xx_probe(struct platform_device *pdev)
+{
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct da8xx_glue		*glue;
+
+	struct clk			*clk;
+
+	int				ret = -ENOMEM;
+
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
+
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
+
+	clk = clk_get(&pdev->dev, "usb20");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		ret = PTR_ERR(clk);
+		goto err2;
+	}
+
+	ret = clk_enable(clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clock\n");
+		goto err3;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+	musb->dev.dma_mask		= &da8xx_dmamask;
+	musb->dev.coherent_dma_mask	= da8xx_dmamask;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+	glue->clk			= clk;
+
+	pdata->platform_ops		= &da8xx_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err4;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err4;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err4;
+	}
+
+	return 0;
+
+err4:
+	clk_disable(clk);
+
+err3:
+	clk_put(clk);
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
+}
+
+static int __exit da8xx_remove(struct platform_device *pdev)
+{
+	struct da8xx_glue		*glue = platform_get_drvdata(pdev);
+
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	clk_disable(glue->clk);
+	clk_put(glue->clk);
+	kfree(glue);
 
 	return 0;
 }
+
+static struct platform_driver da8xx_driver = {
+	.remove		= __exit_p(da8xx_remove),
+	.driver		= {
+		.name	= "musb-da8xx",
+	},
+};
+
+MODULE_DESCRIPTION("DA8xx/OMAP-L1x MUSB Glue Layer");
+MODULE_AUTHOR("Sergei Shtylyov <sshtylyov@ru.mvista.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init da8xx_init(void)
+{
+	return platform_driver_probe(&da8xx_driver, da8xx_probe);
+}
+subsys_initcall(da8xx_init);
+
+static void __exit da8xx_exit(void)
+{
+	platform_driver_unregister(&da8xx_driver);
+}
+module_exit(da8xx_exit);
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 051e2bf1897a..e6de097fb7e8 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -30,6 +30,8 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 
 #include <mach/hardware.h>
 #include <mach/memory.h>
@@ -51,6 +53,12 @@
 #define USB_PHY_CTRL	IO_ADDRESS(USBPHY_CTL_PADDR)
 #define DM355_DEEPSLEEP	IO_ADDRESS(DM355_DEEPSLEEP_PADDR)
 
+struct davinci_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+	struct clk		*clk;
+};
+
 /* REVISIT (PM) we should be able to keep the PHY in low power mode most
  * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0
  * and, when in host mode, autosuspending idle root ports... PHYPLLON
@@ -83,7 +91,7 @@ static inline void phy_off(void)
 
 static int dma_off = 1;
 
-void musb_platform_enable(struct musb *musb)
+static void davinci_musb_enable(struct musb *musb)
 {
 	u32	tmp, old, val;
 
@@ -116,7 +124,7 @@ void musb_platform_enable(struct musb *musb)
 /*
  * Disable the HDRC and flush interrupts
  */
-void musb_platform_disable(struct musb *musb)
+static void davinci_musb_disable(struct musb *musb)
 {
 	/* because we don't set CTRLR.UINT, "important" to:
 	 *  - not read/write INTRUSB/INTRUSBE
@@ -167,7 +175,7 @@ static void evm_deferred_drvvbus(struct work_struct *ignored)
 
 #endif	/* EVM */
 
-static void davinci_source_power(struct musb *musb, int is_on, int immediate)
+static void davinci_musb_source_power(struct musb *musb, int is_on, int immediate)
 {
 #ifdef CONFIG_MACH_DAVINCI_EVM
 	if (is_on)
@@ -190,10 +198,10 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate)
 #endif
 }
 
-static void davinci_set_vbus(struct musb *musb, int is_on)
+static void davinci_musb_set_vbus(struct musb *musb, int is_on)
 {
 	WARN_ON(is_on && is_peripheral_active(musb));
-	davinci_source_power(musb, is_on, 0);
+	davinci_musb_source_power(musb, is_on, 0);
 }
 
 
@@ -259,7 +267,7 @@ static void otg_timer(unsigned long _musb)
 	spin_unlock_irqrestore(&musb->lock, flags);
 }
 
-static irqreturn_t davinci_interrupt(int irq, void *__hci)
+static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)
 {
 	unsigned long	flags;
 	irqreturn_t	retval = IRQ_NONE;
@@ -345,7 +353,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
 		/* NOTE:  this must complete poweron within 100 msec
 		 * (OTG_TIME_A_WAIT_VRISE) but we don't check for that.
 		 */
-		davinci_source_power(musb, drvvbus, 0);
+		davinci_musb_source_power(musb, drvvbus, 0);
 		DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
 				drvvbus ? "on" : "off",
 				otg_state_string(musb),
@@ -370,13 +378,13 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
 	return retval;
 }
 
-int musb_platform_set_mode(struct musb *musb, u8 mode)
+static int davinci_musb_set_mode(struct musb *musb, u8 mode)
 {
 	/* EVM can't do this (right?) */
 	return -EIO;
 }
 
-int __init musb_platform_init(struct musb *musb)
+static int davinci_musb_init(struct musb *musb)
 {
 	void __iomem	*tibase = musb->ctrl_base;
 	u32		revision;
@@ -388,8 +396,6 @@ int __init musb_platform_init(struct musb *musb)
 
 	musb->mregs += DAVINCI_BASE_OFFSET;
 
-	clk_enable(musb->clock);
-
 	/* returns zero if e.g. not clocked */
 	revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
 	if (revision == 0)
@@ -398,8 +404,7 @@ int __init musb_platform_init(struct musb *musb)
 	if (is_host_enabled(musb))
 		setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
 
-	musb->board_set_vbus = davinci_set_vbus;
-	davinci_source_power(musb, 0, 1);
+	davinci_musb_source_power(musb, 0, 1);
 
 	/* dm355 EVM swaps D+/D- for signal integrity, and
 	 * is clocked from the main 24 MHz crystal.
@@ -440,18 +445,16 @@ int __init musb_platform_init(struct musb *musb)
 		revision, __raw_readl(USB_PHY_CTRL),
 		musb_readb(tibase, DAVINCI_USB_CTRL_REG));
 
-	musb->isr = davinci_interrupt;
+	musb->isr = davinci_musb_interrupt;
 	return 0;
 
 fail:
-	clk_disable(musb->clock);
-
 	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 	return -ENODEV;
 }
 
-int musb_platform_exit(struct musb *musb)
+static int davinci_musb_exit(struct musb *musb)
 {
 	if (is_host_enabled(musb))
 		del_timer_sync(&otg_workaround);
@@ -465,7 +468,7 @@ int musb_platform_exit(struct musb *musb)
 		__raw_writel(deepsleep, DM355_DEEPSLEEP);
 	}
 
-	davinci_source_power(musb, 0 /*off*/, 1);
+	davinci_musb_source_power(musb, 0 /*off*/, 1);
 
 	/* delay, to avoid problems with module reload */
 	if (is_host_enabled(musb) && musb->xceiv->default_a) {
@@ -495,10 +498,141 @@ int musb_platform_exit(struct musb *musb)
 
 	phy_off();
 
-	clk_disable(musb->clock);
-
 	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 
 	return 0;
 }
+
+static const struct musb_platform_ops davinci_ops = {
+	.init		= davinci_musb_init,
+	.exit		= davinci_musb_exit,
+
+	.enable		= davinci_musb_enable,
+	.disable	= davinci_musb_disable,
+
+	.set_mode	= davinci_musb_set_mode,
+
+	.set_vbus	= davinci_musb_set_vbus,
+};
+
+static u64 davinci_dmamask = DMA_BIT_MASK(32);
+
+static int __init davinci_probe(struct platform_device *pdev)
+{
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct davinci_glue		*glue;
+	struct clk			*clk;
+
+	int				ret = -ENOMEM;
+
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
+
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
+
+	clk = clk_get(&pdev->dev, "usb");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		ret = PTR_ERR(clk);
+		goto err2;
+	}
+
+	ret = clk_enable(clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clock\n");
+		goto err3;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+	musb->dev.dma_mask		= &davinci_dmamask;
+	musb->dev.coherent_dma_mask	= davinci_dmamask;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+	glue->clk			= clk;
+
+	pdata->platform_ops		= &davinci_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err4;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err4;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err4;
+	}
+
+	return 0;
+
+err4:
+	clk_disable(clk);
+
+err3:
+	clk_put(clk);
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
+}
+
+static int __exit davinci_remove(struct platform_device *pdev)
+{
+	struct davinci_glue		*glue = platform_get_drvdata(pdev);
+
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	clk_disable(glue->clk);
+	clk_put(glue->clk);
+	kfree(glue);
+
+	return 0;
+}
+
+static struct platform_driver davinci_driver = {
+	.remove		= __exit_p(davinci_remove),
+	.driver		= {
+		.name	= "musb-davinci",
+	},
+};
+
+MODULE_DESCRIPTION("DaVinci MUSB Glue Layer");
+MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init davinci_init(void)
+{
+	return platform_driver_probe(&davinci_driver, davinci_probe);
+}
+subsys_initcall(davinci_init);
+
+static void __exit davinci_exit(void)
+{
+	platform_driver_unregister(&davinci_driver);
+}
+module_exit(davinci_exit);
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index a5ceddfe57d6..7816c0180430 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -99,19 +99,8 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-#ifdef	CONFIG_ARM
-#include <mach/hardware.h>
-#include <mach/memory.h>
-#include <asm/mach-types.h>
-#endif
-
 #include "musb_core.h"
 
-
-#ifdef CONFIG_ARCH_DAVINCI
-#include "davinci.h"
-#endif
-
 #define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON)
 
 
@@ -126,7 +115,7 @@ MODULE_PARM_DESC(debug, "Debug message level. Default = 0");
 
 #define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION
 
-#define MUSB_DRIVER_NAME "musb_hdrc"
+#define MUSB_DRIVER_NAME "musb-hdrc"
 const char musb_driver_name[] = MUSB_DRIVER_NAME;
 
 MODULE_DESCRIPTION(DRIVER_INFO);
@@ -230,7 +219,7 @@ static struct otg_io_access_ops musb_ulpi_access = {
 
 /*-------------------------------------------------------------------------*/
 
-#if !defined(CONFIG_USB_TUSB6010) && !defined(CONFIG_BLACKFIN)
+#if !defined(CONFIG_USB_MUSB_TUSB6010) && !defined(CONFIG_USB_MUSB_BLACKFIN)
 
 /*
  * Load an endpoint's FIFO
@@ -390,7 +379,7 @@ void musb_otg_timer_func(unsigned long data)
 	case OTG_STATE_A_SUSPEND:
 	case OTG_STATE_A_WAIT_BCON:
 		DBG(1, "HNP: %s timeout\n", otg_state_string(musb));
-		musb_set_vbus(musb, 0);
+		musb_platform_set_vbus(musb, 0);
 		musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
 		break;
 	default:
@@ -570,7 +559,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 		musb->ep0_stage = MUSB_EP0_START;
 		musb->xceiv->state = OTG_STATE_A_IDLE;
 		MUSB_HST_MODE(musb);
-		musb_set_vbus(musb, 1);
+		musb_platform_set_vbus(musb, 1);
 
 		handled = IRQ_HANDLED;
 	}
@@ -641,7 +630,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 
 		/* go through A_WAIT_VFALL then start a new session */
 		if (!ignore)
-			musb_set_vbus(musb, 0);
+			musb_platform_set_vbus(musb, 0);
 		handled = IRQ_HANDLED;
 	}
 
@@ -1048,8 +1037,6 @@ static void musb_shutdown(struct platform_device *pdev)
 	spin_lock_irqsave(&musb->lock, flags);
 	musb_platform_disable(musb);
 	musb_generic_disable(musb);
-	if (musb->clock)
-		clk_put(musb->clock);
 	spin_unlock_irqrestore(&musb->lock, flags);
 
 	/* FIXME power down */
@@ -1068,10 +1055,11 @@ static void musb_shutdown(struct platform_device *pdev)
  * We don't currently use dynamic fifo setup capability to do anything
  * more than selecting one of a bunch of predefined configurations.
  */
-#if defined(CONFIG_USB_TUSB6010) || \
-	defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) \
-	|| defined(CONFIG_ARCH_OMAP4)
+#if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_OMAP2PLUS) \
+	|| defined(CONFIG_USB_MUSB_AM35X)
 static ushort __initdata fifo_mode = 4;
+#elif defined(CONFIG_USB_MUSB_UX500)
+static ushort __initdata fifo_mode = 5;
 #else
 static ushort __initdata fifo_mode = 2;
 #endif
@@ -1495,7 +1483,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
 		struct musb_hw_ep	*hw_ep = musb->endpoints + i;
 
 		hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase;
-#ifdef CONFIG_USB_TUSB6010
+#ifdef CONFIG_USB_MUSB_TUSB6010
 		hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i);
 		hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i);
 		hw_ep->fifo_sync_va =
@@ -1542,7 +1530,8 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) || \
-	defined(CONFIG_ARCH_OMAP4)
+	defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500) || \
+	defined(CONFIG_ARCH_U5500)
 
 static irqreturn_t generic_interrupt(int irq, void *__hci)
 {
@@ -1898,6 +1887,7 @@ allocate_instance(struct device *dev,
 	}
 
 	musb->controller = dev;
+
 	return musb;
 }
 
@@ -1994,30 +1984,14 @@ bad_config:
 	spin_lock_init(&musb->lock);
 	musb->board_mode = plat->mode;
 	musb->board_set_power = plat->set_power;
-	musb->set_clock = plat->set_clock;
 	musb->min_power = plat->min_power;
-
-	/* Clock usage is chip-specific ... functional clock (DaVinci,
-	 * OMAP2430), or PHY ref (some TUSB6010 boards).  All this core
-	 * code does is make sure a clock handle is available; platform
-	 * code manages it during start/stop and suspend/resume.
-	 */
-	if (plat->clock) {
-		musb->clock = clk_get(dev, plat->clock);
-		if (IS_ERR(musb->clock)) {
-			status = PTR_ERR(musb->clock);
-			musb->clock = NULL;
-			goto fail1;
-		}
-	}
+	musb->ops = plat->platform_ops;
 
 	/* The musb_platform_init() call:
 	 *   - adjusts musb->mregs and musb->isr if needed,
 	 *   - may initialize an integrated tranceiver
 	 *   - initializes musb->xceiv, usually by otg_get_transceiver()
-	 *   - activates clocks.
 	 *   - stops powering VBUS
-	 *   - assigns musb->board_set_vbus if host mode is enabled
 	 *
 	 * There are various transciever configurations.  Blackfin,
 	 * DaVinci, TUSB60x0, and others integrate them.  OMAP3 uses
@@ -2027,7 +2001,7 @@ bad_config:
 	musb->isr = generic_interrupt;
 	status = musb_platform_init(musb);
 	if (status < 0)
-		goto fail2;
+		goto fail1;
 
 	if (!musb->isr) {
 		status = -ENODEV;
@@ -2177,10 +2151,6 @@ fail3:
 		device_init_wakeup(dev, 0);
 	musb_platform_exit(musb);
 
-fail2:
-	if (musb->clock)
-		clk_put(musb->clock);
-
 fail1:
 	dev_err(musb->controller,
 		"musb_init_controller failed with status %d\n", status);
@@ -2263,144 +2233,138 @@ static int __exit musb_remove(struct platform_device *pdev)
 
 #ifdef	CONFIG_PM
 
-static struct musb_context_registers musb_context;
-
-void musb_save_context(struct musb *musb)
+static void musb_save_context(struct musb *musb)
 {
 	int i;
 	void __iomem *musb_base = musb->mregs;
 	void __iomem *epio;
 
 	if (is_host_enabled(musb)) {
-		musb_context.frame = musb_readw(musb_base, MUSB_FRAME);
-		musb_context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
-		musb_context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
+		musb->context.frame = musb_readw(musb_base, MUSB_FRAME);
+		musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
+		musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
 	}
-	musb_context.power = musb_readb(musb_base, MUSB_POWER);
-	musb_context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE);
-	musb_context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE);
-	musb_context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE);
-	musb_context.index = musb_readb(musb_base, MUSB_INDEX);
-	musb_context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
+	musb->context.power = musb_readb(musb_base, MUSB_POWER);
+	musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE);
+	musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE);
+	musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE);
+	musb->context.index = musb_readb(musb_base, MUSB_INDEX);
+	musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
 
 	for (i = 0; i < musb->config->num_eps; ++i) {
 		epio = musb->endpoints[i].regs;
-		musb_context.index_regs[i].txmaxp =
+		musb->context.index_regs[i].txmaxp =
 			musb_readw(epio, MUSB_TXMAXP);
-		musb_context.index_regs[i].txcsr =
+		musb->context.index_regs[i].txcsr =
 			musb_readw(epio, MUSB_TXCSR);
-		musb_context.index_regs[i].rxmaxp =
+		musb->context.index_regs[i].rxmaxp =
 			musb_readw(epio, MUSB_RXMAXP);
-		musb_context.index_regs[i].rxcsr =
+		musb->context.index_regs[i].rxcsr =
 			musb_readw(epio, MUSB_RXCSR);
 
 		if (musb->dyn_fifo) {
-			musb_context.index_regs[i].txfifoadd =
+			musb->context.index_regs[i].txfifoadd =
 					musb_read_txfifoadd(musb_base);
-			musb_context.index_regs[i].rxfifoadd =
+			musb->context.index_regs[i].rxfifoadd =
 					musb_read_rxfifoadd(musb_base);
-			musb_context.index_regs[i].txfifosz =
+			musb->context.index_regs[i].txfifosz =
 					musb_read_txfifosz(musb_base);
-			musb_context.index_regs[i].rxfifosz =
+			musb->context.index_regs[i].rxfifosz =
 					musb_read_rxfifosz(musb_base);
 		}
 		if (is_host_enabled(musb)) {
-			musb_context.index_regs[i].txtype =
+			musb->context.index_regs[i].txtype =
 				musb_readb(epio, MUSB_TXTYPE);
-			musb_context.index_regs[i].txinterval =
+			musb->context.index_regs[i].txinterval =
 				musb_readb(epio, MUSB_TXINTERVAL);
-			musb_context.index_regs[i].rxtype =
+			musb->context.index_regs[i].rxtype =
 				musb_readb(epio, MUSB_RXTYPE);
-			musb_context.index_regs[i].rxinterval =
+			musb->context.index_regs[i].rxinterval =
 				musb_readb(epio, MUSB_RXINTERVAL);
 
-			musb_context.index_regs[i].txfunaddr =
+			musb->context.index_regs[i].txfunaddr =
 				musb_read_txfunaddr(musb_base, i);
-			musb_context.index_regs[i].txhubaddr =
+			musb->context.index_regs[i].txhubaddr =
 				musb_read_txhubaddr(musb_base, i);
-			musb_context.index_regs[i].txhubport =
+			musb->context.index_regs[i].txhubport =
 				musb_read_txhubport(musb_base, i);
 
-			musb_context.index_regs[i].rxfunaddr =
+			musb->context.index_regs[i].rxfunaddr =
 				musb_read_rxfunaddr(musb_base, i);
-			musb_context.index_regs[i].rxhubaddr =
+			musb->context.index_regs[i].rxhubaddr =
 				musb_read_rxhubaddr(musb_base, i);
-			musb_context.index_regs[i].rxhubport =
+			musb->context.index_regs[i].rxhubport =
 				musb_read_rxhubport(musb_base, i);
 		}
 	}
-
-	musb_platform_save_context(musb, &musb_context);
 }
 
-void musb_restore_context(struct musb *musb)
+static void musb_restore_context(struct musb *musb)
 {
 	int i;
 	void __iomem *musb_base = musb->mregs;
 	void __iomem *ep_target_regs;
 	void __iomem *epio;
 
-	musb_platform_restore_context(musb, &musb_context);
-
 	if (is_host_enabled(musb)) {
-		musb_writew(musb_base, MUSB_FRAME, musb_context.frame);
-		musb_writeb(musb_base, MUSB_TESTMODE, musb_context.testmode);
-		musb_write_ulpi_buscontrol(musb->mregs, musb_context.busctl);
+		musb_writew(musb_base, MUSB_FRAME, musb->context.frame);
+		musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
+		musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
 	}
-	musb_writeb(musb_base, MUSB_POWER, musb_context.power);
-	musb_writew(musb_base, MUSB_INTRTXE, musb_context.intrtxe);
-	musb_writew(musb_base, MUSB_INTRRXE, musb_context.intrrxe);
-	musb_writeb(musb_base, MUSB_INTRUSBE, musb_context.intrusbe);
-	musb_writeb(musb_base, MUSB_DEVCTL, musb_context.devctl);
+	musb_writeb(musb_base, MUSB_POWER, musb->context.power);
+	musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe);
+	musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe);
+	musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);
+	musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
 
 	for (i = 0; i < musb->config->num_eps; ++i) {
 		epio = musb->endpoints[i].regs;
 		musb_writew(epio, MUSB_TXMAXP,
-			musb_context.index_regs[i].txmaxp);
+			musb->context.index_regs[i].txmaxp);
 		musb_writew(epio, MUSB_TXCSR,
-			musb_context.index_regs[i].txcsr);
+			musb->context.index_regs[i].txcsr);
 		musb_writew(epio, MUSB_RXMAXP,
-			musb_context.index_regs[i].rxmaxp);
+			musb->context.index_regs[i].rxmaxp);
 		musb_writew(epio, MUSB_RXCSR,
-			musb_context.index_regs[i].rxcsr);
+			musb->context.index_regs[i].rxcsr);
 
 		if (musb->dyn_fifo) {
 			musb_write_txfifosz(musb_base,
-				musb_context.index_regs[i].txfifosz);
+				musb->context.index_regs[i].txfifosz);
 			musb_write_rxfifosz(musb_base,
-				musb_context.index_regs[i].rxfifosz);
+				musb->context.index_regs[i].rxfifosz);
 			musb_write_txfifoadd(musb_base,
-				musb_context.index_regs[i].txfifoadd);
+				musb->context.index_regs[i].txfifoadd);
 			musb_write_rxfifoadd(musb_base,
-				musb_context.index_regs[i].rxfifoadd);
+				musb->context.index_regs[i].rxfifoadd);
 		}
 
 		if (is_host_enabled(musb)) {
 			musb_writeb(epio, MUSB_TXTYPE,
-				musb_context.index_regs[i].txtype);
+				musb->context.index_regs[i].txtype);
 			musb_writeb(epio, MUSB_TXINTERVAL,
-				musb_context.index_regs[i].txinterval);
+				musb->context.index_regs[i].txinterval);
 			musb_writeb(epio, MUSB_RXTYPE,
-				musb_context.index_regs[i].rxtype);
+				musb->context.index_regs[i].rxtype);
 			musb_writeb(epio, MUSB_RXINTERVAL,
 
-			musb_context.index_regs[i].rxinterval);
+			musb->context.index_regs[i].rxinterval);
 			musb_write_txfunaddr(musb_base, i,
-				musb_context.index_regs[i].txfunaddr);
+				musb->context.index_regs[i].txfunaddr);
 			musb_write_txhubaddr(musb_base, i,
-				musb_context.index_regs[i].txhubaddr);
+				musb->context.index_regs[i].txhubaddr);
 			musb_write_txhubport(musb_base, i,
-				musb_context.index_regs[i].txhubport);
+				musb->context.index_regs[i].txhubport);
 
 			ep_target_regs =
 				musb_read_target_reg_base(i, musb_base);
 
 			musb_write_rxfunaddr(ep_target_regs,
-				musb_context.index_regs[i].rxfunaddr);
+				musb->context.index_regs[i].rxfunaddr);
 			musb_write_rxhubaddr(ep_target_regs,
-				musb_context.index_regs[i].rxhubaddr);
+				musb->context.index_regs[i].rxhubaddr);
 			musb_write_rxhubport(ep_target_regs,
-				musb_context.index_regs[i].rxhubport);
+				musb->context.index_regs[i].rxhubport);
 		}
 	}
 }
@@ -2411,9 +2375,6 @@ static int musb_suspend(struct device *dev)
 	unsigned long	flags;
 	struct musb	*musb = dev_to_musb(&pdev->dev);
 
-	if (!musb->clock)
-		return 0;
-
 	spin_lock_irqsave(&musb->lock, flags);
 
 	if (is_peripheral_active(musb)) {
@@ -2428,10 +2389,6 @@ static int musb_suspend(struct device *dev)
 
 	musb_save_context(musb);
 
-	if (musb->set_clock)
-		musb->set_clock(musb->clock, 0);
-	else
-		clk_disable(musb->clock);
 	spin_unlock_irqrestore(&musb->lock, flags);
 	return 0;
 }
@@ -2441,14 +2398,6 @@ static int musb_resume_noirq(struct device *dev)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct musb	*musb = dev_to_musb(&pdev->dev);
 
-	if (!musb->clock)
-		return 0;
-
-	if (musb->set_clock)
-		musb->set_clock(musb->clock, 1);
-	else
-		clk_enable(musb->clock);
-
 	musb_restore_context(musb);
 
 	/* for static cmos like DaVinci, register values were preserved
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 6ad72f395e28..d0c236f8e191 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -222,7 +222,7 @@ enum musb_g_ep0_state {
 #endif
 
 /* TUSB mapping: "flat" plus ep0 special cases */
-#if	defined(CONFIG_USB_TUSB6010)
+#if	defined(CONFIG_USB_MUSB_TUSB6010)
 #define musb_ep_select(_mbase, _epnum) \
 	musb_writeb((_mbase), MUSB_INDEX, (_epnum))
 #define	MUSB_EP_OFFSET			MUSB_TUSB_OFFSET
@@ -253,6 +253,29 @@ enum musb_g_ep0_state {
 
 /******************************** TYPES *************************************/
 
+/**
+ * struct musb_platform_ops - Operations passed to musb_core by HW glue layer
+ * @init:	turns on clocks, sets up platform-specific registers, etc
+ * @exit:	undoes @init
+ * @set_mode:	forcefully changes operating mode
+ * @try_ilde:	tries to idle the IP
+ * @vbus_status: returns vbus status if possible
+ * @set_vbus:	forces vbus status
+ */
+struct musb_platform_ops {
+	int	(*init)(struct musb *musb);
+	int	(*exit)(struct musb *musb);
+
+	void	(*enable)(struct musb *musb);
+	void	(*disable)(struct musb *musb);
+
+	int	(*set_mode)(struct musb *musb, u8 mode);
+	void	(*try_idle)(struct musb *musb, unsigned long timeout);
+
+	int	(*vbus_status)(struct musb *musb);
+	void	(*set_vbus)(struct musb *musb, int on);
+};
+
 /*
  * struct musb_hw_ep - endpoint hardware (bidirectional)
  *
@@ -263,7 +286,7 @@ struct musb_hw_ep {
 	void __iomem		*fifo;
 	void __iomem		*regs;
 
-#ifdef CONFIG_USB_TUSB6010
+#ifdef CONFIG_USB_MUSB_TUSB6010
 	void __iomem		*conf;
 #endif
 
@@ -280,7 +303,7 @@ struct musb_hw_ep {
 	struct dma_channel	*tx_channel;
 	struct dma_channel	*rx_channel;
 
-#ifdef CONFIG_USB_TUSB6010
+#ifdef CONFIG_USB_MUSB_TUSB6010
 	/* TUSB has "asynchronous" and "synchronous" dma modes */
 	dma_addr_t		fifo_async;
 	dma_addr_t		fifo_sync;
@@ -323,14 +346,43 @@ static inline struct usb_request *next_out_request(struct musb_hw_ep *hw_ep)
 #endif
 }
 
+struct musb_csr_regs {
+	/* FIFO registers */
+	u16 txmaxp, txcsr, rxmaxp, rxcsr;
+	u16 rxfifoadd, txfifoadd;
+	u8 txtype, txinterval, rxtype, rxinterval;
+	u8 rxfifosz, txfifosz;
+	u8 txfunaddr, txhubaddr, txhubport;
+	u8 rxfunaddr, rxhubaddr, rxhubport;
+};
+
+struct musb_context_registers {
+
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+    defined(CONFIG_ARCH_OMAP4)
+	u32 otg_sysconfig, otg_forcestandby;
+#endif
+	u8 power;
+	u16 intrtxe, intrrxe;
+	u8 intrusbe;
+	u16 frame;
+	u8 index, testmode;
+
+	u8 devctl, busctl, misc;
+
+	struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
+};
+
 /*
  * struct musb - Driver instance data.
  */
 struct musb {
 	/* device lock */
 	spinlock_t		lock;
-	struct clk		*clock;
-	struct clk		*phy_clock;
+
+	const struct musb_platform_ops *ops;
+	struct musb_context_registers context;
+
 	irqreturn_t		(*isr)(int, void *);
 	struct work_struct	irq_work;
 	u16			hwvers;
@@ -359,11 +411,7 @@ struct musb {
 
 	struct timer_list	otg_timer;
 #endif
-
-	/* called with IRQs blocked; ON/nonzero implies starting a session,
-	 * and waiting at least a_wait_vrise_tmout.
-	 */
-	void			(*board_set_vbus)(struct musb *, int is_on);
+	struct notifier_block	nb;
 
 	struct dma_controller	*dma_controller;
 
@@ -371,7 +419,7 @@ struct musb {
 	void __iomem		*ctrl_base;
 	void __iomem		*mregs;
 
-#ifdef CONFIG_USB_TUSB6010
+#ifdef CONFIG_USB_MUSB_TUSB6010
 	dma_addr_t		async;
 	dma_addr_t		sync;
 	void __iomem		*sync_va;
@@ -398,8 +446,6 @@ struct musb {
 	u8 board_mode;		/* enum musb_mode */
 	int			(*board_set_power)(int state);
 
-	int			(*set_clock)(struct clk *clk, int is_active);
-
 	u8			min_power;	/* vbus for periph, in mA/2 */
 
 	bool			is_host;
@@ -458,52 +504,6 @@ struct musb {
 #endif
 };
 
-#ifdef CONFIG_PM
-struct musb_csr_regs {
-	/* FIFO registers */
-	u16 txmaxp, txcsr, rxmaxp, rxcsr;
-	u16 rxfifoadd, txfifoadd;
-	u8 txtype, txinterval, rxtype, rxinterval;
-	u8 rxfifosz, txfifosz;
-	u8 txfunaddr, txhubaddr, txhubport;
-	u8 rxfunaddr, rxhubaddr, rxhubport;
-};
-
-struct musb_context_registers {
-
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
-    defined(CONFIG_ARCH_OMAP4)
-	u32 otg_sysconfig, otg_forcestandby;
-#endif
-	u8 power;
-	u16 intrtxe, intrrxe;
-	u8 intrusbe;
-	u16 frame;
-	u8 index, testmode;
-
-	u8 devctl, busctl, misc;
-
-	struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
-};
-
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
-    defined(CONFIG_ARCH_OMAP4)
-extern void musb_platform_save_context(struct musb *musb,
-		struct musb_context_registers *musb_context);
-extern void musb_platform_restore_context(struct musb *musb,
-		struct musb_context_registers *musb_context);
-#else
-#define musb_platform_save_context(m, x)	do {} while (0)
-#define musb_platform_restore_context(m, x)	do {} while (0)
-#endif
-
-#endif
-
-static inline void musb_set_vbus(struct musb *musb, int is_on)
-{
-	musb->board_set_vbus(musb, is_on);
-}
-
 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
 static inline struct musb *gadget_to_musb(struct usb_gadget *g)
 {
@@ -592,29 +592,63 @@ extern void musb_load_testpacket(struct musb *);
 
 extern irqreturn_t musb_interrupt(struct musb *);
 
-extern void musb_platform_enable(struct musb *musb);
-extern void musb_platform_disable(struct musb *musb);
-
 extern void musb_hnp_stop(struct musb *musb);
 
-extern int musb_platform_set_mode(struct musb *musb, u8 musb_mode);
+static inline void musb_platform_set_vbus(struct musb *musb, int is_on)
+{
+	if (musb->ops->set_vbus)
+		musb->ops->set_vbus(musb, is_on);
+}
 
-#if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN) || \
-	defined(CONFIG_ARCH_DAVINCI_DA8XX) || \
-	defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
-	defined(CONFIG_ARCH_OMAP4)
-extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout);
-#else
-#define musb_platform_try_idle(x, y)		do {} while (0)
-#endif
+static inline void musb_platform_enable(struct musb *musb)
+{
+	if (musb->ops->enable)
+		musb->ops->enable(musb);
+}
 
-#if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN)
-extern int musb_platform_get_vbus_status(struct musb *musb);
-#else
-#define musb_platform_get_vbus_status(x)	0
-#endif
+static inline void musb_platform_disable(struct musb *musb)
+{
+	if (musb->ops->disable)
+		musb->ops->disable(musb);
+}
+
+static inline int musb_platform_set_mode(struct musb *musb, u8 mode)
+{
+	if (!musb->ops->set_mode)
+		return 0;
+
+	return musb->ops->set_mode(musb, mode);
+}
+
+static inline void musb_platform_try_idle(struct musb *musb,
+		unsigned long timeout)
+{
+	if (musb->ops->try_idle)
+		musb->ops->try_idle(musb, timeout);
+}
+
+static inline int musb_platform_get_vbus_status(struct musb *musb)
+{
+	if (!musb->ops->vbus_status)
+		return 0;
 
-extern int __init musb_platform_init(struct musb *musb);
-extern int musb_platform_exit(struct musb *musb);
+	return musb->ops->vbus_status(musb);
+}
+
+static inline int musb_platform_init(struct musb *musb)
+{
+	if (!musb->ops->init)
+		return -EINVAL;
+
+	return musb->ops->init(musb);
+}
+
+static inline int musb_platform_exit(struct musb *musb)
+{
+	if (!musb->ops->exit)
+		return -EINVAL;
+
+	return musb->ops->exit(musb);
+}
 
 #endif	/* __MUSB_CORE_H__ */
diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h
index b06e9ef00cfc..03c6ccdbb3be 100644
--- a/drivers/usb/musb/musb_io.h
+++ b/drivers/usb/musb/musb_io.h
@@ -74,7 +74,7 @@ static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data)
 	{ __raw_writel(data, addr + offset); }
 
 
-#ifdef CONFIG_USB_TUSB6010
+#ifdef CONFIG_USB_MUSB_TUSB6010
 
 /*
  * TUSB6010 doesn't allow 8-bit access; 16-bit access is the minimum.
@@ -114,7 +114,7 @@ static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
 static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
 	{ __raw_writeb(data, addr + offset); }
 
-#endif	/* CONFIG_USB_TUSB6010 */
+#endif	/* CONFIG_USB_MUSB_TUSB6010 */
 
 #else
 
diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h
index 244267527a60..9cb5fe044438 100644
--- a/drivers/usb/musb/musb_regs.h
+++ b/drivers/usb/musb/musb_regs.h
@@ -234,7 +234,7 @@
 #define MUSB_TESTMODE		0x0F	/* 8 bit */
 
 /* Get offset for a given FIFO from musb->mregs */
-#ifdef	CONFIG_USB_TUSB6010
+#ifdef	CONFIG_USB_MUSB_TUSB6010
 #define MUSB_FIFO_OFFSET(epnum)	(0x200 + ((epnum) * 0x20))
 #else
 #define MUSB_FIFO_OFFSET(epnum)	(0x20 + ((epnum) * 4))
@@ -295,7 +295,7 @@
 #define MUSB_FLAT_OFFSET(_epnum, _offset)	\
 	(0x100 + (0x10*(_epnum)) + (_offset))
 
-#ifdef CONFIG_USB_TUSB6010
+#ifdef CONFIG_USB_MUSB_TUSB6010
 /* TUSB6010 EP0 configuration register is special */
 #define MUSB_TUSB_OFFSET(_epnum, _offset)	\
 	(0x10 + _offset)
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index 43233c397b6e..b46d1877e28e 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -276,7 +276,7 @@ int musb_hub_control(
 			break;
 		case USB_PORT_FEAT_POWER:
 			if (!(is_otg_enabled(musb) && hcd->self.is_b_host))
-				musb_set_vbus(musb, 0);
+				musb_platform_set_vbus(musb, 0);
 			break;
 		case USB_PORT_FEAT_C_CONNECTION:
 		case USB_PORT_FEAT_C_ENABLE:
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 27dabcf0a868..a3f12333fc41 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -31,10 +31,18 @@
 #include <linux/list.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 
 #include "musb_core.h"
 #include "omap2430.h"
 
+struct omap2430_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+	struct clk		*clk;
+};
+#define glue_to_musb(g)		platform_get_drvdata(g->musb)
 
 static struct timer_list musb_idle_timer;
 
@@ -49,12 +57,8 @@ static void musb_do_idle(unsigned long _musb)
 
 	spin_lock_irqsave(&musb->lock, flags);
 
-	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
-
 	switch (musb->xceiv->state) {
 	case OTG_STATE_A_WAIT_BCON:
-		devctl &= ~MUSB_DEVCTL_SESSION;
-		musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 
 		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 		if (devctl & MUSB_DEVCTL_BDEVICE) {
@@ -98,7 +102,7 @@ static void musb_do_idle(unsigned long _musb)
 }
 
 
-void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
 {
 	unsigned long		default_timeout = jiffies + msecs_to_jiffies(3);
 	static unsigned long	last_timer;
@@ -131,15 +135,11 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
 	mod_timer(&musb_idle_timer, timeout);
 }
 
-void musb_platform_enable(struct musb *musb)
-{
-}
-void musb_platform_disable(struct musb *musb)
-{
-}
-static void omap_set_vbus(struct musb *musb, int is_on)
+static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
 {
 	u8		devctl;
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+	int ret = 1;
 	/* HDRC controls CPEN, but beware current surges during device
 	 * connect.  They can trigger transient overcurrent conditions
 	 * that must be ignored.
@@ -148,12 +148,35 @@ static void omap_set_vbus(struct musb *musb, int is_on)
 	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
 	if (is_on) {
-		musb->is_active = 1;
-		musb->xceiv->default_a = 1;
-		musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
-		devctl |= MUSB_DEVCTL_SESSION;
-
-		MUSB_HST_MODE(musb);
+		if (musb->xceiv->state == OTG_STATE_A_IDLE) {
+			/* start the session */
+			devctl |= MUSB_DEVCTL_SESSION;
+			musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+			/*
+			 * Wait for the musb to set as A device to enable the
+			 * VBUS
+			 */
+			while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
+
+				cpu_relax();
+
+				if (time_after(jiffies, timeout)) {
+					dev_err(musb->controller,
+					"configured as A device timeout");
+					ret = -EINVAL;
+					break;
+				}
+			}
+
+			if (ret && musb->xceiv->set_vbus)
+				otg_set_vbus(musb->xceiv, 1);
+		} else {
+			musb->is_active = 1;
+			musb->xceiv->default_a = 1;
+			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+			devctl |= MUSB_DEVCTL_SESSION;
+			MUSB_HST_MODE(musb);
+		}
 	} else {
 		musb->is_active = 0;
 
@@ -175,9 +198,7 @@ static void omap_set_vbus(struct musb *musb, int is_on)
 		musb_readb(musb->mregs, MUSB_DEVCTL));
 }
 
-static int musb_platform_resume(struct musb *musb);
-
-int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+static int omap2430_musb_set_mode(struct musb *musb, u8 musb_mode)
 {
 	u8	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
@@ -187,9 +208,91 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
 	return 0;
 }
 
-int __init musb_platform_init(struct musb *musb)
+static inline void omap2430_low_level_exit(struct musb *musb)
+{
+	u32 l;
+
+	/* in any role */
+	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
+	l |= ENABLEFORCE;	/* enable MSTANDBY */
+	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
+
+	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
+	l |= ENABLEWAKEUP;	/* enable wakeup */
+	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
+}
+
+static inline void omap2430_low_level_init(struct musb *musb)
 {
 	u32 l;
+
+	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
+	l &= ~ENABLEWAKEUP;	/* disable wakeup */
+	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
+
+	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
+	l &= ~ENABLEFORCE;	/* disable MSTANDBY */
+	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
+}
+
+/* blocking notifier support */
+static int musb_otg_notifications(struct notifier_block *nb,
+		unsigned long event, void *unused)
+{
+	struct musb	*musb = container_of(nb, struct musb, nb);
+	struct device *dev = musb->controller;
+	struct musb_hdrc_platform_data *pdata = dev->platform_data;
+	struct omap_musb_board_data *data = pdata->board_data;
+
+	switch (event) {
+	case USB_EVENT_ID:
+		DBG(4, "ID GND\n");
+
+		if (is_otg_enabled(musb)) {
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+			if (musb->gadget_driver) {
+				otg_init(musb->xceiv);
+
+				if (data->interface_type ==
+						MUSB_INTERFACE_UTMI)
+					omap2430_musb_set_vbus(musb, 1);
+
+			}
+#endif
+		} else {
+			otg_init(musb->xceiv);
+			if (data->interface_type ==
+					MUSB_INTERFACE_UTMI)
+				omap2430_musb_set_vbus(musb, 1);
+		}
+		break;
+
+	case USB_EVENT_VBUS:
+		DBG(4, "VBUS Connect\n");
+
+		otg_init(musb->xceiv);
+		break;
+
+	case USB_EVENT_NONE:
+		DBG(4, "VBUS Disconnect\n");
+
+		if (data->interface_type == MUSB_INTERFACE_UTMI) {
+			if (musb->xceiv->set_vbus)
+				otg_set_vbus(musb->xceiv, 0);
+		}
+		otg_shutdown(musb->xceiv);
+		break;
+	default:
+		DBG(4, "ID float\n");
+		return NOTIFY_DONE;
+	}
+
+	return NOTIFY_OK;
+}
+
+static int omap2430_musb_init(struct musb *musb)
+{
+	u32 l, status = 0;
 	struct device *dev = musb->controller;
 	struct musb_hdrc_platform_data *plat = dev->platform_data;
 	struct omap_musb_board_data *data = plat->board_data;
@@ -204,7 +307,7 @@ int __init musb_platform_init(struct musb *musb)
 		return -ENODEV;
 	}
 
-	musb_platform_resume(musb);
+	omap2430_low_level_init(musb);
 
 	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
 	l &= ~ENABLEWAKEUP;	/* disable wakeup */
@@ -241,87 +344,214 @@ int __init musb_platform_init(struct musb *musb)
 			musb_readl(musb->mregs, OTG_INTERFSEL),
 			musb_readl(musb->mregs, OTG_SIMENABLE));
 
-	if (is_host_enabled(musb))
-		musb->board_set_vbus = omap_set_vbus;
+	musb->nb.notifier_call = musb_otg_notifications;
+	status = otg_register_notifier(musb->xceiv, &musb->nb);
+
+	if (status)
+		DBG(1, "notification register failed\n");
+
+	/* check whether cable is already connected */
+	if (musb->xceiv->state ==OTG_STATE_B_IDLE)
+		musb_otg_notifications(&musb->nb, 1,
+					musb->xceiv->gadget);
 
 	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
 
 	return 0;
 }
 
-#ifdef CONFIG_PM
-void musb_platform_save_context(struct musb *musb,
-		struct musb_context_registers *musb_context)
+static int omap2430_musb_exit(struct musb *musb)
 {
-	musb_context->otg_sysconfig = musb_readl(musb->mregs, OTG_SYSCONFIG);
-	musb_context->otg_forcestandby = musb_readl(musb->mregs, OTG_FORCESTDBY);
-}
 
-void musb_platform_restore_context(struct musb *musb,
-		struct musb_context_registers *musb_context)
-{
-	musb_writel(musb->mregs, OTG_SYSCONFIG, musb_context->otg_sysconfig);
-	musb_writel(musb->mregs, OTG_FORCESTDBY, musb_context->otg_forcestandby);
+	omap2430_low_level_exit(musb);
+	otg_put_transceiver(musb->xceiv);
+
+	return 0;
 }
-#endif
 
-static int musb_platform_suspend(struct musb *musb)
+static const struct musb_platform_ops omap2430_ops = {
+	.init		= omap2430_musb_init,
+	.exit		= omap2430_musb_exit,
+
+	.set_mode	= omap2430_musb_set_mode,
+	.try_idle	= omap2430_musb_try_idle,
+
+	.set_vbus	= omap2430_musb_set_vbus,
+};
+
+static u64 omap2430_dmamask = DMA_BIT_MASK(32);
+
+static int __init omap2430_probe(struct platform_device *pdev)
 {
-	u32 l;
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct omap2430_glue		*glue;
+	struct clk			*clk;
 
-	if (!musb->clock)
-		return 0;
+	int				ret = -ENOMEM;
 
-	/* in any role */
-	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
-	l |= ENABLEFORCE;	/* enable MSTANDBY */
-	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
 
-	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
-	l |= ENABLEWAKEUP;	/* enable wakeup */
-	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
 
-	otg_set_suspend(musb->xceiv, 1);
+	clk = clk_get(&pdev->dev, "ick");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		ret = PTR_ERR(clk);
+		goto err2;
+	}
 
-	if (musb->set_clock)
-		musb->set_clock(musb->clock, 0);
-	else
-		clk_disable(musb->clock);
+	ret = clk_enable(clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clock\n");
+		goto err3;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+	musb->dev.dma_mask		= &omap2430_dmamask;
+	musb->dev.coherent_dma_mask	= omap2430_dmamask;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+	glue->clk			= clk;
+
+	pdata->platform_ops		= &omap2430_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err4;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err4;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err4;
+	}
 
 	return 0;
+
+err4:
+	clk_disable(clk);
+
+err3:
+	clk_put(clk);
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
 }
 
-static int musb_platform_resume(struct musb *musb)
+static int __exit omap2430_remove(struct platform_device *pdev)
 {
-	u32 l;
+	struct omap2430_glue		*glue = platform_get_drvdata(pdev);
 
-	if (!musb->clock)
-		return 0;
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	clk_disable(glue->clk);
+	clk_put(glue->clk);
+	kfree(glue);
 
-	otg_set_suspend(musb->xceiv, 0);
+	return 0;
+}
 
-	if (musb->set_clock)
-		musb->set_clock(musb->clock, 1);
-	else
-		clk_enable(musb->clock);
+#ifdef CONFIG_PM
+static void omap2430_save_context(struct musb *musb)
+{
+	musb->context.otg_sysconfig = musb_readl(musb->mregs, OTG_SYSCONFIG);
+	musb->context.otg_forcestandby = musb_readl(musb->mregs, OTG_FORCESTDBY);
+}
 
-	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
-	l &= ~ENABLEWAKEUP;	/* disable wakeup */
-	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
+static void omap2430_restore_context(struct musb *musb)
+{
+	musb_writel(musb->mregs, OTG_SYSCONFIG, musb->context.otg_sysconfig);
+	musb_writel(musb->mregs, OTG_FORCESTDBY, musb->context.otg_forcestandby);
+}
 
-	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
-	l &= ~ENABLEFORCE;	/* disable MSTANDBY */
-	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
+static int omap2430_suspend(struct device *dev)
+{
+	struct omap2430_glue		*glue = dev_get_drvdata(dev);
+	struct musb			*musb = glue_to_musb(glue);
+
+	omap2430_low_level_exit(musb);
+	otg_set_suspend(musb->xceiv, 1);
+	omap2430_save_context(musb);
+	clk_disable(glue->clk);
 
 	return 0;
 }
 
-
-int musb_platform_exit(struct musb *musb)
+static int omap2430_resume(struct device *dev)
 {
+	struct omap2430_glue		*glue = dev_get_drvdata(dev);
+	struct musb			*musb = glue_to_musb(glue);
+	int				ret;
+
+	ret = clk_enable(glue->clk);
+	if (ret) {
+		dev_err(dev, "faled to enable clock\n");
+		return ret;
+	}
 
-	musb_platform_suspend(musb);
+	omap2430_low_level_init(musb);
+	omap2430_restore_context(musb);
+	otg_set_suspend(musb->xceiv, 0);
 
-	otg_put_transceiver(musb->xceiv);
 	return 0;
 }
+
+static struct dev_pm_ops omap2430_pm_ops = {
+	.suspend	= omap2430_suspend,
+	.resume		= omap2430_resume,
+};
+
+#define DEV_PM_OPS	(&omap2430_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
+static struct platform_driver omap2430_driver = {
+	.remove		= __exit_p(omap2430_remove),
+	.driver		= {
+		.name	= "musb-omap2430",
+		.pm	= DEV_PM_OPS,
+	},
+};
+
+MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer");
+MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init omap2430_init(void)
+{
+	return platform_driver_probe(&omap2430_driver, omap2430_probe);
+}
+subsys_initcall(omap2430_init);
+
+static void __exit omap2430_exit(void)
+{
+	platform_driver_unregister(&omap2430_driver);
+}
+module_exit(omap2430_exit);
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 41b04b906ce1..2ba3b070ed0b 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -21,10 +21,16 @@
 #include <linux/usb.h>
 #include <linux/irq.h>
 #include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 
 #include "musb_core.h"
 
-static void tusb_source_power(struct musb *musb, int is_on);
+struct tusb6010_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+};
+
+static void tusb_musb_set_vbus(struct musb *musb, int is_on);
 
 #define TUSB_REV_MAJOR(reg_val)		((reg_val >> 4) & 0xf)
 #define TUSB_REV_MINOR(reg_val)		(reg_val & 0xf)
@@ -50,7 +56,7 @@ u8 tusb_get_revision(struct musb *musb)
 	return rev;
 }
 
-static int __init tusb_print_revision(struct musb *musb)
+static int tusb_print_revision(struct musb *musb)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 	u8		rev;
@@ -275,17 +281,6 @@ static int tusb_draw_power(struct otg_transceiver *x, unsigned mA)
 	void __iomem	*tbase = musb->ctrl_base;
 	u32		reg;
 
-	/*
-	 * Keep clock active when enabled. Note that this is not tied to
-	 * drawing VBUS, as with OTG mA can be less than musb->min_power.
-	 */
-	if (musb->set_clock) {
-		if (mA)
-			musb->set_clock(musb->clock, 1);
-		else
-			musb->set_clock(musb->clock, 0);
-	}
-
 	/* tps65030 seems to consume max 100mA, with maybe 60mA available
 	 * (measured on one board) for things other than tps and tusb.
 	 *
@@ -348,7 +343,7 @@ static void tusb_set_clock_source(struct musb *musb, unsigned mode)
  * USB link is not suspended ... and tells us the relevant wakeup
  * events.  SW_EN for voltage is handled separately.
  */
-void tusb_allow_idle(struct musb *musb, u32 wakeup_enables)
+static void tusb_allow_idle(struct musb *musb, u32 wakeup_enables)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 	u32		reg;
@@ -385,7 +380,7 @@ void tusb_allow_idle(struct musb *musb, u32 wakeup_enables)
 /*
  * Updates cable VBUS status. Caller must take care of locking.
  */
-int musb_platform_get_vbus_status(struct musb *musb)
+static int tusb_musb_vbus_status(struct musb *musb)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 	u32		otg_stat, prcm_mngmt;
@@ -431,7 +426,7 @@ static void musb_do_idle(unsigned long _musb)
 		}
 		/* FALLTHROUGH */
 	case OTG_STATE_A_IDLE:
-		tusb_source_power(musb, 0);
+		tusb_musb_set_vbus(musb, 0);
 	default:
 		break;
 	}
@@ -475,7 +470,7 @@ done:
  * we don't want to treat that full speed J as a wakeup event.
  * ... peripherals must draw only suspend current after 10 msec.
  */
-void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout)
 {
 	unsigned long		default_timeout = jiffies + msecs_to_jiffies(3);
 	static unsigned long	last_timer;
@@ -515,7 +510,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
 				| TUSB_DEV_OTG_TIMER_ENABLE) \
 		: 0)
 
-static void tusb_source_power(struct musb *musb, int is_on)
+static void tusb_musb_set_vbus(struct musb *musb, int is_on)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 	u32		conf, prcm, timer;
@@ -531,8 +526,6 @@ static void tusb_source_power(struct musb *musb, int is_on)
 	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
 	if (is_on) {
-		if (musb->set_clock)
-			musb->set_clock(musb->clock, 1);
 		timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE);
 		musb->xceiv->default_a = 1;
 		musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
@@ -571,8 +564,6 @@ static void tusb_source_power(struct musb *musb, int is_on)
 
 		devctl &= ~MUSB_DEVCTL_SESSION;
 		conf &= ~TUSB_DEV_CONF_USB_HOST_MODE;
-		if (musb->set_clock)
-			musb->set_clock(musb->clock, 0);
 	}
 	prcm &= ~(TUSB_PRCM_MNGMT_15_SW_EN | TUSB_PRCM_MNGMT_33_SW_EN);
 
@@ -599,7 +590,7 @@ static void tusb_source_power(struct musb *musb, int is_on)
  * and peripheral modes in non-OTG configurations by reconfiguring hardware
  * and then setting musb->board_mode. For now, only support OTG mode.
  */
-int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+static int tusb_musb_set_mode(struct musb *musb, u8 musb_mode)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 	u32		otg_stat, phy_otg_ctrl, phy_otg_ena, dev_conf;
@@ -677,7 +668,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
 			default_a = is_host_enabled(musb);
 		DBG(2, "Default-%c\n", default_a ? 'A' : 'B');
 		musb->xceiv->default_a = default_a;
-		tusb_source_power(musb, default_a);
+		tusb_musb_set_vbus(musb, default_a);
 
 		/* Don't allow idling immediately */
 		if (default_a)
@@ -722,7 +713,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
 			switch (musb->xceiv->state) {
 			case OTG_STATE_A_IDLE:
 				DBG(2, "Got SRP, turning on VBUS\n");
-				musb_set_vbus(musb, 1);
+				musb_platform_set_vbus(musb, 1);
 
 				/* CONNECT can wake if a_wait_bcon is set */
 				if (musb->a_wait_bcon != 0)
@@ -748,11 +739,11 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
 				 */
 				if (musb->vbuserr_retry) {
 					musb->vbuserr_retry--;
-					tusb_source_power(musb, 1);
+					tusb_musb_set_vbus(musb, 1);
 				} else {
 					musb->vbuserr_retry
 						= VBUSERR_RETRY_COUNT;
-					tusb_source_power(musb, 0);
+					tusb_musb_set_vbus(musb, 0);
 				}
 				break;
 			default:
@@ -786,7 +777,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
 			} else {
 				/* REVISIT report overcurrent to hub? */
 				ERR("vbus too slow, devctl %02x\n", devctl);
-				tusb_source_power(musb, 0);
+				tusb_musb_set_vbus(musb, 0);
 			}
 			break;
 		case OTG_STATE_A_WAIT_BCON:
@@ -807,7 +798,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
 	return idle_timeout;
 }
 
-static irqreturn_t tusb_interrupt(int irq, void *__hci)
+static irqreturn_t tusb_musb_interrupt(int irq, void *__hci)
 {
 	struct musb	*musb = __hci;
 	void __iomem	*tbase = musb->ctrl_base;
@@ -911,7 +902,7 @@ static irqreturn_t tusb_interrupt(int irq, void *__hci)
 	musb_writel(tbase, TUSB_INT_SRC_CLEAR,
 		int_src & ~TUSB_INT_MASK_RESERVED_BITS);
 
-	musb_platform_try_idle(musb, idle_timeout);
+	tusb_musb_try_idle(musb, idle_timeout);
 
 	musb_writel(tbase, TUSB_INT_MASK, int_mask);
 	spin_unlock_irqrestore(&musb->lock, flags);
@@ -926,7 +917,7 @@ static int dma_off;
  * REVISIT:
  * - Check what is unnecessary in MGC_HdrcStart()
  */
-void musb_platform_enable(struct musb *musb)
+static void tusb_musb_enable(struct musb *musb)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 
@@ -970,7 +961,7 @@ void musb_platform_enable(struct musb *musb)
 /*
  * Disables TUSB6010. Caller must take care of locking.
  */
-void musb_platform_disable(struct musb *musb)
+static void tusb_musb_disable(struct musb *musb)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 
@@ -995,7 +986,7 @@ void musb_platform_disable(struct musb *musb)
  * Sets up TUSB6010 CPU interface specific signals and registers
  * Note: Settings optimized for OMAP24xx
  */
-static void __init tusb_setup_cpu_interface(struct musb *musb)
+static void tusb_setup_cpu_interface(struct musb *musb)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 
@@ -1022,7 +1013,7 @@ static void __init tusb_setup_cpu_interface(struct musb *musb)
 	musb_writel(tbase, TUSB_WAIT_COUNT, 1);
 }
 
-static int __init tusb_start(struct musb *musb)
+static int tusb_musb_start(struct musb *musb)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 	int		ret = 0;
@@ -1091,7 +1082,7 @@ err:
 	return -ENODEV;
 }
 
-int __init musb_platform_init(struct musb *musb)
+static int tusb_musb_init(struct musb *musb)
 {
 	struct platform_device	*pdev;
 	struct resource		*mem;
@@ -1131,16 +1122,14 @@ int __init musb_platform_init(struct musb *musb)
 	 */
 	musb->mregs += TUSB_BASE_OFFSET;
 
-	ret = tusb_start(musb);
+	ret = tusb_musb_start(musb);
 	if (ret) {
 		printk(KERN_ERR "Could not start tusb6010 (%d)\n",
 				ret);
 		goto done;
 	}
-	musb->isr = tusb_interrupt;
+	musb->isr = tusb_musb_interrupt;
 
-	if (is_host_enabled(musb))
-		musb->board_set_vbus = tusb_source_power;
 	if (is_peripheral_enabled(musb)) {
 		musb->xceiv->set_power = tusb_draw_power;
 		the_musb = musb;
@@ -1159,7 +1148,7 @@ done:
 	return ret;
 }
 
-int musb_platform_exit(struct musb *musb)
+static int tusb_musb_exit(struct musb *musb)
 {
 	del_timer_sync(&musb_idle_timer);
 	the_musb = NULL;
@@ -1173,3 +1162,115 @@ int musb_platform_exit(struct musb *musb)
 	usb_nop_xceiv_unregister();
 	return 0;
 }
+
+static const struct musb_platform_ops tusb_ops = {
+	.init		= tusb_musb_init,
+	.exit		= tusb_musb_exit,
+
+	.enable		= tusb_musb_enable,
+	.disable	= tusb_musb_disable,
+
+	.set_mode	= tusb_musb_set_mode,
+	.try_idle	= tusb_musb_try_idle,
+
+	.vbus_status	= tusb_musb_vbus_status,
+	.set_vbus	= tusb_musb_set_vbus,
+};
+
+static u64 tusb_dmamask = DMA_BIT_MASK(32);
+
+static int __init tusb_probe(struct platform_device *pdev)
+{
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct tusb6010_glue		*glue;
+
+	int				ret = -ENOMEM;
+
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
+
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+	musb->dev.dma_mask		= &tusb_dmamask;
+	musb->dev.coherent_dma_mask	= tusb_dmamask;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+
+	pdata->platform_ops		= &tusb_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err2;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err2;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err1;
+	}
+
+	return 0;
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
+}
+
+static int __exit tusb_remove(struct platform_device *pdev)
+{
+	struct tusb6010_glue		*glue = platform_get_drvdata(pdev);
+
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	kfree(glue);
+
+	return 0;
+}
+
+static struct platform_driver tusb_driver = {
+	.remove		= __exit_p(tusb_remove),
+	.driver		= {
+		.name	= "musb-tusb",
+	},
+};
+
+MODULE_DESCRIPTION("TUSB6010 MUSB Glue Layer");
+MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init tusb_init(void)
+{
+	return platform_driver_probe(&tusb_driver, tusb_probe);
+}
+subsys_initcall(tusb_init);
+
+static void __exit tusb_exit(void)
+{
+	platform_driver_unregister(&tusb_driver);
+}
+module_exit(tusb_exit);
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
new file mode 100644
index 000000000000..d6384e4aeef9
--- /dev/null
+++ b/drivers/usb/musb/ux500.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2010 ST-Ericsson AB
+ * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
+ *
+ * Based on omap2430.c
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include "musb_core.h"
+
+struct ux500_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+	struct clk		*clk;
+};
+#define glue_to_musb(g)	platform_get_drvdata(g->musb)
+
+static int ux500_musb_init(struct musb *musb)
+{
+	musb->xceiv = otg_get_transceiver();
+	if (!musb->xceiv) {
+		pr_err("HS USB OTG: no transceiver configured\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int ux500_musb_exit(struct musb *musb)
+{
+	otg_put_transceiver(musb->xceiv);
+
+	return 0;
+}
+
+static const struct musb_platform_ops ux500_ops = {
+	.init		= ux500_musb_init,
+	.exit		= ux500_musb_exit,
+};
+
+static int __init ux500_probe(struct platform_device *pdev)
+{
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct ux500_glue		*glue;
+	struct clk			*clk;
+
+	int				ret = -ENOMEM;
+
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
+
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
+
+	clk = clk_get(&pdev->dev, "usb");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		ret = PTR_ERR(clk);
+		goto err2;
+	}
+
+	ret = clk_enable(clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clock\n");
+		goto err3;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+	glue->clk			= clk;
+
+	pdata->platform_ops		= &ux500_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err4;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err4;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err4;
+	}
+
+	return 0;
+
+err4:
+	clk_disable(clk);
+
+err3:
+	clk_put(clk);
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
+}
+
+static int __exit ux500_remove(struct platform_device *pdev)
+{
+	struct ux500_glue	*glue = platform_get_drvdata(pdev);
+
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	clk_disable(glue->clk);
+	clk_put(glue->clk);
+	kfree(glue);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ux500_suspend(struct device *dev)
+{
+	struct ux500_glue	*glue = dev_get_drvdata(dev);
+	struct musb		*musb = glue_to_musb(glue);
+
+	otg_set_suspend(musb->xceiv, 1);
+	clk_disable(glue->clk);
+
+	return 0;
+}
+
+static int ux500_resume(struct device *dev)
+{
+	struct ux500_glue	*glue = dev_get_drvdata(dev);
+	struct musb		*musb = glue_to_musb(glue);
+	int			ret;
+
+	ret = clk_enable(glue->clk);
+	if (ret) {
+		dev_err(dev, "failed to enable clock\n");
+		return ret;
+	}
+
+	otg_set_suspend(musb->xceiv, 0);
+
+	return 0;
+}
+
+static const struct dev_pm_ops ux500_pm_ops = {
+	.suspend	= ux500_suspend,
+	.resume		= ux500_resume,
+};
+
+#define DEV_PM_OPS	(&ux500_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
+static struct platform_driver ux500_driver = {
+	.remove		= __exit_p(ux500_remove),
+	.driver		= {
+		.name	= "musb-ux500",
+		.pm	= DEV_PM_OPS,
+	},
+};
+
+MODULE_DESCRIPTION("UX500 MUSB Glue Layer");
+MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init ux500_init(void)
+{
+	return platform_driver_probe(&ux500_driver, ux500_probe);
+}
+subsys_initcall(ux500_init);
+
+static void __exit ux500_exit(void)
+{
+	platform_driver_unregister(&ux500_driver);
+}
+module_exit(ux500_exit);
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 6491717a636a..9fb875d5f09c 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -59,6 +59,18 @@ config TWL4030_USB
 	  This transceiver supports high and full speed devices plus,
 	  in host mode, low speed.
 
+config TWL6030_USB
+	tristate "TWL6030 USB Transceiver Driver"
+	depends on TWL4030_CORE
+	select USB_OTG_UTILS
+	help
+	  Enable this to support the USB OTG transceiver on TWL6030
+	  family chips. This TWL6030 transceiver has the VBUS and ID GND
+	  and OTG SRP events capabilities. For all other transceiver functionality
+	  UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs
+	  are hooked to this driver through platform_data structure.
+	  The definition of internal PHY APIs are in the mach-omap2 layer.
+
 config NOP_USB_XCEIV
 	tristate "NOP USB Transceiver Driver"
 	select USB_OTG_UTILS
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index 30a23f3b7a1f..a520e715cfd6 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_USB_OTG_UTILS)	+= otg.o
 obj-$(CONFIG_USB_GPIO_VBUS)	+= gpio_vbus.o
 obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)	+= twl4030-usb.o
+obj-$(CONFIG_TWL6030_USB)	+= twl6030-usb.o
 obj-$(CONFIG_USB_LANGWELL_OTG)	+= langwell_otg.o
 obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o
 obj-$(CONFIG_USB_ULPI)		+= ulpi.o
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
new file mode 100644
index 000000000000..28f770103640
--- /dev/null
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -0,0 +1,493 @@
+/*
+ * twl6030_usb - TWL6030 USB transceiver, talking to OMAP OTG driver.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Hema HK <hemahk@ti.com>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/usb/otg.h>
+#include <linux/i2c/twl.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/notifier.h>
+#include <linux/slab.h>
+
+/* usb register definitions */
+#define USB_VENDOR_ID_LSB		0x00
+#define USB_VENDOR_ID_MSB		0x01
+#define USB_PRODUCT_ID_LSB		0x02
+#define USB_PRODUCT_ID_MSB		0x03
+#define USB_VBUS_CTRL_SET		0x04
+#define USB_VBUS_CTRL_CLR		0x05
+#define USB_ID_CTRL_SET			0x06
+#define USB_ID_CTRL_CLR			0x07
+#define USB_VBUS_INT_SRC		0x08
+#define USB_VBUS_INT_LATCH_SET		0x09
+#define USB_VBUS_INT_LATCH_CLR		0x0A
+#define USB_VBUS_INT_EN_LO_SET		0x0B
+#define USB_VBUS_INT_EN_LO_CLR		0x0C
+#define USB_VBUS_INT_EN_HI_SET		0x0D
+#define USB_VBUS_INT_EN_HI_CLR		0x0E
+#define USB_ID_INT_SRC			0x0F
+#define USB_ID_INT_LATCH_SET		0x10
+#define USB_ID_INT_LATCH_CLR		0x11
+
+#define USB_ID_INT_EN_LO_SET		0x12
+#define USB_ID_INT_EN_LO_CLR		0x13
+#define USB_ID_INT_EN_HI_SET		0x14
+#define USB_ID_INT_EN_HI_CLR		0x15
+#define USB_OTG_ADP_CTRL		0x16
+#define USB_OTG_ADP_HIGH		0x17
+#define USB_OTG_ADP_LOW			0x18
+#define USB_OTG_ADP_RISE		0x19
+#define USB_OTG_REVISION		0x1A
+
+/* to be moved to LDO */
+#define TWL6030_MISC2			0xE5
+#define TWL6030_CFG_LDO_PD2		0xF5
+#define TWL6030_BACKUP_REG		0xFA
+
+#define STS_HW_CONDITIONS		0x21
+
+/* In module TWL6030_MODULE_PM_MASTER */
+#define STS_HW_CONDITIONS		0x21
+#define STS_USB_ID			BIT(2)
+
+/* In module TWL6030_MODULE_PM_RECEIVER */
+#define VUSB_CFG_TRANS			0x71
+#define VUSB_CFG_STATE			0x72
+#define VUSB_CFG_VOLTAGE		0x73
+
+/* in module TWL6030_MODULE_MAIN_CHARGE */
+
+#define CHARGERUSB_CTRL1		0x8
+
+#define CONTROLLER_STAT1		0x03
+#define	VBUS_DET			BIT(2)
+
+struct twl6030_usb {
+	struct otg_transceiver	otg;
+	struct device		*dev;
+
+	/* for vbus reporting with irqs disabled */
+	spinlock_t		lock;
+
+	struct regulator		*usb3v3;
+
+	int			irq1;
+	int			irq2;
+	u8			linkstat;
+	u8			asleep;
+	bool			irq_enabled;
+};
+
+#define xceiv_to_twl(x)		container_of((x), struct twl6030_usb, otg);
+
+/*-------------------------------------------------------------------------*/
+
+static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
+						u8 data, u8 address)
+{
+	int ret = 0;
+
+	ret = twl_i2c_write_u8(module, data, address);
+	if (ret < 0)
+		dev_err(twl->dev,
+			"Write[0x%x] Error %d\n", address, ret);
+	return ret;
+}
+
+static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
+{
+	u8 data, ret = 0;
+
+	ret = twl_i2c_read_u8(module, &data, address);
+	if (ret >= 0)
+		ret = data;
+	else
+		dev_err(twl->dev,
+			"readb[0x%x,0x%x] Error %d\n",
+					module, address, ret);
+	return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+static int twl6030_set_phy_clk(struct otg_transceiver *x, int on)
+{
+	struct twl6030_usb *twl;
+	struct device *dev;
+	struct twl4030_usb_data *pdata;
+
+	twl = xceiv_to_twl(x);
+	dev  = twl->dev;
+	pdata = dev->platform_data;
+
+	pdata->phy_set_clock(twl->dev, on);
+
+	return 0;
+}
+
+static int twl6030_phy_init(struct otg_transceiver *x)
+{
+	u8 hw_state;
+	struct twl6030_usb *twl;
+	struct device *dev;
+	struct twl4030_usb_data *pdata;
+
+	twl = xceiv_to_twl(x);
+	dev  = twl->dev;
+	pdata = dev->platform_data;
+
+	regulator_enable(twl->usb3v3);
+
+	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
+
+	if (hw_state & STS_USB_ID)
+		pdata->phy_power(twl->dev, 1, 1);
+	else
+		pdata->phy_power(twl->dev, 0, 1);
+
+	return 0;
+}
+
+static void twl6030_phy_shutdown(struct otg_transceiver *x)
+{
+	struct twl6030_usb *twl;
+	struct device *dev;
+	struct twl4030_usb_data *pdata;
+
+	twl = xceiv_to_twl(x);
+	dev  = twl->dev;
+	pdata = dev->platform_data;
+	pdata->phy_power(twl->dev, 0, 0);
+	regulator_disable(twl->usb3v3);
+}
+
+static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
+{
+
+	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
+	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);
+
+	/* Program CFG_LDO_PD2 register and set VUSB bit */
+	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2);
+
+	/* Program MISC2 register and set bit VUSB_IN_VBAT */
+	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);
+
+	twl->usb3v3 = regulator_get(twl->dev, "vusb");
+	if (IS_ERR(twl->usb3v3))
+		return -ENODEV;
+
+	regulator_enable(twl->usb3v3);
+
+	/* Program the VUSB_CFG_TRANS for ACTIVE state. */
+	twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0x3F,
+						VUSB_CFG_TRANS);
+
+	/* Program the VUSB_CFG_STATE register to ON on all groups. */
+	twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0xE1,
+						VUSB_CFG_STATE);
+
+	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
+	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);
+
+	/*
+	 * Program the USB_ID_CTRL_SET register to enable GND drive
+	 * and the ID comparators
+	 */
+	twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET);
+
+	return 0;
+}
+
+static ssize_t twl6030_usb_vbus_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct twl6030_usb *twl = dev_get_drvdata(dev);
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	spin_lock_irqsave(&twl->lock, flags);
+
+	switch (twl->linkstat) {
+	case USB_EVENT_VBUS:
+	       ret = snprintf(buf, PAGE_SIZE, "vbus\n");
+	       break;
+	case USB_EVENT_ID:
+	       ret = snprintf(buf, PAGE_SIZE, "id\n");
+	       break;
+	case USB_EVENT_NONE:
+	       ret = snprintf(buf, PAGE_SIZE, "none\n");
+	       break;
+	default:
+	       ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
+	}
+	spin_unlock_irqrestore(&twl->lock, flags);
+
+	return ret;
+}
+static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
+
+static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
+{
+	struct twl6030_usb *twl = _twl;
+	int status;
+	u8 vbus_state, hw_state;
+
+	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
+
+	vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE,
+						CONTROLLER_STAT1);
+	if (!(hw_state & STS_USB_ID)) {
+		if (vbus_state & VBUS_DET) {
+			status = USB_EVENT_VBUS;
+			twl->otg.default_a = false;
+			twl->otg.state = OTG_STATE_B_IDLE;
+		} else {
+			status = USB_EVENT_NONE;
+		}
+		if (status >= 0) {
+			twl->linkstat = status;
+			blocking_notifier_call_chain(&twl->otg.notifier,
+						status, twl->otg.gadget);
+		}
+	}
+	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
+{
+	struct twl6030_usb *twl = _twl;
+	int status = USB_EVENT_NONE;
+	u8 hw_state;
+
+	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
+
+	if (hw_state & STS_USB_ID) {
+
+		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1);
+		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;
+		blocking_notifier_call_chain(&twl->otg.notifier, status,
+							twl->otg.gadget);
+	} else  {
+		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
+								0x10);
+		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
+								0x1);
+	}
+	twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR, status);
+	twl->linkstat = status;
+
+	return IRQ_HANDLED;
+}
+
+static int twl6030_set_peripheral(struct otg_transceiver *x,
+		struct usb_gadget *gadget)
+{
+	struct twl6030_usb *twl;
+
+	if (!x)
+		return -ENODEV;
+
+	twl = xceiv_to_twl(x);
+	twl->otg.gadget = gadget;
+	if (!gadget)
+		twl->otg.state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int twl6030_enable_irq(struct otg_transceiver *x)
+{
+	struct twl6030_usb *twl = xceiv_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);
+	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
+
+	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
+				REG_INT_MSK_LINE_C);
+	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
+				REG_INT_MSK_STS_C);
+	twl6030_usb_irq(twl->irq2, twl);
+	twl6030_usbotg_irq(twl->irq1, twl);
+
+	return 0;
+}
+
+static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled)
+{
+	struct twl6030_usb *twl = xceiv_to_twl(x);
+
+	/*
+	 * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1
+	 * register. This enables boost mode.
+	 */
+	if (enabled)
+		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
+						CHARGERUSB_CTRL1);
+	 else
+		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
+						CHARGERUSB_CTRL1);
+	return 0;
+}
+
+static int twl6030_set_host(struct otg_transceiver *x, struct usb_bus *host)
+{
+	struct twl6030_usb *twl;
+
+	if (!x)
+		return -ENODEV;
+
+	twl = xceiv_to_twl(x);
+	twl->otg.host = host;
+	if (!host)
+		twl->otg.state = OTG_STATE_UNDEFINED;
+	return 0;
+}
+
+static int __devinit twl6030_usb_probe(struct platform_device *pdev)
+{
+	struct twl6030_usb	*twl;
+	int			status, err;
+	struct twl4030_usb_data *pdata;
+	struct device *dev = &pdev->dev;
+	pdata = dev->platform_data;
+
+	twl = kzalloc(sizeof *twl, GFP_KERNEL);
+	if (!twl)
+		return -ENOMEM;
+
+	twl->dev		= &pdev->dev;
+	twl->irq1		= platform_get_irq(pdev, 0);
+	twl->irq2		= platform_get_irq(pdev, 1);
+	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;
+
+	/* init spinlock for workqueue */
+	spin_lock_init(&twl->lock);
+
+	err = twl6030_usb_ldo_init(twl);
+	if (err) {
+		dev_err(&pdev->dev, "ldo init failed\n");
+		kfree(twl);
+		return err;
+	}
+	otg_set_transceiver(&twl->otg);
+
+	platform_set_drvdata(pdev, twl);
+	if (device_create_file(&pdev->dev, &dev_attr_vbus))
+		dev_warn(&pdev->dev, "could not create sysfs file\n");
+
+	BLOCKING_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
+
+	twl->irq_enabled = true;
+	status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			"twl6030_usb", twl);
+	if (status < 0) {
+		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
+			twl->irq1, status);
+		device_remove_file(twl->dev, &dev_attr_vbus);
+		kfree(twl);
+		return status;
+	}
+
+	status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq,
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			"twl6030_usb", twl);
+	if (status < 0) {
+		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
+			twl->irq2, status);
+		free_irq(twl->irq1, twl);
+		device_remove_file(twl->dev, &dev_attr_vbus);
+		kfree(twl);
+		return status;
+	}
+
+	pdata->phy_init(dev);
+	twl6030_enable_irq(&twl->otg);
+	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
+
+	return 0;
+}
+
+static int __exit twl6030_usb_remove(struct platform_device *pdev)
+{
+	struct twl6030_usb *twl = platform_get_drvdata(pdev);
+
+	struct twl4030_usb_data *pdata;
+	struct device *dev = &pdev->dev;
+	pdata = dev->platform_data;
+
+	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
+		REG_INT_MSK_LINE_C);
+	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
+			REG_INT_MSK_STS_C);
+	free_irq(twl->irq1, twl);
+	free_irq(twl->irq2, twl);
+	regulator_put(twl->usb3v3);
+	pdata->phy_exit(twl->dev);
+	device_remove_file(twl->dev, &dev_attr_vbus);
+	kfree(twl);
+
+	return 0;
+}
+
+static struct platform_driver twl6030_usb_driver = {
+	.probe		= twl6030_usb_probe,
+	.remove		= __exit_p(twl6030_usb_remove),
+	.driver		= {
+		.name	= "twl6030_usb",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init twl6030_usb_init(void)
+{
+	return platform_driver_register(&twl6030_usb_driver);
+}
+subsys_initcall(twl6030_usb_init);
+
+static void __exit twl6030_usb_exit(void)
+{
+	platform_driver_unregister(&twl6030_usb_driver);
+}
+module_exit(twl6030_usb_exit);
+
+MODULE_ALIAS("platform:twl6030_usb");
+MODULE_AUTHOR("Hema HK <hemahk@ti.com>");
+MODULE_DESCRIPTION("TWL6030 USB transceiver driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index c760991b354a..61b9609e55f2 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -593,6 +593,13 @@ enum twl4030_usb_mode {
 
 struct twl4030_usb_data {
 	enum twl4030_usb_mode	usb_mode;
+
+	int		(*phy_init)(struct device *dev);
+	int		(*phy_exit)(struct device *dev);
+	/* Power on/off the PHY */
+	int		(*phy_power)(struct device *dev, int iD, int on);
+	/* enable/disable  phy clocks */
+	int		(*phy_set_clock)(struct device *dev, int on);
 };
 
 struct twl4030_ins {
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
index ee2dd1d506ed..0b0e383035e5 100644
--- a/include/linux/usb/musb.h
+++ b/include/linux/usb/musb.h
@@ -3,7 +3,7 @@
  * Inventra (Multidrop) Highspeed Dual-Role Controllers:  (M)HDRC.
  *
  * Board initialization should put one of these into dev->platform_data,
- * probably on some platform_device named "musb_hdrc".  It encapsulates
+ * probably on some platform_device named "musb-hdrc".  It encapsulates
  * key configuration differences between boards.
  */
 
@@ -118,14 +118,14 @@ struct musb_hdrc_platform_data {
 	/* Power the device on or off */
 	int		(*set_power)(int state);
 
-	/* Turn device clock on or off */
-	int		(*set_clock)(struct clk *clock, int is_on);
-
 	/* MUSB configuration-specific details */
 	struct musb_hdrc_config	*config;
 
 	/* Architecture specific board data	*/
 	void		*board_data;
+
+	/* Platform specific struct musb_ops pointer */
+	const void	*platform_ops;
 };