Merge commit 'xceiv-for-v3.7' into for-3.7/cleanup2
diff --git a/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt
new file mode 100644
index 0000000..36b9aed
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt
@@ -0,0 +1,40 @@
+USB COMPARATOR OF TWL CHIPS
+
+TWL6030 USB COMPARATOR
+ - compatible : Should be "ti,twl6030-usb"
+ - interrupts : Two interrupt numbers to the cpu should be specified. First
+   interrupt number is the otg interrupt number that raises ID interrupts when
+   the controller has to act as host and the second interrupt number is the
+   usb interrupt number that raises VBUS interrupts when the controller has to
+   act as device
+ - usb-supply : phandle to the regulator device tree node. It should be vusb
+   if it is twl6030 or ldousb if it is twl6025 subclass.
+
+twl6030-usb {
+	compatible = "ti,twl6030-usb";
+	interrupts = < 4 10 >;
+};
+
+Board specific device node entry
+&twl6030-usb {
+	usb-supply = <&vusb>;
+};
+
+TWL4030 USB PHY AND COMPARATOR
+ - compatible : Should be "ti,twl4030-usb"
+ - interrupts : The interrupt numbers to the cpu should be specified. First
+   interrupt number is the otg interrupt number that raises ID interrupts
+   and VBUS interrupts. The second interrupt number is optional.
+ - <supply-name>-supply : phandle to the regulator device tree node.
+   <supply-name> should be vusb1v5, vusb1v8 and vusb3v1
+ - usb_mode : The mode used by the phy to connect to the controller. "1"
+   specifies "ULPI" mode and "2" specifies "CEA2011_3PIN" mode.
+
+twl4030-usb {
+	compatible = "ti,twl4030-usb";
+	interrupts = < 10 4 >;
+	usb1v5-supply = <&vusb1v5>;
+	usb1v8-supply = <&vusb1v8>;
+	usb3v1-supply = <&vusb3v1>;
+	usb_mode = <1>;
+};
diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
new file mode 100644
index 0000000..80d4148
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
@@ -0,0 +1,17 @@
+USB PHY
+
+OMAP USB2 PHY
+
+Required properties:
+ - compatible: Should be "ti,omap-usb2"
+ - reg : Address and length of the register set for the device. Also
+add the address of control module dev conf register until a driver for
+control module is added
+
+This is usually a subnode of ocp2scp to which it is connected.
+
+usb2phy@4a0ad080 {
+	compatible = "ti,omap-usb2";
+	reg = <0x4a0ad080 0x58>,
+	      <0x4a002300 0x4>;
+};
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 0d362e9..3d2a988 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -32,6 +32,7 @@
 #include <linux/spi/ads7846.h>
 #include <linux/i2c/twl.h>
 #include <linux/usb/otg.h>
+#include <linux/usb/nop-usb-xceiv.h>
 #include <linux/smsc911x.h>
 
 #include <linux/wl12xx.h>
diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c
index d52651a..874aecc 100644
--- a/arch/arm/mach-omap2/omap_phy_internal.c
+++ b/arch/arm/mach-omap2/omap_phy_internal.c
@@ -31,144 +31,6 @@
 #include <plat/usb.h>
 #include "control.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;
-static int usbotghs_control;
-
-int omap4430_phy_init(struct device *dev)
-{
-	ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
-	if (!ctrl_base) {
-		pr_err("control module ioremap failed\n");
-		return -ENOMEM;
-	}
-	/* Power down the phy */
-	__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-
-	if (!dev) {
-		iounmap(ctrl_base);
-		return 0;
-	}
-
-	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) {
-		if (ID)
-			/* enable VBUS valid, IDDIG groung */
-			__raw_writel(AVALID | VBUSVALID, ctrl_base +
-							USBOTGHS_CONTROL);
-		else
-			/*
-			 * Enable VBUS Valid, AValid and IDDIG
-			 * high impedance
-			 */
-			__raw_writel(IDDIG | AVALID | VBUSVALID,
-						ctrl_base + USBOTGHS_CONTROL);
-	} else {
-		/* Enable session END and IDIG to high impedance. */
-		__raw_writel(SESSEND | IDDIG, ctrl_base +
-					USBOTGHS_CONTROL);
-	}
-	return 0;
-}
-
-int omap4430_phy_suspend(struct device *dev, int suspend)
-{
-	if (suspend) {
-		/* Disable the clocks */
-		omap4430_phy_set_clk(dev, 0);
-		/* Power down the phy */
-		__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-
-		/* save the context */
-		usbotghs_control = __raw_readl(ctrl_base + USBOTGHS_CONTROL);
-	} else {
-		/* Enable the internel phy clcoks */
-		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);
-		}
-
-		/* restore the context */
-		__raw_writel(usbotghs_control, ctrl_base + USBOTGHS_CONTROL);
-	}
-
-	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;
-}
-
 void am35x_musb_reset(void)
 {
 	u32	regval;
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index db5ff66..329b726 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -251,11 +251,6 @@
 
 #if defined(CONFIG_ARCH_OMAP4)
 static struct twl4030_usb_data omap4_usb_pdata = {
-	.phy_init	= omap4430_phy_init,
-	.phy_exit	= omap4430_phy_exit,
-	.phy_power	= omap4430_phy_power,
-	.phy_set_clock	= omap4430_phy_set_clk,
-	.phy_suspend	= omap4430_phy_suspend,
 };
 
 static struct regulator_init_data omap4_vdac_idata = {
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index c4a5768..e9b4b23 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -117,7 +117,4 @@
 	dev->dma_mask = &musb_dmamask;
 	dev->coherent_dma_mask = musb_dmamask;
 	put_device(dev);
-
-	if (cpu_is_omap44xx())
-		omap4430_phy_init(dev);
 }
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index b129f37..ed41905 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -23,7 +23,6 @@
 obj-$(CONFIG_TEGRA_SYSTEM_DMA)		+= dma.o
 obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
 obj-$(CONFIG_TEGRA_PCI)			+= pcie.o
-obj-$(CONFIG_USB_SUPPORT)		+= usb_phy.o
 
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= board-dt-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= board-dt-tegra30.o
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index c70e65f..d8ab762 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -27,7 +27,7 @@
 #include <mach/irqs.h>
 #include <mach/iomap.h>
 #include <mach/dma.h>
-#include <mach/usb_phy.h>
+#include <linux/usb/tegra_usb_phy.h>
 
 #include "gpio-names.h"
 #include "devices.h"
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
index 4f50527..906a61f 100644
--- a/arch/arm/mach-tegra/devices.h
+++ b/arch/arm/mach-tegra/devices.h
@@ -22,7 +22,7 @@
 #include <linux/platform_device.h>
 #include <linux/platform_data/tegra_usb.h>
 
-#include <mach/usb_phy.h>
+#include <linux/usb/tegra_usb_phy.h>
 
 extern struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config;
 
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index c34452a..79a24fa 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -50,6 +50,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/of.h>
 
+#include <linux/usb/otg.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 
@@ -136,6 +137,8 @@
 	reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
 	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 
+	usb_phy_init(dwc->usb2_phy);
+	usb_phy_init(dwc->usb3_phy);
 	mdelay(100);
 
 	/* Clear USB3 PHY reset */
@@ -465,6 +468,18 @@
 		return -ENOMEM;
 	}
 
+	dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+	if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
+		dev_err(dev, "no usb2 phy configured\n");
+		return -EPROBE_DEFER;
+	}
+
+	dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
+	if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
+		dev_err(dev, "no usb3 phy configured\n");
+		return -EPROBE_DEFER;
+	}
+
 	spin_lock_init(&dwc->lock);
 	platform_set_drvdata(pdev, dwc);
 
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 151eca8..dbc5713 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -624,6 +624,8 @@
  * @maximum_speed: maximum speed requested (mainly for testing purposes)
  * @revision: revision register contents
  * @mode: mode of operation
+ * @usb2_phy: pointer to USB2 PHY
+ * @usb3_phy: pointer to USB3 PHY
  * @is_selfpowered: true when we are selfpowered
  * @three_stage_setup: set if we perform a three phase setup
  * @ep0_bounced: true when we used bounce buffer
@@ -667,6 +669,9 @@
 	struct usb_gadget	gadget;
 	struct usb_gadget_driver *gadget_driver;
 
+	struct usb_phy		*usb2_phy;
+	struct usb_phy		*usb3_phy;
+
 	void __iomem		*regs;
 	size_t			regs_size;
 
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index b8f0038..ca65978 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -19,16 +19,74 @@
 #include <linux/platform_data/dwc3-exynos.h>
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/nop-usb-xceiv.h>
 
 #include "core.h"
 
 struct dwc3_exynos {
 	struct platform_device	*dwc3;
+	struct platform_device	*usb2_phy;
+	struct platform_device	*usb3_phy;
 	struct device		*dev;
 
 	struct clk		*clk;
 };
 
+static int __devinit dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
+{
+	struct nop_usb_xceiv_platform_data pdata;
+	struct platform_device	*pdev;
+	int			ret;
+
+	memset(&pdata, 0x00, sizeof(pdata));
+
+	pdev = platform_device_alloc("nop_usb_xceiv", 0);
+	if (!pdev)
+		return -ENOMEM;
+
+	exynos->usb2_phy = pdev;
+	pdata.type = USB_PHY_TYPE_USB2;
+
+	ret = platform_device_add_data(exynos->usb2_phy, &pdata, sizeof(pdata));
+	if (ret)
+		goto err1;
+
+	pdev = platform_device_alloc("nop_usb_xceiv", 1);
+	if (!pdev) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	exynos->usb3_phy = pdev;
+	pdata.type = USB_PHY_TYPE_USB3;
+
+	ret = platform_device_add_data(exynos->usb3_phy, &pdata, sizeof(pdata));
+	if (ret)
+		goto err2;
+
+	ret = platform_device_add(exynos->usb2_phy);
+	if (ret)
+		goto err2;
+
+	ret = platform_device_add(exynos->usb3_phy);
+	if (ret)
+		goto err3;
+
+	return 0;
+
+err3:
+	platform_device_del(exynos->usb2_phy);
+
+err2:
+	platform_device_put(exynos->usb3_phy);
+
+err1:
+	platform_device_put(exynos->usb2_phy);
+
+	return ret;
+}
+
 static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
 {
 	struct dwc3_exynos_data	*pdata = pdev->dev.platform_data;
@@ -51,6 +109,12 @@
 	if (devid < 0)
 		goto err1;
 
+	ret = dwc3_exynos_register_phys(exynos);
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't register PHYs\n");
+		goto err1;
+	}
+
 	dwc3 = platform_device_alloc("dwc3", devid);
 	if (!dwc3) {
 		dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
@@ -120,6 +184,8 @@
 	struct dwc3_exynos_data *pdata = pdev->dev.platform_data;
 
 	platform_device_unregister(exynos->dwc3);
+	platform_device_unregister(exynos->usb2_phy);
+	platform_device_unregister(exynos->usb3_phy);
 
 	dwc3_put_device_id(exynos->dwc3->id);
 
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 479dc04..ee57a10 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -48,6 +48,9 @@
 #include <linux/io.h>
 #include <linux/of.h>
 
+#include <linux/usb/otg.h>
+#include <linux/usb/nop-usb-xceiv.h>
+
 #include "core.h"
 
 /*
@@ -131,6 +134,8 @@
 	spinlock_t		lock;
 
 	struct platform_device	*dwc3;
+	struct platform_device	*usb2_phy;
+	struct platform_device	*usb3_phy;
 	struct device		*dev;
 
 	int			irq;
@@ -152,6 +157,59 @@
 	writel(value, base + offset);
 }
 
+static int __devinit dwc3_omap_register_phys(struct dwc3_omap *omap)
+{
+	struct nop_usb_xceiv_platform_data pdata;
+	struct platform_device	*pdev;
+	int			ret;
+
+	memset(&pdata, 0x00, sizeof(pdata));
+
+	pdev = platform_device_alloc("nop_usb_xceiv", 0);
+	if (!pdev)
+		return -ENOMEM;
+
+	omap->usb2_phy = pdev;
+	pdata.type = USB_PHY_TYPE_USB2;
+
+	ret = platform_device_add_data(omap->usb2_phy, &pdata, sizeof(pdata));
+	if (ret)
+		goto err1;
+
+	pdev = platform_device_alloc("nop_usb_xceiv", 1);
+	if (!pdev) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	omap->usb3_phy = pdev;
+	pdata.type = USB_PHY_TYPE_USB3;
+
+	ret = platform_device_add_data(omap->usb3_phy, &pdata, sizeof(pdata));
+	if (ret)
+		goto err2;
+
+	ret = platform_device_add(omap->usb2_phy);
+	if (ret)
+		goto err2;
+
+	ret = platform_device_add(omap->usb3_phy);
+	if (ret)
+		goto err3;
+
+	return 0;
+
+err3:
+	platform_device_del(omap->usb2_phy);
+
+err2:
+	platform_device_put(omap->usb3_phy);
+
+err1:
+	platform_device_put(omap->usb2_phy);
+
+	return ret;
+}
 
 static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
 {
@@ -251,6 +309,12 @@
 		return -ENOMEM;
 	}
 
+	ret = dwc3_omap_register_phys(omap);
+	if (ret) {
+		dev_err(dev, "couldn't register PHYs\n");
+		return ret;
+	}
+
 	devid = dwc3_get_device_id();
 	if (devid < 0)
 		return -ENODEV;
@@ -371,6 +435,8 @@
 	struct dwc3_omap	*omap = platform_get_drvdata(pdev);
 
 	platform_device_unregister(omap->dwc3);
+	platform_device_unregister(omap->usb2_phy);
+	platform_device_unregister(omap->usb3_phy);
 
 	dwc3_put_device_id(omap->dwc3->id);
 
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index a9ca9ad..94f550e 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -42,6 +42,9 @@
 #include <linux/pci.h>
 #include <linux/platform_device.h>
 
+#include <linux/usb/otg.h>
+#include <linux/usb/nop-usb-xceiv.h>
+
 #include "core.h"
 
 /* FIXME define these in <linux/pci_ids.h> */
@@ -51,8 +54,64 @@
 struct dwc3_pci {
 	struct device		*dev;
 	struct platform_device	*dwc3;
+	struct platform_device	*usb2_phy;
+	struct platform_device	*usb3_phy;
 };
 
+static int __devinit dwc3_pci_register_phys(struct dwc3_pci *glue)
+{
+	struct nop_usb_xceiv_platform_data pdata;
+	struct platform_device	*pdev;
+	int			ret;
+
+	memset(&pdata, 0x00, sizeof(pdata));
+
+	pdev = platform_device_alloc("nop_usb_xceiv", 0);
+	if (!pdev)
+		return -ENOMEM;
+
+	glue->usb2_phy = pdev;
+	pdata.type = USB_PHY_TYPE_USB2;
+
+	ret = platform_device_add_data(glue->usb2_phy, &pdata, sizeof(pdata));
+	if (ret)
+		goto err1;
+
+	pdev = platform_device_alloc("nop_usb_xceiv", 1);
+	if (!pdev) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	glue->usb3_phy = pdev;
+	pdata.type = USB_PHY_TYPE_USB3;
+
+	ret = platform_device_add_data(glue->usb3_phy, &pdata, sizeof(pdata));
+	if (ret)
+		goto err2;
+
+	ret = platform_device_add(glue->usb2_phy);
+	if (ret)
+		goto err2;
+
+	ret = platform_device_add(glue->usb3_phy);
+	if (ret)
+		goto err3;
+
+	return 0;
+
+err3:
+	platform_device_del(glue->usb2_phy);
+
+err2:
+	platform_device_put(glue->usb3_phy);
+
+err1:
+	platform_device_put(glue->usb2_phy);
+
+	return ret;
+}
+
 static int __devinit dwc3_pci_probe(struct pci_dev *pci,
 		const struct pci_device_id *id)
 {
@@ -80,6 +139,12 @@
 	pci_set_power_state(pci, PCI_D0);
 	pci_set_master(pci);
 
+	ret = dwc3_pci_register_phys(glue);
+	if (ret) {
+		dev_err(dev, "couldn't register PHYs\n");
+		return ret;
+	}
+
 	devid = dwc3_get_device_id();
 	if (devid < 0) {
 		ret = -ENOMEM;
@@ -144,6 +209,8 @@
 {
 	struct dwc3_pci	*glue = pci_get_drvdata(pci);
 
+	platform_device_unregister(glue->usb2_phy);
+	platform_device_unregister(glue->usb3_phy);
 	dwc3_put_device_id(glue->dwc3->id);
 	platform_device_unregister(glue->dwc3);
 	pci_set_drvdata(pci, NULL);
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 26dedb3..c0d4732 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -27,7 +27,7 @@
 #include <linux/of_gpio.h>
 #include <linux/pm_runtime.h>
 
-#include <mach/usb_phy.h>
+#include <linux/usb/tegra_usb_phy.h>
 #include <mach/iomap.h>
 
 #define TEGRA_USB_DMA_ALIGN 32
@@ -49,7 +49,7 @@
 
 	clk_prepare_enable(tegra->emc_clk);
 	clk_prepare_enable(tegra->clk);
-	tegra_usb_phy_power_on(tegra->phy);
+	usb_phy_set_suspend(&tegra->phy->u_phy, 0);
 	tegra->host_resumed = 1;
 }
 
@@ -58,7 +58,7 @@
 	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
 
 	tegra->host_resumed = 0;
-	tegra_usb_phy_power_off(tegra->phy);
+	usb_phy_set_suspend(&tegra->phy->u_phy, 1);
 	clk_disable_unprepare(tegra->clk);
 	clk_disable_unprepare(tegra->emc_clk);
 }
@@ -715,7 +715,9 @@
 		goto fail_phy;
 	}
 
-	err = tegra_usb_phy_power_on(tegra->phy);
+	usb_phy_init(&tegra->phy->u_phy);
+
+	err = usb_phy_set_suspend(&tegra->phy->u_phy, 0);
 	if (err) {
 		dev_err(&pdev->dev, "Failed to power on the phy\n");
 		goto fail;
@@ -762,7 +764,7 @@
 		usb_put_phy(tegra->transceiver);
 	}
 #endif
-	tegra_usb_phy_close(tegra->phy);
+	usb_phy_shutdown(&tegra->phy->u_phy);
 fail_phy:
 	iounmap(hcd->regs);
 fail_io:
@@ -800,7 +802,7 @@
 
 	usb_remove_hcd(hcd);
 
-	tegra_usb_phy_close(tegra->phy);
+	usb_phy_shutdown(&tegra->phy->u_phy);
 	iounmap(hcd->regs);
 
 	usb_put_hcd(hcd);
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index 7a95ab8..5d64c5b 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -33,6 +33,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/usb/nop-usb-xceiv.h>
 
 #include <plat/usb.h>
 
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index 428e6aa..b562623 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/prefetch.h>
+#include <linux/usb/nop-usb-xceiv.h>
 
 #include <asm/cacheflush.h>
 
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 0f9fcec..16798c9 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -33,6 +33,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/usb/nop-usb-xceiv.h>
 
 #include <mach/da8xx.h>
 #include <mach/usb.h>
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 472c8b4..863a9b6 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -33,6 +33,7 @@
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/usb/nop-usb-xceiv.h>
 
 #include <mach/cputype.h>
 #include <mach/hardware.h>
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 494772f..c20b877 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -36,6 +36,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/module.h>
+#include <linux/usb/nop-usb-xceiv.h>
 
 #include <linux/of.h>
 #include <linux/of_device.h>
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 1a1bd9c..00f21df 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -24,6 +24,7 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/usb/nop-usb-xceiv.h>
 
 #include "musb_core.h"
 
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 13fd1ddf..d8c8a42 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -68,7 +68,7 @@
 
 config TWL6030_USB
 	tristate "TWL6030 USB Transceiver Driver"
-	depends on TWL4030_CORE
+	depends on TWL4030_CORE && OMAP_USB2
 	select USB_OTG_UTILS
 	help
 	  Enable this to support the USB OTG transceiver on TWL6030
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c
index 23c798c..c19d1d7 100644
--- a/drivers/usb/otg/fsl_otg.c
+++ b/drivers/usb/otg/fsl_otg.c
@@ -544,9 +544,13 @@
  */
 static int fsl_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
 {
-	struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy);
+	struct fsl_otg *otg_dev;
 
-	if (!otg || otg_dev != fsl_otg_dev)
+	if (!otg)
+		return -ENODEV;
+
+	otg_dev = container_of(otg->phy, struct fsl_otg, phy);
+	if (otg_dev != fsl_otg_dev)
 		return -ENODEV;
 
 	otg->host = host;
@@ -590,12 +594,15 @@
 static int fsl_otg_set_peripheral(struct usb_otg *otg,
 					struct usb_gadget *gadget)
 {
-	struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy);
+	struct fsl_otg *otg_dev;
 
+	if (!otg)
+		return -ENODEV;
+
+	otg_dev = container_of(otg->phy, struct fsl_otg, phy);
 	VDBG("otg_dev 0x%x\n", (int)otg_dev);
 	VDBG("fsl_otg_dev 0x%x\n", (int)fsl_otg_dev);
-
-	if (!otg || otg_dev != fsl_otg_dev)
+	if (otg_dev != fsl_otg_dev)
 		return -ENODEV;
 
 	if (!gadget) {
@@ -660,10 +667,13 @@
 /* B-device start SRP */
 static int fsl_otg_start_srp(struct usb_otg *otg)
 {
-	struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy);
+	struct fsl_otg *otg_dev;
 
-	if (!otg || otg_dev != fsl_otg_dev
-	    || otg->phy->state != OTG_STATE_B_IDLE)
+	if (!otg || otg->phy->state != OTG_STATE_B_IDLE)
+		return -ENODEV;
+
+	otg_dev = container_of(otg->phy, struct fsl_otg, phy);
+	if (otg_dev != fsl_otg_dev)
 		return -ENODEV;
 
 	otg_dev->fsm.b_bus_req = 1;
@@ -675,9 +685,13 @@
 /* A_host suspend will call this function to start hnp */
 static int fsl_otg_start_hnp(struct usb_otg *otg)
 {
-	struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy);
+	struct fsl_otg *otg_dev;
 
-	if (!otg || otg_dev != fsl_otg_dev)
+	if (!otg)
+		return -ENODEV;
+
+	otg_dev = container_of(otg->phy, struct fsl_otg, phy);
+	if (otg_dev != fsl_otg_dev)
 		return -ENODEV;
 
 	DBG("start_hnp...n");
diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c
index c1a67cb..88db976 100644
--- a/drivers/usb/otg/mxs-phy.c
+++ b/drivers/usb/otg/mxs-phy.c
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/workqueue.h>
 
 #define DRIVER_NAME "mxs_phy"
 
@@ -34,9 +35,16 @@
 #define BM_USBPHY_CTRL_ENUTMILEVEL2		BIT(14)
 #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT	BIT(1)
 
+/*
+ * Amount of delay in miliseconds to safely enable ENHOSTDISCONDETECT bit
+ * so that connection and reset processing can be completed for the root hub.
+ */
+#define MXY_PHY_ENHOSTDISCONDETECT_DELAY	250
+
 struct mxs_phy {
 	struct usb_phy phy;
 	struct clk *clk;
+	struct delayed_work enhostdiscondetect_work;
 };
 
 #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
@@ -62,6 +70,7 @@
 
 	clk_prepare_enable(mxs_phy->clk);
 	mxs_phy_hw_init(mxs_phy);
+	INIT_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work, NULL);
 
 	return 0;
 }
@@ -76,13 +85,34 @@
 	clk_disable_unprepare(mxs_phy->clk);
 }
 
+static void mxs_phy_enhostdiscondetect_delay(struct work_struct *ws)
+{
+	struct mxs_phy *mxs_phy = container_of(ws, struct mxs_phy,
+						enhostdiscondetect_work.work);
+
+	/* Enable HOSTDISCONDETECT after delay. */
+	dev_dbg(mxs_phy->phy.dev, "Setting ENHOSTDISCONDETECT\n");
+	writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+				mxs_phy->phy.io_priv + HW_USBPHY_CTRL_SET);
+}
+
 static int mxs_phy_on_connect(struct usb_phy *phy, int port)
 {
+	struct mxs_phy *mxs_phy = to_mxs_phy(phy);
+
 	dev_dbg(phy->dev, "Connect on port %d\n", port);
 
-	mxs_phy_hw_init(to_mxs_phy(phy));
-	writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
-			phy->io_priv + HW_USBPHY_CTRL_SET);
+	mxs_phy_hw_init(mxs_phy);
+
+	/*
+	 * Delay enabling ENHOSTDISCONDETECT so that connection and
+	 * reset processing can be completed for the root hub.
+	 */
+	dev_dbg(phy->dev, "Delaying setting ENHOSTDISCONDETECT\n");
+	PREPARE_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work,
+			mxs_phy_enhostdiscondetect_delay);
+	schedule_delayed_work(&mxs_phy->enhostdiscondetect_work,
+			msecs_to_jiffies(MXY_PHY_ENHOSTDISCONDETECT_DELAY));
 
 	return 0;
 }
@@ -91,6 +121,8 @@
 {
 	dev_dbg(phy->dev, "Disconnect on port %d\n", port);
 
+	/* No need to delay before clearing ENHOSTDISCONDETECT. */
+	dev_dbg(phy->dev, "Clearing ENHOSTDISCONDETECT\n");
 	writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
 			phy->io_priv + HW_USBPHY_CTRL_CLR);
 
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
index 803f958..e52e35e 100644
--- a/drivers/usb/otg/nop-usb-xceiv.c
+++ b/drivers/usb/otg/nop-usb-xceiv.c
@@ -30,6 +30,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/usb/otg.h>
+#include <linux/usb/nop-usb-xceiv.h>
 #include <linux/slab.h>
 
 struct nop_usb_xceiv {
@@ -94,7 +95,9 @@
 
 static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev)
 {
+	struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;
 	struct nop_usb_xceiv	*nop;
+	enum usb_phy_type	type = USB_PHY_TYPE_USB2;
 	int err;
 
 	nop = kzalloc(sizeof *nop, GFP_KERNEL);
@@ -107,6 +110,9 @@
 		return -ENOMEM;
 	}
 
+	if (pdata)
+		type = pdata->type;
+
 	nop->dev		= &pdev->dev;
 	nop->phy.dev		= nop->dev;
 	nop->phy.label		= "nop-xceiv";
@@ -117,7 +123,7 @@
 	nop->phy.otg->set_host		= nop_set_host;
 	nop->phy.otg->set_peripheral	= nop_set_peripheral;
 
-	err = usb_add_phy(&nop->phy, USB_PHY_TYPE_USB2);
+	err = usb_add_phy(&nop->phy, type);
 	if (err) {
 		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
 			err);
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
index 1bf60a2..a30c041 100644
--- a/drivers/usb/otg/otg.c
+++ b/drivers/usb/otg/otg.c
@@ -159,7 +159,7 @@
 	unsigned long	flags;
 	struct usb_phy	*phy;
 
-	if (x && x->type != USB_PHY_TYPE_UNDEFINED) {
+	if (x->type != USB_PHY_TYPE_UNDEFINED) {
 		dev_err(x->dev, "not accepting initialized PHY %s\n", x->label);
 		return -EINVAL;
 	}
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index 523cad5..f0d2e75 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -585,23 +585,28 @@
 	struct twl4030_usb	*twl;
 	int			status, err;
 	struct usb_otg		*otg;
-
-	if (!pdata) {
-		dev_dbg(&pdev->dev, "platform_data not available\n");
-		return -EINVAL;
-	}
+	struct device_node	*np = pdev->dev.of_node;
 
 	twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL);
 	if (!twl)
 		return -ENOMEM;
 
+	if (np)
+		of_property_read_u32(np, "usb_mode",
+				(enum twl4030_usb_mode *)&twl->usb_mode);
+	else if (pdata)
+		twl->usb_mode = pdata->usb_mode;
+	else {
+		dev_err(&pdev->dev, "twl4030 initialized without pdata\n");
+		return -EINVAL;
+	}
+
 	otg = devm_kzalloc(&pdev->dev, sizeof *otg, GFP_KERNEL);
 	if (!otg)
 		return -ENOMEM;
 
 	twl->dev		= &pdev->dev;
 	twl->irq		= platform_get_irq(pdev, 0);
-	twl->usb_mode		= pdata->usb_mode;
 	twl->vbus_supplied	= false;
 	twl->asleep		= 1;
 	twl->linkstat		= OMAP_MUSB_UNKNOWN;
@@ -690,12 +695,21 @@
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id twl4030_usb_id_table[] = {
+	{ .compatible = "ti,twl4030-usb" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, twl4030_usb_id_table);
+#endif
+
 static struct platform_driver twl4030_usb_driver = {
 	.probe		= twl4030_usb_probe,
 	.remove		= __exit_p(twl4030_usb_remove),
 	.driver		= {
 		.name	= "twl4030_usb",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(twl4030_usb_id_table),
 	},
 };
 
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index 6907d8d..fcadef7 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -25,8 +25,9 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/usb/otg.h>
 #include <linux/usb/musb-omap.h>
+#include <linux/usb/phy_companion.h>
+#include <linux/usb/omap_usb.h>
 #include <linux/i2c/twl.h>
 #include <linux/regulator/consumer.h>
 #include <linux/err.h>
@@ -87,7 +88,7 @@
 #define	VBUS_DET			BIT(2)
 
 struct twl6030_usb {
-	struct usb_phy		phy;
+	struct phy_companion	comparator;
 	struct device		*dev;
 
 	/* for vbus reporting with irqs disabled */
@@ -104,10 +105,10 @@
 	u8			asleep;
 	bool			irq_enabled;
 	bool			vbus_enable;
-	unsigned long		features;
+	const char		*regulator;
 };
 
-#define phy_to_twl(x)		container_of((x), struct twl6030_usb, phy)
+#define	comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator)
 
 /*-------------------------------------------------------------------------*/
 
@@ -137,50 +138,9 @@
 	return ret;
 }
 
-static int twl6030_phy_init(struct usb_phy *x)
+static int twl6030_start_srp(struct phy_companion *comparator)
 {
-	struct twl6030_usb *twl;
-	struct device *dev;
-	struct twl4030_usb_data *pdata;
-
-	twl = phy_to_twl(x);
-	dev  = twl->dev;
-	pdata = dev->platform_data;
-
-	if (twl->linkstat == OMAP_MUSB_ID_GROUND)
-		pdata->phy_power(twl->dev, 1, 1);
-	else
-		pdata->phy_power(twl->dev, 0, 1);
-
-	return 0;
-}
-
-static void twl6030_phy_shutdown(struct usb_phy *x)
-{
-	struct twl6030_usb *twl;
-	struct device *dev;
-	struct twl4030_usb_data *pdata;
-
-	twl = phy_to_twl(x);
-	dev  = twl->dev;
-	pdata = dev->platform_data;
-	pdata->phy_power(twl->dev, 0, 0);
-}
-
-static int twl6030_phy_suspend(struct usb_phy *x, int suspend)
-{
-	struct twl6030_usb *twl = phy_to_twl(x);
-	struct device *dev = twl->dev;
-	struct twl4030_usb_data *pdata = dev->platform_data;
-
-	pdata->phy_suspend(dev, suspend);
-
-	return 0;
-}
-
-static int twl6030_start_srp(struct usb_otg *otg)
-{
-	struct twl6030_usb *twl = phy_to_twl(otg->phy);
+	struct twl6030_usb *twl = comparator_to_twl(comparator);
 
 	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
 	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);
@@ -193,13 +153,6 @@
 
 static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
 {
-	char *regulator_name;
-
-	if (twl->features & TWL6025_SUBCLASS)
-		regulator_name = "ldousb";
-	else
-		regulator_name = "vusb";
-
 	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
 	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);
 
@@ -209,7 +162,7 @@
 	/* Program MISC2 register and set bit VUSB_IN_VBAT */
 	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);
 
-	twl->usb3v3 = regulator_get(twl->dev, regulator_name);
+	twl->usb3v3 = regulator_get(twl->dev, twl->regulator);
 	if (IS_ERR(twl->usb3v3))
 		return -ENODEV;
 
@@ -313,23 +266,8 @@
 	return IRQ_HANDLED;
 }
 
-static int twl6030_set_peripheral(struct usb_otg *otg,
-		struct usb_gadget *gadget)
+static int twl6030_enable_irq(struct twl6030_usb *twl)
 {
-	if (!otg)
-		return -ENODEV;
-
-	otg->gadget = gadget;
-	if (!gadget)
-		otg->phy->state = OTG_STATE_UNDEFINED;
-
-	return 0;
-}
-
-static int twl6030_enable_irq(struct usb_phy *x)
-{
-	struct twl6030_usb *twl = phy_to_twl(x);
-
 	twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
 	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
 	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
@@ -362,9 +300,9 @@
 							CHARGERUSB_CTRL1);
 }
 
-static int twl6030_set_vbus(struct usb_otg *otg, bool enabled)
+static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
 {
-	struct twl6030_usb *twl = phy_to_twl(otg->phy);
+	struct twl6030_usb *twl = comparator_to_twl(comparator);
 
 	twl->vbus_enable = enabled;
 	schedule_work(&twl->set_vbus_work);
@@ -372,52 +310,44 @@
 	return 0;
 }
 
-static int twl6030_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	if (!otg)
-		return -ENODEV;
-
-	otg->host = host;
-	if (!host)
-		otg->phy->state = OTG_STATE_UNDEFINED;
-	return 0;
-}
-
 static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 {
+	u32 ret;
 	struct twl6030_usb	*twl;
 	int			status, err;
-	struct twl4030_usb_data *pdata;
-	struct usb_otg		*otg;
-	struct device *dev = &pdev->dev;
-	pdata = dev->platform_data;
+	struct device_node	*np = pdev->dev.of_node;
+	struct device		*dev = &pdev->dev;
+	struct twl4030_usb_data	*pdata = dev->platform_data;
 
 	twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL);
 	if (!twl)
 		return -ENOMEM;
 
-	otg = devm_kzalloc(dev, sizeof *otg, GFP_KERNEL);
-	if (!otg)
-		return -ENOMEM;
-
 	twl->dev		= &pdev->dev;
 	twl->irq1		= platform_get_irq(pdev, 0);
 	twl->irq2		= platform_get_irq(pdev, 1);
-	twl->features		= pdata->features;
 	twl->linkstat		= OMAP_MUSB_UNKNOWN;
 
-	twl->phy.dev		= twl->dev;
-	twl->phy.label		= "twl6030";
-	twl->phy.otg		= otg;
-	twl->phy.init		= twl6030_phy_init;
-	twl->phy.shutdown	= twl6030_phy_shutdown;
-	twl->phy.set_suspend	= twl6030_phy_suspend;
+	twl->comparator.set_vbus	= twl6030_set_vbus;
+	twl->comparator.start_srp	= twl6030_start_srp;
 
-	otg->phy		= &twl->phy;
-	otg->set_host		= twl6030_set_host;
-	otg->set_peripheral	= twl6030_set_peripheral;
-	otg->set_vbus		= twl6030_set_vbus;
-	otg->start_srp		= twl6030_start_srp;
+	ret = omap_usb2_set_comparator(&twl->comparator);
+	if (ret == -ENODEV) {
+		dev_info(&pdev->dev, "phy not ready, deferring probe");
+		return -EPROBE_DEFER;
+	}
+
+	if (np) {
+		twl->regulator = "usb";
+	} else if (pdata) {
+		if (pdata->features & TWL6025_SUBCLASS)
+			twl->regulator = "ldousb";
+		else
+			twl->regulator = "vusb";
+	} else {
+		dev_err(&pdev->dev, "twl6030 initialized without pdata\n");
+		return -EINVAL;
+	}
 
 	/* init spinlock for workqueue */
 	spin_lock_init(&twl->lock);
@@ -427,7 +357,6 @@
 		dev_err(&pdev->dev, "ldo init failed\n");
 		return err;
 	}
-	usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
 
 	platform_set_drvdata(pdev, twl);
 	if (device_create_file(&pdev->dev, &dev_attr_vbus))
@@ -458,9 +387,7 @@
 	}
 
 	twl->asleep = 0;
-	pdata->phy_init(dev);
-	twl6030_phy_suspend(&twl->phy, 0);
-	twl6030_enable_irq(&twl->phy);
+	twl6030_enable_irq(twl);
 	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
 
 	return 0;
@@ -470,10 +397,6 @@
 {
 	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,
@@ -481,19 +404,27 @@
 	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);
 	cancel_work_sync(&twl->set_vbus_work);
 
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id twl6030_usb_id_table[] = {
+	{ .compatible = "ti,twl6030-usb" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
+#endif
+
 static struct platform_driver twl6030_usb_driver = {
 	.probe		= twl6030_usb_probe,
 	.remove		= __exit_p(twl6030_usb_remove),
 	.driver		= {
 		.name	= "twl6030_usb",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(twl6030_usb_id_table),
 	},
 };
 
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index e7cf84f..63c339b 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -4,6 +4,15 @@
 comment "USB Physical Layer drivers"
 	depends on USB || USB_GADGET
 
+config OMAP_USB2
+	tristate "OMAP USB2 PHY Driver"
+	select USB_OTG_UTILS
+	help
+	  Enable this to support the transceiver that is part of SOC. This
+	  driver takes care of all the PHY functionality apart from comparator.
+	  The USB OTG controller communicates with the comparator using this
+	  driver.
+
 config USB_ISP1301
 	tristate "NXP ISP1301 USB transceiver support"
 	depends on USB || USB_GADGET
@@ -15,3 +24,11 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called isp1301.
+
+config MV_U3D_PHY
+	bool "Marvell USB 3.0 PHY controller Driver"
+	depends on USB_MV_U3D
+	select USB_OTG_UTILS
+	help
+	  Enable this to support Marvell USB 3.0 phy controller for Marvell
+	  SoC.
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index eca095b..b069f29 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -4,4 +4,7 @@
 
 ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
 
+obj-$(CONFIG_OMAP_USB2)			+= omap-usb2.o
 obj-$(CONFIG_USB_ISP1301)		+= isp1301.o
+obj-$(CONFIG_MV_U3D_PHY)		+= mv_u3d_phy.o
+obj-$(CONFIG_USB_EHCI_TEGRA)	+= tegra_usb_phy.o
diff --git a/drivers/usb/phy/isp1301.c b/drivers/usb/phy/isp1301.c
index b19f493..18dbf7e 100644
--- a/drivers/usb/phy/isp1301.c
+++ b/drivers/usb/phy/isp1301.c
@@ -15,12 +15,6 @@
 
 #define DRV_NAME		"isp1301"
 
-#define ISP1301_I2C_ADDR	0x2C
-
-static const unsigned short normal_i2c[] = {
-	ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END
-};
-
 static const struct i2c_device_id isp1301_id[] = {
 	{ "isp1301", 0 },
 	{ }
diff --git a/drivers/usb/phy/mv_u3d_phy.c b/drivers/usb/phy/mv_u3d_phy.c
new file mode 100644
index 0000000..9f1c5d3
--- /dev/null
+++ b/drivers/usb/phy/mv_u3d_phy.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/usb/otg.h>
+#include <linux/platform_data/mv_usb.h>
+
+#include "mv_u3d_phy.h"
+
+/*
+ * struct mv_u3d_phy - transceiver driver state
+ * @phy: transceiver structure
+ * @dev: The parent device supplied to the probe function
+ * @clk: usb phy clock
+ * @base: usb phy register memory base
+ */
+struct mv_u3d_phy {
+	struct usb_phy	phy;
+	struct mv_usb_platform_data *plat;
+	struct device	*dev;
+	struct clk	*clk;
+	void __iomem	*base;
+};
+
+static u32 mv_u3d_phy_read(void __iomem *base, u32 reg)
+{
+	void __iomem *addr, *data;
+
+	addr = base;
+	data = base + 0x4;
+
+	writel_relaxed(reg, addr);
+	return readl_relaxed(data);
+}
+
+static void mv_u3d_phy_set(void __iomem *base, u32 reg, u32 value)
+{
+	void __iomem *addr, *data;
+	u32 tmp;
+
+	addr = base;
+	data = base + 0x4;
+
+	writel_relaxed(reg, addr);
+	tmp = readl_relaxed(data);
+	tmp |= value;
+	writel_relaxed(tmp, data);
+}
+
+static void mv_u3d_phy_clear(void __iomem *base, u32 reg, u32 value)
+{
+	void __iomem *addr, *data;
+	u32 tmp;
+
+	addr = base;
+	data = base + 0x4;
+
+	writel_relaxed(reg, addr);
+	tmp = readl_relaxed(data);
+	tmp &= ~value;
+	writel_relaxed(tmp, data);
+}
+
+static void mv_u3d_phy_write(void __iomem *base, u32 reg, u32 value)
+{
+	void __iomem *addr, *data;
+
+	addr = base;
+	data = base + 0x4;
+
+	writel_relaxed(reg, addr);
+	writel_relaxed(value, data);
+}
+
+void mv_u3d_phy_shutdown(struct usb_phy *phy)
+{
+	struct mv_u3d_phy *mv_u3d_phy;
+	void __iomem *base;
+	u32 val;
+
+	mv_u3d_phy = container_of(phy, struct mv_u3d_phy, phy);
+	base = mv_u3d_phy->base;
+
+	/* Power down Reference Analog current, bit 15
+	 * Power down PLL, bit 14
+	 * Power down Receiver, bit 13
+	 * Power down Transmitter, bit 12
+	 * of USB3_POWER_PLL_CONTROL register
+	 */
+	val = mv_u3d_phy_read(base, USB3_POWER_PLL_CONTROL);
+	val &= ~(USB3_POWER_PLL_CONTROL_PU);
+	mv_u3d_phy_write(base, USB3_POWER_PLL_CONTROL, val);
+
+	if (mv_u3d_phy->clk)
+		clk_disable(mv_u3d_phy->clk);
+}
+
+static int mv_u3d_phy_init(struct usb_phy *phy)
+{
+	struct mv_u3d_phy *mv_u3d_phy;
+	void __iomem *base;
+	u32 val, count;
+
+	/* enable usb3 phy */
+	mv_u3d_phy = container_of(phy, struct mv_u3d_phy, phy);
+
+	if (mv_u3d_phy->clk)
+		clk_enable(mv_u3d_phy->clk);
+
+	base = mv_u3d_phy->base;
+
+	val = mv_u3d_phy_read(base, USB3_POWER_PLL_CONTROL);
+	val &= ~(USB3_POWER_PLL_CONTROL_PU_MASK);
+	val |= 0xF << USB3_POWER_PLL_CONTROL_PU_SHIFT;
+	mv_u3d_phy_write(base, USB3_POWER_PLL_CONTROL, val);
+	udelay(100);
+
+	mv_u3d_phy_write(base, USB3_RESET_CONTROL,
+			USB3_RESET_CONTROL_RESET_PIPE);
+	udelay(100);
+
+	mv_u3d_phy_write(base, USB3_RESET_CONTROL,
+			USB3_RESET_CONTROL_RESET_PIPE
+			| USB3_RESET_CONTROL_RESET_PHY);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_POWER_PLL_CONTROL);
+	val &= ~(USB3_POWER_PLL_CONTROL_REF_FREF_SEL_MASK
+		| USB3_POWER_PLL_CONTROL_PHY_MODE_MASK);
+	val |=  (USB3_PLL_25MHZ << USB3_POWER_PLL_CONTROL_REF_FREF_SEL_SHIFT)
+		| (0x5 << USB3_POWER_PLL_CONTROL_PHY_MODE_SHIFT);
+	mv_u3d_phy_write(base, USB3_POWER_PLL_CONTROL, val);
+	udelay(100);
+
+	mv_u3d_phy_clear(base, USB3_KVCO_CALI_CONTROL,
+		USB3_KVCO_CALI_CONTROL_USE_MAX_PLL_RATE_MASK);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_SQUELCH_FFE);
+	val &= ~(USB3_SQUELCH_FFE_FFE_CAP_SEL_MASK
+		| USB3_SQUELCH_FFE_FFE_RES_SEL_MASK
+		| USB3_SQUELCH_FFE_SQ_THRESH_IN_MASK);
+	val |= ((0xD << USB3_SQUELCH_FFE_FFE_CAP_SEL_SHIFT)
+		| (0x7 << USB3_SQUELCH_FFE_FFE_RES_SEL_SHIFT)
+		| (0x8 << USB3_SQUELCH_FFE_SQ_THRESH_IN_SHIFT));
+	mv_u3d_phy_write(base, USB3_SQUELCH_FFE, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_GEN1_SET0);
+	val &= ~USB3_GEN1_SET0_G1_TX_SLEW_CTRL_EN_MASK;
+	val |= 1 << USB3_GEN1_SET0_G1_TX_EMPH_EN_SHIFT;
+	mv_u3d_phy_write(base, USB3_GEN1_SET0, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_GEN2_SET0);
+	val &= ~(USB3_GEN2_SET0_G2_TX_AMP_MASK
+		| USB3_GEN2_SET0_G2_TX_EMPH_AMP_MASK
+		| USB3_GEN2_SET0_G2_TX_SLEW_CTRL_EN_MASK);
+	val |= ((0x14 << USB3_GEN2_SET0_G2_TX_AMP_SHIFT)
+		| (1 << USB3_GEN2_SET0_G2_TX_AMP_ADJ_SHIFT)
+		| (0xA << USB3_GEN2_SET0_G2_TX_EMPH_AMP_SHIFT)
+		| (1 << USB3_GEN2_SET0_G2_TX_EMPH_EN_SHIFT));
+	mv_u3d_phy_write(base, USB3_GEN2_SET0, val);
+	udelay(100);
+
+	mv_u3d_phy_read(base, USB3_TX_EMPPH);
+	val &= ~(USB3_TX_EMPPH_AMP_MASK
+		| USB3_TX_EMPPH_EN_MASK
+		| USB3_TX_EMPPH_AMP_FORCE_MASK
+		| USB3_TX_EMPPH_PAR1_MASK
+		| USB3_TX_EMPPH_PAR2_MASK);
+	val |= ((0xB << USB3_TX_EMPPH_AMP_SHIFT)
+		| (1 << USB3_TX_EMPPH_EN_SHIFT)
+		| (1 << USB3_TX_EMPPH_AMP_FORCE_SHIFT)
+		| (0x1C << USB3_TX_EMPPH_PAR1_SHIFT)
+		| (1 << USB3_TX_EMPPH_PAR2_SHIFT));
+
+	mv_u3d_phy_write(base, USB3_TX_EMPPH, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_GEN2_SET1);
+	val &= ~(USB3_GEN2_SET1_G2_RX_SELMUPI_MASK
+		| USB3_GEN2_SET1_G2_RX_SELMUPF_MASK
+		| USB3_GEN2_SET1_G2_RX_SELMUFI_MASK
+		| USB3_GEN2_SET1_G2_RX_SELMUFF_MASK);
+	val |= ((1 << USB3_GEN2_SET1_G2_RX_SELMUPI_SHIFT)
+		| (1 << USB3_GEN2_SET1_G2_RX_SELMUPF_SHIFT)
+		| (1 << USB3_GEN2_SET1_G2_RX_SELMUFI_SHIFT)
+		| (1 << USB3_GEN2_SET1_G2_RX_SELMUFF_SHIFT));
+	mv_u3d_phy_write(base, USB3_GEN2_SET1, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_DIGITAL_LOOPBACK_EN);
+	val &= ~USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_MASK;
+	val |= 1 << USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_SHIFT;
+	mv_u3d_phy_write(base, USB3_DIGITAL_LOOPBACK_EN, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_IMPEDANCE_TX_SSC);
+	val &= ~USB3_IMPEDANCE_TX_SSC_SSC_AMP_MASK;
+	val |= 0xC << USB3_IMPEDANCE_TX_SSC_SSC_AMP_SHIFT;
+	mv_u3d_phy_write(base, USB3_IMPEDANCE_TX_SSC, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_IMPEDANCE_CALI_CTRL);
+	val &= ~USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_MASK;
+	val |= 0x4 << USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_SHIFT;
+	mv_u3d_phy_write(base, USB3_IMPEDANCE_CALI_CTRL, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_PHY_ISOLATION_MODE);
+	val &= ~(USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_MASK
+		| USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_MASK
+		| USB3_PHY_ISOLATION_MODE_TX_DRV_IDLE_MASK);
+	val |= ((1 << USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_SHIFT)
+		| (1 << USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_SHIFT));
+	mv_u3d_phy_write(base, USB3_PHY_ISOLATION_MODE, val);
+	udelay(100);
+
+	val = mv_u3d_phy_read(base, USB3_TXDETRX);
+	val &= ~(USB3_TXDETRX_VTHSEL_MASK);
+	val |= 0x1 << USB3_TXDETRX_VTHSEL_SHIFT;
+	mv_u3d_phy_write(base, USB3_TXDETRX, val);
+	udelay(100);
+
+	dev_dbg(mv_u3d_phy->dev, "start calibration\n");
+
+calstart:
+	/* Perform Manual Calibration */
+	mv_u3d_phy_set(base, USB3_KVCO_CALI_CONTROL,
+		1 << USB3_KVCO_CALI_CONTROL_CAL_START_SHIFT);
+
+	mdelay(1);
+
+	count = 0;
+	while (1) {
+		val = mv_u3d_phy_read(base, USB3_KVCO_CALI_CONTROL);
+		if (val & (1 << USB3_KVCO_CALI_CONTROL_CAL_DONE_SHIFT))
+			break;
+		else if (count > 50) {
+			dev_dbg(mv_u3d_phy->dev, "calibration failure, retry...\n");
+			goto calstart;
+		}
+		count++;
+		mdelay(1);
+	}
+
+	/* active PIPE interface */
+	mv_u3d_phy_write(base, USB3_PIPE_SM_CTRL,
+		1 << USB3_PIPE_SM_CTRL_PHY_INIT_DONE);
+
+	return 0;
+}
+
+static int __devinit mv_u3d_phy_probe(struct platform_device *pdev)
+{
+	struct mv_u3d_phy *mv_u3d_phy;
+	struct mv_usb_platform_data *pdata;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	void __iomem	*phy_base;
+	int	ret;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: no platform data defined\n", __func__);
+		return -EINVAL;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "missing mem resource\n");
+		return -ENODEV;
+	}
+
+	phy_base = devm_request_and_ioremap(dev, res);
+	if (!phy_base) {
+		dev_err(dev, "%s: register mapping failed\n", __func__);
+		return -ENXIO;
+	}
+
+	mv_u3d_phy = devm_kzalloc(dev, sizeof(*mv_u3d_phy), GFP_KERNEL);
+	if (!mv_u3d_phy)
+		return -ENOMEM;
+
+	mv_u3d_phy->dev			= &pdev->dev;
+	mv_u3d_phy->plat		= pdata;
+	mv_u3d_phy->base		= phy_base;
+	mv_u3d_phy->phy.dev		= mv_u3d_phy->dev;
+	mv_u3d_phy->phy.label		= "mv-u3d-phy";
+	mv_u3d_phy->phy.init		= mv_u3d_phy_init;
+	mv_u3d_phy->phy.shutdown	= mv_u3d_phy_shutdown;
+
+	ret = usb_add_phy(&mv_u3d_phy->phy, USB_PHY_TYPE_USB3);
+	if (ret)
+		goto err;
+
+	if (!mv_u3d_phy->clk)
+		mv_u3d_phy->clk = clk_get(mv_u3d_phy->dev, "u3dphy");
+
+	platform_set_drvdata(pdev, mv_u3d_phy);
+
+	dev_info(&pdev->dev, "Initialized Marvell USB 3.0 PHY\n");
+err:
+	return ret;
+}
+
+static int __exit mv_u3d_phy_remove(struct platform_device *pdev)
+{
+	struct mv_u3d_phy *mv_u3d_phy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&mv_u3d_phy->phy);
+
+	if (mv_u3d_phy->clk) {
+		clk_put(mv_u3d_phy->clk);
+		mv_u3d_phy->clk = NULL;
+	}
+
+	return 0;
+}
+
+static struct platform_driver mv_u3d_phy_driver = {
+	.probe		= mv_u3d_phy_probe,
+	.remove		= __devexit_p(mv_u3d_phy_remove),
+	.driver		= {
+		.name	= "mv-u3d-phy",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(mv_u3d_phy_driver);
+MODULE_DESCRIPTION("Marvell USB 3.0 PHY controller");
+MODULE_AUTHOR("Yu Xu <yuxu@marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mv-u3d-phy");
diff --git a/drivers/usb/phy/mv_u3d_phy.h b/drivers/usb/phy/mv_u3d_phy.h
new file mode 100644
index 0000000..2a658cb
--- /dev/null
+++ b/drivers/usb/phy/mv_u3d_phy.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#ifndef __MV_U3D_PHY_H
+#define __MV_U3D_PHY_H
+
+#define USB3_POWER_PLL_CONTROL		0x1
+#define USB3_KVCO_CALI_CONTROL		0x2
+#define USB3_IMPEDANCE_CALI_CTRL	0x3
+#define USB3_IMPEDANCE_TX_SSC		0x4
+#define USB3_SQUELCH_FFE		0x6
+#define USB3_GEN1_SET0			0xD
+#define USB3_GEN2_SET0			0xF
+#define USB3_GEN2_SET1			0x10
+#define USB3_DIGITAL_LOOPBACK_EN	0x23
+#define USB3_PHY_ISOLATION_MODE		0x26
+#define USB3_TXDETRX			0x48
+#define USB3_TX_EMPPH			0x5E
+#define USB3_RESET_CONTROL		0x90
+#define USB3_PIPE_SM_CTRL		0x91
+
+#define USB3_RESET_CONTROL_RESET_PIPE			0x1
+#define USB3_RESET_CONTROL_RESET_PHY			0x2
+
+#define USB3_POWER_PLL_CONTROL_REF_FREF_SEL_MASK	(0x1F << 0)
+#define USB3_POWER_PLL_CONTROL_REF_FREF_SEL_SHIFT	0
+#define USB3_PLL_25MHZ					0x2
+#define USB3_PLL_26MHZ					0x5
+#define USB3_POWER_PLL_CONTROL_PHY_MODE_MASK		(0x7 << 5)
+#define USB3_POWER_PLL_CONTROL_PHY_MODE_SHIFT		5
+#define USB3_POWER_PLL_CONTROL_PU_MASK			(0xF << 12)
+#define USB3_POWER_PLL_CONTROL_PU_SHIFT			12
+#define USB3_POWER_PLL_CONTROL_PU			(0xF << 12)
+
+#define USB3_KVCO_CALI_CONTROL_USE_MAX_PLL_RATE_MASK	(0x1 << 12)
+#define USB3_KVCO_CALI_CONTROL_USE_MAX_PLL_RATE_SHIFT	12
+#define USB3_KVCO_CALI_CONTROL_CAL_DONE_SHIFT		14
+#define USB3_KVCO_CALI_CONTROL_CAL_START_SHIFT		15
+
+#define USB3_SQUELCH_FFE_FFE_CAP_SEL_MASK		0xF
+#define USB3_SQUELCH_FFE_FFE_CAP_SEL_SHIFT		0
+#define USB3_SQUELCH_FFE_FFE_RES_SEL_MASK		(0x7 << 4)
+#define USB3_SQUELCH_FFE_FFE_RES_SEL_SHIFT		4
+#define USB3_SQUELCH_FFE_SQ_THRESH_IN_MASK		(0x1F << 8)
+#define USB3_SQUELCH_FFE_SQ_THRESH_IN_SHIFT		8
+
+#define USB3_GEN1_SET0_G1_TX_SLEW_CTRL_EN_MASK		(0x1 << 15)
+#define USB3_GEN1_SET0_G1_TX_EMPH_EN_SHIFT		11
+
+#define USB3_GEN2_SET0_G2_TX_AMP_MASK			(0x1F << 1)
+#define USB3_GEN2_SET0_G2_TX_AMP_SHIFT			1
+#define USB3_GEN2_SET0_G2_TX_AMP_ADJ_SHIFT		6
+#define USB3_GEN2_SET0_G2_TX_EMPH_AMP_MASK		(0xF << 7)
+#define USB3_GEN2_SET0_G2_TX_EMPH_AMP_SHIFT		7
+#define USB3_GEN2_SET0_G2_TX_EMPH_EN_MASK		(0x1 << 11)
+#define USB3_GEN2_SET0_G2_TX_EMPH_EN_SHIFT		11
+#define USB3_GEN2_SET0_G2_TX_SLEW_CTRL_EN_MASK		(0x1 << 15)
+#define USB3_GEN2_SET0_G2_TX_SLEW_CTRL_EN_SHIFT		15
+
+#define USB3_GEN2_SET1_G2_RX_SELMUPI_MASK		(0x7 << 0)
+#define USB3_GEN2_SET1_G2_RX_SELMUPI_SHIFT		0
+#define USB3_GEN2_SET1_G2_RX_SELMUPF_MASK		(0x7 << 3)
+#define USB3_GEN2_SET1_G2_RX_SELMUPF_SHIFT		3
+#define USB3_GEN2_SET1_G2_RX_SELMUFI_MASK		(0x3 << 6)
+#define USB3_GEN2_SET1_G2_RX_SELMUFI_SHIFT		6
+#define USB3_GEN2_SET1_G2_RX_SELMUFF_MASK		(0x3 << 8)
+#define USB3_GEN2_SET1_G2_RX_SELMUFF_SHIFT		8
+
+#define USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_MASK		(0x3 << 10)
+#define USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_SHIFT		10
+
+#define USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_MASK	(0x7 << 12)
+#define USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_SHIFT	12
+
+#define USB3_IMPEDANCE_TX_SSC_SSC_AMP_MASK		(0x3F << 0)
+#define USB3_IMPEDANCE_TX_SSC_SSC_AMP_SHIFT		0
+
+#define USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_MASK		0xF
+#define USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_SHIFT	0
+#define USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_MASK		(0xF << 4)
+#define USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_SHIFT	4
+#define USB3_PHY_ISOLATION_MODE_TX_DRV_IDLE_MASK	(0x1 << 8)
+
+#define USB3_TXDETRX_VTHSEL_MASK			(0x3 << 4)
+#define USB3_TXDETRX_VTHSEL_SHIFT			4
+
+#define USB3_TX_EMPPH_AMP_MASK				(0xF << 0)
+#define USB3_TX_EMPPH_AMP_SHIFT				0
+#define USB3_TX_EMPPH_EN_MASK				(0x1 << 6)
+#define USB3_TX_EMPPH_EN_SHIFT				6
+#define USB3_TX_EMPPH_AMP_FORCE_MASK			(0x1 << 7)
+#define USB3_TX_EMPPH_AMP_FORCE_SHIFT			7
+#define USB3_TX_EMPPH_PAR1_MASK				(0x1F << 8)
+#define USB3_TX_EMPPH_PAR1_SHIFT			8
+#define USB3_TX_EMPPH_PAR2_MASK				(0x1 << 13)
+#define USB3_TX_EMPPH_PAR2_SHIFT			13
+
+#define USB3_PIPE_SM_CTRL_PHY_INIT_DONE			15
+
+#endif /* __MV_U3D_PHY_H */
diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/omap-usb2.c
new file mode 100644
index 0000000..15ab3d6
--- /dev/null
+++ b/drivers/usb/phy/omap-usb2.c
@@ -0,0 +1,271 @@
+/*
+ * omap-usb2.c - USB PHY, talking to musb controller in OMAP.
+ *
+ * Copyright (C) 2012 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: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/usb/omap_usb.h>
+#include <linux/usb/phy_companion.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+
+/**
+ * omap_usb2_set_comparator - links the comparator present in the sytem with
+ *	this phy
+ * @comparator - the companion phy(comparator) for this phy
+ *
+ * The phy companion driver should call this API passing the phy_companion
+ * filled with set_vbus and start_srp to be used by usb phy.
+ *
+ * For use by phy companion driver
+ */
+int omap_usb2_set_comparator(struct phy_companion *comparator)
+{
+	struct omap_usb	*phy;
+	struct usb_phy	*x = usb_get_phy(USB_PHY_TYPE_USB2);
+
+	if (IS_ERR(x))
+		return -ENODEV;
+
+	phy = phy_to_omapusb(x);
+	phy->comparator = comparator;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
+
+/**
+ * omap_usb_phy_power - power on/off the phy using control module reg
+ * @phy: struct omap_usb *
+ * @on: 0 or 1, based on powering on or off the PHY
+ *
+ * XXX: Remove this function once control module driver gets merged
+ */
+static void omap_usb_phy_power(struct omap_usb *phy, int on)
+{
+	u32 val;
+
+	if (on) {
+		val = readl(phy->control_dev);
+		if (val & PHY_PD) {
+			writel(~PHY_PD, phy->control_dev);
+			/* XXX: add proper documentation for this delay */
+			mdelay(200);
+		}
+	} else {
+		writel(PHY_PD, phy->control_dev);
+	}
+}
+
+static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
+{
+	struct omap_usb *phy = phy_to_omapusb(otg->phy);
+
+	if (!phy->comparator)
+		return -ENODEV;
+
+	return phy->comparator->set_vbus(phy->comparator, enabled);
+}
+
+static int omap_usb_start_srp(struct usb_otg *otg)
+{
+	struct omap_usb *phy = phy_to_omapusb(otg->phy);
+
+	if (!phy->comparator)
+		return -ENODEV;
+
+	return phy->comparator->start_srp(phy->comparator);
+}
+
+static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	struct usb_phy	*phy = otg->phy;
+
+	otg->host = host;
+	if (!host)
+		phy->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int omap_usb_set_peripheral(struct usb_otg *otg,
+		struct usb_gadget *gadget)
+{
+	struct usb_phy	*phy = otg->phy;
+
+	otg->gadget = gadget;
+	if (!gadget)
+		phy->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int omap_usb2_suspend(struct usb_phy *x, int suspend)
+{
+	u32 ret;
+	struct omap_usb *phy = phy_to_omapusb(x);
+
+	if (suspend && !phy->is_suspended) {
+		omap_usb_phy_power(phy, 0);
+		pm_runtime_put_sync(phy->dev);
+		phy->is_suspended = 1;
+	} else if (!suspend && phy->is_suspended) {
+		ret = pm_runtime_get_sync(phy->dev);
+		if (ret < 0) {
+			dev_err(phy->dev, "get_sync failed with err %d\n",
+									ret);
+			return ret;
+		}
+		omap_usb_phy_power(phy, 1);
+		phy->is_suspended = 0;
+	}
+
+	return 0;
+}
+
+static int __devinit omap_usb2_probe(struct platform_device *pdev)
+{
+	struct omap_usb			*phy;
+	struct usb_otg			*otg;
+	struct resource			*res;
+
+	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy) {
+		dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n");
+		return -ENOMEM;
+	}
+
+	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+	if (!otg) {
+		dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n");
+		return -ENOMEM;
+	}
+
+	phy->dev		= &pdev->dev;
+
+	phy->phy.dev		= phy->dev;
+	phy->phy.label		= "omap-usb2";
+	phy->phy.set_suspend	= omap_usb2_suspend;
+	phy->phy.otg		= otg;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+	phy->control_dev = devm_request_and_ioremap(&pdev->dev, res);
+	if (phy->control_dev == NULL) {
+		dev_err(&pdev->dev, "Failed to obtain io memory\n");
+		return -ENXIO;
+	}
+
+	phy->is_suspended	= 1;
+	omap_usb_phy_power(phy, 0);
+
+	otg->set_host		= omap_usb_set_host;
+	otg->set_peripheral	= omap_usb_set_peripheral;
+	otg->set_vbus		= omap_usb_set_vbus;
+	otg->start_srp		= omap_usb_start_srp;
+	otg->phy		= &phy->phy;
+
+	phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
+	if (IS_ERR(phy->wkupclk)) {
+		dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
+		return PTR_ERR(phy->wkupclk);
+	}
+	clk_prepare(phy->wkupclk);
+
+	usb_add_phy(&phy->phy, USB_PHY_TYPE_USB2);
+
+	platform_set_drvdata(pdev, phy);
+
+	pm_runtime_enable(phy->dev);
+
+	return 0;
+}
+
+static int __devexit omap_usb2_remove(struct platform_device *pdev)
+{
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	clk_unprepare(phy->wkupclk);
+	usb_remove_phy(&phy->phy);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+
+static int omap_usb2_runtime_suspend(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	clk_disable(phy->wkupclk);
+
+	return 0;
+}
+
+static int omap_usb2_runtime_resume(struct device *dev)
+{
+	u32 ret = 0;
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	ret = clk_enable(phy->wkupclk);
+	if (ret < 0)
+		dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
+
+	return ret;
+}
+
+static const struct dev_pm_ops omap_usb2_pm_ops = {
+	SET_RUNTIME_PM_OPS(omap_usb2_runtime_suspend, omap_usb2_runtime_resume,
+		NULL)
+};
+
+#define DEV_PM_OPS     (&omap_usb2_pm_ops)
+#else
+#define DEV_PM_OPS     NULL
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id omap_usb2_id_table[] = {
+	{ .compatible = "ti,omap-usb2" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
+#endif
+
+static struct platform_driver omap_usb2_driver = {
+	.probe		= omap_usb2_probe,
+	.remove		= __devexit_p(omap_usb2_remove),
+	.driver		= {
+		.name	= "omap-usb2",
+		.owner	= THIS_MODULE,
+		.pm	= DEV_PM_OPS,
+		.of_match_table = of_match_ptr(omap_usb2_id_table),
+	},
+};
+
+module_platform_driver(omap_usb2_driver);
+
+MODULE_ALIAS("platform: omap_usb2");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("OMAP USB2 phy driver");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-tegra/usb_phy.c b/drivers/usb/phy/tegra_usb_phy.c
similarity index 93%
rename from arch/arm/mach-tegra/usb_phy.c
rename to drivers/usb/phy/tegra_usb_phy.c
index 022b33a..4739903 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/drivers/usb/phy/tegra_usb_phy.c
@@ -1,6 +1,4 @@
 /*
- * arch/arm/mach-tegra/usb_phy.c
- *
  * Copyright (C) 2010 Google, Inc.
  *
  * Author:
@@ -31,7 +29,7 @@
 #include <linux/usb/ulpi.h>
 #include <asm/mach-types.h>
 #include <mach/gpio-tegra.h>
-#include <mach/usb_phy.h>
+#include <linux/usb/tegra_usb_phy.h>
 #include <mach/iomap.h>
 
 #define ULPI_VIEWPORT		0x170
@@ -482,7 +480,7 @@
 	return 0;
 }
 
-static void utmi_phy_power_off(struct tegra_usb_phy *phy)
+static int utmi_phy_power_off(struct tegra_usb_phy *phy)
 {
 	unsigned long val;
 	void __iomem *base = phy->regs;
@@ -514,7 +512,7 @@
 	       UTMIP_FORCE_PDDR_POWERDOWN;
 	writel(val, base + UTMIP_XCVR_CFG1);
 
-	utmip_pad_power_off(phy);
+	return utmip_pad_power_off(phy);
 }
 
 static void utmi_phy_preresume(struct tegra_usb_phy *phy)
@@ -638,7 +636,7 @@
 	return 0;
 }
 
-static void ulpi_phy_power_off(struct tegra_usb_phy *phy)
+static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
 {
 	unsigned long val;
 	void __iomem *base = phy->regs;
@@ -651,15 +649,92 @@
 	val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN);
 	writel(val, base + USB_PORTSC1);
 
-	gpio_direction_output(config->reset_gpio, 0);
 	clk_disable(phy->clk);
+	return gpio_direction_output(config->reset_gpio, 0);
+}
+
+static int	tegra_phy_init(struct usb_phy *x)
+{
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+	struct tegra_ulpi_config *ulpi_config;
+	int err;
+
+	if (phy_is_ulpi(phy)) {
+		ulpi_config = phy->config;
+		phy->clk = clk_get_sys(NULL, ulpi_config->clk);
+		if (IS_ERR(phy->clk)) {
+			pr_err("%s: can't get ulpi clock\n", __func__);
+			err = -ENXIO;
+			goto err1;
+		}
+		if (!gpio_is_valid(ulpi_config->reset_gpio))
+			ulpi_config->reset_gpio =
+				of_get_named_gpio(phy->dev->of_node,
+						  "nvidia,phy-reset-gpio", 0);
+		if (!gpio_is_valid(ulpi_config->reset_gpio)) {
+			pr_err("%s: invalid reset gpio: %d\n", __func__,
+			       ulpi_config->reset_gpio);
+			err = -EINVAL;
+			goto err1;
+		}
+		gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b");
+		gpio_direction_output(ulpi_config->reset_gpio, 0);
+		phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
+		phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT;
+	} else {
+		err = utmip_pad_open(phy);
+		if (err < 0)
+			goto err1;
+	}
+	return 0;
+err1:
+	clk_disable_unprepare(phy->pll_u);
+	clk_put(phy->pll_u);
+	return err;
+}
+
+static void tegra_usb_phy_close(struct usb_phy *x)
+{
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+
+	if (phy_is_ulpi(phy))
+		clk_put(phy->clk);
+	else
+		utmip_pad_close(phy);
+	clk_disable_unprepare(phy->pll_u);
+	clk_put(phy->pll_u);
+	kfree(phy);
+}
+
+static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
+{
+	if (phy_is_ulpi(phy))
+		return ulpi_phy_power_on(phy);
+	else
+		return utmi_phy_power_on(phy);
+}
+
+static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
+{
+	if (phy_is_ulpi(phy))
+		return ulpi_phy_power_off(phy);
+	else
+		return utmi_phy_power_off(phy);
+}
+
+static int	tegra_usb_phy_suspend(struct usb_phy *x, int suspend)
+{
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+	if (suspend)
+		return tegra_usb_phy_power_off(phy);
+	else
+		return tegra_usb_phy_power_on(phy);
 }
 
 struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
 	void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode)
 {
 	struct tegra_usb_phy *phy;
-	struct tegra_ulpi_config *ulpi_config;
 	unsigned long parent_rate;
 	int i;
 	int err;
@@ -672,6 +747,7 @@
 	phy->regs = regs;
 	phy->config = config;
 	phy->mode = phy_mode;
+	phy->dev = dev;
 
 	if (!phy->config) {
 		if (phy_is_ulpi(phy)) {
@@ -704,33 +780,9 @@
 		goto err1;
 	}
 
-	if (phy_is_ulpi(phy)) {
-		ulpi_config = config;
-		phy->clk = clk_get_sys(NULL, ulpi_config->clk);
-		if (IS_ERR(phy->clk)) {
-			pr_err("%s: can't get ulpi clock\n", __func__);
-			err = -ENXIO;
-			goto err1;
-		}
-		if (!gpio_is_valid(ulpi_config->reset_gpio))
-			ulpi_config->reset_gpio =
-				of_get_named_gpio(dev->of_node,
-						  "nvidia,phy-reset-gpio", 0);
-		if (!gpio_is_valid(ulpi_config->reset_gpio)) {
-			pr_err("%s: invalid reset gpio: %d\n", __func__,
-			       ulpi_config->reset_gpio);
-			err = -EINVAL;
-			goto err1;
-		}
-		gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b");
-		gpio_direction_output(ulpi_config->reset_gpio, 0);
-		phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
-		phy->ulpi->io_priv = regs + ULPI_VIEWPORT;
-	} else {
-		err = utmip_pad_open(phy);
-		if (err < 0)
-			goto err1;
-	}
+	phy->u_phy.init = tegra_phy_init;
+	phy->u_phy.shutdown = tegra_usb_phy_close;
+	phy->u_phy.set_suspend = tegra_usb_phy_suspend;
 
 	return phy;
 
@@ -743,24 +795,6 @@
 }
 EXPORT_SYMBOL_GPL(tegra_usb_phy_open);
 
-int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
-{
-	if (phy_is_ulpi(phy))
-		return ulpi_phy_power_on(phy);
-	else
-		return utmi_phy_power_on(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_power_on);
-
-void tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
-{
-	if (phy_is_ulpi(phy))
-		ulpi_phy_power_off(phy);
-	else
-		utmi_phy_power_off(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_power_off);
-
 void tegra_usb_phy_preresume(struct tegra_usb_phy *phy)
 {
 	if (!phy_is_ulpi(phy))
@@ -803,15 +837,3 @@
 		utmi_phy_clk_enable(phy);
 }
 EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_enable);
-
-void tegra_usb_phy_close(struct tegra_usb_phy *phy)
-{
-	if (phy_is_ulpi(phy))
-		clk_put(phy->clk);
-	else
-		utmip_pad_close(phy);
-	clk_disable_unprepare(phy->pll_u);
-	clk_put(phy->pll_u);
-	kfree(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_close);
diff --git a/include/linux/usb/nop-usb-xceiv.h b/include/linux/usb/nop-usb-xceiv.h
new file mode 100644
index 0000000..28884c7
--- /dev/null
+++ b/include/linux/usb/nop-usb-xceiv.h
@@ -0,0 +1,24 @@
+#ifndef __LINUX_USB_NOP_XCEIV_H
+#define __LINUX_USB_NOP_XCEIV_H
+
+#include <linux/usb/otg.h>
+
+struct nop_usb_xceiv_platform_data {
+	enum usb_phy_type type;
+};
+
+#if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE))
+/* sometimes transceivers are accessed only through e.g. ULPI */
+extern void usb_nop_xceiv_register(void);
+extern void usb_nop_xceiv_unregister(void);
+#else
+static inline void usb_nop_xceiv_register(void)
+{
+}
+
+static inline void usb_nop_xceiv_unregister(void)
+{
+}
+#endif
+
+#endif /* __LINUX_USB_NOP_XCEIV_H */
diff --git a/include/linux/usb/omap_usb.h b/include/linux/usb/omap_usb.h
new file mode 100644
index 0000000..0ea17f8
--- /dev/null
+++ b/include/linux/usb/omap_usb.h
@@ -0,0 +1,46 @@
+/*
+ * omap_usb.h -- omap usb2 phy header file
+ *
+ * Copyright (C) 2012 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: Kishon Vijay Abraham I <kishon@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.
+ *
+ */
+
+#ifndef __DRIVERS_OMAP_USB2_H
+#define __DRIVERS_OMAP_USB2_H
+
+#include <linux/usb/otg.h>
+
+struct omap_usb {
+	struct usb_phy		phy;
+	struct phy_companion	*comparator;
+	struct device		*dev;
+	u32 __iomem		*control_dev;
+	struct clk		*wkupclk;
+	u8			is_suspended:1;
+};
+
+#define	PHY_PD	0x1
+
+#define	phy_to_omapusb(x)	container_of((x), struct omap_usb, phy)
+
+#if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE)
+extern int omap_usb2_set_comparator(struct phy_companion *comparator);
+#else
+static inline int omap_usb2_set_comparator(struct phy_companion *comparator)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif /* __DRIVERS_OMAP_USB_H */
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 45824be..e8a5fe8 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -9,56 +9,7 @@
 #ifndef __LINUX_USB_OTG_H
 #define __LINUX_USB_OTG_H
 
-#include <linux/notifier.h>
-
-/* OTG defines lots of enumeration states before device reset */
-enum usb_otg_state {
-	OTG_STATE_UNDEFINED = 0,
-
-	/* single-role peripheral, and dual-role default-b */
-	OTG_STATE_B_IDLE,
-	OTG_STATE_B_SRP_INIT,
-	OTG_STATE_B_PERIPHERAL,
-
-	/* extra dual-role default-b states */
-	OTG_STATE_B_WAIT_ACON,
-	OTG_STATE_B_HOST,
-
-	/* dual-role default-a */
-	OTG_STATE_A_IDLE,
-	OTG_STATE_A_WAIT_VRISE,
-	OTG_STATE_A_WAIT_BCON,
-	OTG_STATE_A_HOST,
-	OTG_STATE_A_SUSPEND,
-	OTG_STATE_A_PERIPHERAL,
-	OTG_STATE_A_WAIT_VFALL,
-	OTG_STATE_A_VBUS_ERR,
-};
-
-enum usb_phy_events {
-	USB_EVENT_NONE,         /* no events or cable disconnected */
-	USB_EVENT_VBUS,         /* vbus valid event */
-	USB_EVENT_ID,           /* id was grounded */
-	USB_EVENT_CHARGER,      /* usb dedicated charger */
-	USB_EVENT_ENUMERATED,   /* gadget driver enumerated */
-};
-
-/* associate a type with PHY */
-enum usb_phy_type {
-	USB_PHY_TYPE_UNDEFINED,
-	USB_PHY_TYPE_USB2,
-	USB_PHY_TYPE_USB3,
-};
-
-struct usb_phy;
-
-/* for transceivers connected thru an ULPI interface, the user must
- * provide access ops
- */
-struct usb_phy_io_ops {
-	int (*read)(struct usb_phy *x, u32 reg);
-	int (*write)(struct usb_phy *x, u32 val, u32 reg);
-};
+#include <linux/usb/phy.h>
 
 struct usb_otg {
 	u8			default_a;
@@ -85,134 +36,9 @@
 
 };
 
-/*
- * the otg driver needs to interact with both device side and host side
- * usb controllers.  it decides which controller is active at a given
- * moment, using the transceiver, ID signal, HNP and sometimes static
- * configuration information (including "board isn't wired for otg").
- */
-struct usb_phy {
-	struct device		*dev;
-	const char		*label;
-	unsigned int		 flags;
-
-	enum usb_phy_type	type;
-	enum usb_otg_state	state;
-	enum usb_phy_events	last_event;
-
-	struct usb_otg		*otg;
-
-	struct device		*io_dev;
-	struct usb_phy_io_ops	*io_ops;
-	void __iomem		*io_priv;
-
-	/* for notification of usb_phy_events */
-	struct atomic_notifier_head	notifier;
-
-	/* to pass extra port status to the root hub */
-	u16			port_status;
-	u16			port_change;
-
-	/* to support controllers that have multiple transceivers */
-	struct list_head	head;
-
-	/* initialize/shutdown the OTG controller */
-	int	(*init)(struct usb_phy *x);
-	void	(*shutdown)(struct usb_phy *x);
-
-	/* effective for B devices, ignored for A-peripheral */
-	int	(*set_power)(struct usb_phy *x,
-				unsigned mA);
-
-	/* for non-OTG B devices: set transceiver into suspend mode */
-	int	(*set_suspend)(struct usb_phy *x,
-				int suspend);
-
-	/* notify phy connect status change */
-	int	(*notify_connect)(struct usb_phy *x, int port);
-	int	(*notify_disconnect)(struct usb_phy *x, int port);
-};
-
-
-/* for board-specific init logic */
-extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type);
-extern void usb_remove_phy(struct usb_phy *);
-
-#if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE))
-/* sometimes transceivers are accessed only through e.g. ULPI */
-extern void usb_nop_xceiv_register(void);
-extern void usb_nop_xceiv_unregister(void);
-#else
-static inline void usb_nop_xceiv_register(void)
-{
-}
-
-static inline void usb_nop_xceiv_unregister(void)
-{
-}
-#endif
-
-/* helpers for direct access thru low-level io interface */
-static inline int usb_phy_io_read(struct usb_phy *x, u32 reg)
-{
-	if (x->io_ops && x->io_ops->read)
-		return x->io_ops->read(x, reg);
-
-	return -EINVAL;
-}
-
-static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg)
-{
-	if (x->io_ops && x->io_ops->write)
-		return x->io_ops->write(x, val, reg);
-
-	return -EINVAL;
-}
-
-static inline int
-usb_phy_init(struct usb_phy *x)
-{
-	if (x->init)
-		return x->init(x);
-
-	return 0;
-}
-
-static inline void
-usb_phy_shutdown(struct usb_phy *x)
-{
-	if (x->shutdown)
-		x->shutdown(x);
-}
-
-/* for usb host and peripheral controller drivers */
 #ifdef CONFIG_USB_OTG_UTILS
-extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
-extern struct usb_phy *devm_usb_get_phy(struct device *dev,
-	enum usb_phy_type type);
-extern void usb_put_phy(struct usb_phy *);
-extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
 extern const char *otg_state_string(enum usb_otg_state state);
 #else
-static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
-{
-	return NULL;
-}
-
-static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
-	enum usb_phy_type type)
-{
-	return NULL;
-}
-
-static inline void usb_put_phy(struct usb_phy *x)
-{
-}
-
-static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x)
-{
-}
-
 static inline const char *otg_state_string(enum usb_otg_state state)
 {
 	return NULL;
@@ -262,42 +88,6 @@
 }
 
 static inline int
-usb_phy_set_power(struct usb_phy *x, unsigned mA)
-{
-	if (x && x->set_power)
-		return x->set_power(x, mA);
-	return 0;
-}
-
-/* Context: can sleep */
-static inline int
-usb_phy_set_suspend(struct usb_phy *x, int suspend)
-{
-	if (x->set_suspend != NULL)
-		return x->set_suspend(x, suspend);
-	else
-		return 0;
-}
-
-static inline int
-usb_phy_notify_connect(struct usb_phy *x, int port)
-{
-	if (x->notify_connect)
-		return x->notify_connect(x, port);
-	else
-		return 0;
-}
-
-static inline int
-usb_phy_notify_disconnect(struct usb_phy *x, int port)
-{
-	if (x->notify_disconnect)
-		return x->notify_disconnect(x, port);
-	else
-		return 0;
-}
-
-static inline int
 otg_start_srp(struct usb_otg *otg)
 {
 	if (otg && otg->start_srp)
@@ -306,31 +96,7 @@
 	return -ENOTSUPP;
 }
 
-/* notifiers */
-static inline int
-usb_register_notifier(struct usb_phy *x, struct notifier_block *nb)
-{
-	return atomic_notifier_chain_register(&x->notifier, nb);
-}
-
-static inline void
-usb_unregister_notifier(struct usb_phy *x, struct notifier_block *nb)
-{
-	atomic_notifier_chain_unregister(&x->notifier, nb);
-}
-
 /* for OTG controller drivers (and maybe other stuff) */
 extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
 
-static inline const char *usb_phy_type_string(enum usb_phy_type type)
-{
-	switch (type) {
-	case USB_PHY_TYPE_USB2:
-		return "USB2 PHY";
-	case USB_PHY_TYPE_USB3:
-		return "USB3 PHY";
-	default:
-		return "UNKNOWN PHY TYPE";
-	}
-}
 #endif /* __LINUX_USB_OTG_H */
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
new file mode 100644
index 0000000..06b5bae
--- /dev/null
+++ b/include/linux/usb/phy.h
@@ -0,0 +1,233 @@
+/* USB OTG (On The Go) defines */
+/*
+ *
+ * These APIs may be used between USB controllers.  USB device drivers
+ * (for either host or peripheral roles) don't use these calls; they
+ * continue to use just usb_device and usb_gadget.
+ */
+
+#ifndef __LINUX_USB_PHY_H
+#define __LINUX_USB_PHY_H
+
+#include <linux/notifier.h>
+
+enum usb_phy_events {
+	USB_EVENT_NONE,         /* no events or cable disconnected */
+	USB_EVENT_VBUS,         /* vbus valid event */
+	USB_EVENT_ID,           /* id was grounded */
+	USB_EVENT_CHARGER,      /* usb dedicated charger */
+	USB_EVENT_ENUMERATED,   /* gadget driver enumerated */
+};
+
+/* associate a type with PHY */
+enum usb_phy_type {
+	USB_PHY_TYPE_UNDEFINED,
+	USB_PHY_TYPE_USB2,
+	USB_PHY_TYPE_USB3,
+};
+
+/* OTG defines lots of enumeration states before device reset */
+enum usb_otg_state {
+	OTG_STATE_UNDEFINED = 0,
+
+	/* single-role peripheral, and dual-role default-b */
+	OTG_STATE_B_IDLE,
+	OTG_STATE_B_SRP_INIT,
+	OTG_STATE_B_PERIPHERAL,
+
+	/* extra dual-role default-b states */
+	OTG_STATE_B_WAIT_ACON,
+	OTG_STATE_B_HOST,
+
+	/* dual-role default-a */
+	OTG_STATE_A_IDLE,
+	OTG_STATE_A_WAIT_VRISE,
+	OTG_STATE_A_WAIT_BCON,
+	OTG_STATE_A_HOST,
+	OTG_STATE_A_SUSPEND,
+	OTG_STATE_A_PERIPHERAL,
+	OTG_STATE_A_WAIT_VFALL,
+	OTG_STATE_A_VBUS_ERR,
+};
+
+struct usb_phy;
+struct usb_otg;
+
+/* for transceivers connected thru an ULPI interface, the user must
+ * provide access ops
+ */
+struct usb_phy_io_ops {
+	int (*read)(struct usb_phy *x, u32 reg);
+	int (*write)(struct usb_phy *x, u32 val, u32 reg);
+};
+
+struct usb_phy {
+	struct device		*dev;
+	const char		*label;
+	unsigned int		 flags;
+
+	enum usb_phy_type	type;
+	enum usb_otg_state	state;
+	enum usb_phy_events	last_event;
+
+	struct usb_otg		*otg;
+
+	struct device		*io_dev;
+	struct usb_phy_io_ops	*io_ops;
+	void __iomem		*io_priv;
+
+	/* for notification of usb_phy_events */
+	struct atomic_notifier_head	notifier;
+
+	/* to pass extra port status to the root hub */
+	u16			port_status;
+	u16			port_change;
+
+	/* to support controllers that have multiple transceivers */
+	struct list_head	head;
+
+	/* initialize/shutdown the OTG controller */
+	int	(*init)(struct usb_phy *x);
+	void	(*shutdown)(struct usb_phy *x);
+
+	/* effective for B devices, ignored for A-peripheral */
+	int	(*set_power)(struct usb_phy *x,
+				unsigned mA);
+
+	/* for non-OTG B devices: set transceiver into suspend mode */
+	int	(*set_suspend)(struct usb_phy *x,
+				int suspend);
+
+	/* notify phy connect status change */
+	int	(*notify_connect)(struct usb_phy *x, int port);
+	int	(*notify_disconnect)(struct usb_phy *x, int port);
+};
+
+
+/* for board-specific init logic */
+extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type);
+extern void usb_remove_phy(struct usb_phy *);
+
+/* helpers for direct access thru low-level io interface */
+static inline int usb_phy_io_read(struct usb_phy *x, u32 reg)
+{
+	if (x->io_ops && x->io_ops->read)
+		return x->io_ops->read(x, reg);
+
+	return -EINVAL;
+}
+
+static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg)
+{
+	if (x->io_ops && x->io_ops->write)
+		return x->io_ops->write(x, val, reg);
+
+	return -EINVAL;
+}
+
+static inline int
+usb_phy_init(struct usb_phy *x)
+{
+	if (x->init)
+		return x->init(x);
+
+	return 0;
+}
+
+static inline void
+usb_phy_shutdown(struct usb_phy *x)
+{
+	if (x->shutdown)
+		x->shutdown(x);
+}
+
+/* for usb host and peripheral controller drivers */
+#ifdef CONFIG_USB_OTG_UTILS
+extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
+extern struct usb_phy *devm_usb_get_phy(struct device *dev,
+	enum usb_phy_type type);
+extern void usb_put_phy(struct usb_phy *);
+extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
+#else
+static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
+{
+	return NULL;
+}
+
+static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
+	enum usb_phy_type type)
+{
+	return NULL;
+}
+
+static inline void usb_put_phy(struct usb_phy *x)
+{
+}
+
+static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x)
+{
+}
+
+#endif
+
+static inline int
+usb_phy_set_power(struct usb_phy *x, unsigned mA)
+{
+	if (x && x->set_power)
+		return x->set_power(x, mA);
+	return 0;
+}
+
+/* Context: can sleep */
+static inline int
+usb_phy_set_suspend(struct usb_phy *x, int suspend)
+{
+	if (x->set_suspend != NULL)
+		return x->set_suspend(x, suspend);
+	else
+		return 0;
+}
+
+static inline int
+usb_phy_notify_connect(struct usb_phy *x, int port)
+{
+	if (x->notify_connect)
+		return x->notify_connect(x, port);
+	else
+		return 0;
+}
+
+static inline int
+usb_phy_notify_disconnect(struct usb_phy *x, int port)
+{
+	if (x->notify_disconnect)
+		return x->notify_disconnect(x, port);
+	else
+		return 0;
+}
+
+/* notifiers */
+static inline int
+usb_register_notifier(struct usb_phy *x, struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&x->notifier, nb);
+}
+
+static inline void
+usb_unregister_notifier(struct usb_phy *x, struct notifier_block *nb)
+{
+	atomic_notifier_chain_unregister(&x->notifier, nb);
+}
+
+static inline const char *usb_phy_type_string(enum usb_phy_type type)
+{
+	switch (type) {
+	case USB_PHY_TYPE_USB2:
+		return "USB2 PHY";
+	case USB_PHY_TYPE_USB3:
+		return "USB3 PHY";
+	default:
+		return "UNKNOWN PHY TYPE";
+	}
+}
+#endif /* __LINUX_USB_PHY_H */
diff --git a/include/linux/usb/phy_companion.h b/include/linux/usb/phy_companion.h
new file mode 100644
index 0000000..edd2ec2
--- /dev/null
+++ b/include/linux/usb/phy_companion.h
@@ -0,0 +1,34 @@
+/*
+ * phy-companion.h -- phy companion to indicate the comparator part of PHY
+ *
+ * Copyright (C) 2012 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: Kishon Vijay Abraham I <kishon@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.
+ *
+ */
+
+#ifndef __DRIVERS_PHY_COMPANION_H
+#define __DRIVERS_PHY_COMPANION_H
+
+#include <linux/usb/otg.h>
+
+/* phy_companion to take care of VBUS, ID and srp capabilities */
+struct phy_companion {
+
+	/* effective for A-peripheral, ignored for B devices */
+	int	(*set_vbus)(struct phy_companion *x, bool enabled);
+
+	/* for B devices only:  start session with A-Host */
+	int	(*start_srp)(struct phy_companion *x);
+};
+
+#endif /* __DRIVERS_PHY_COMPANION_H */
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/include/linux/usb/tegra_usb_phy.h
similarity index 85%
rename from arch/arm/mach-tegra/include/mach/usb_phy.h
rename to include/linux/usb/tegra_usb_phy.h
index 935ce9f..176b1ca 100644
--- a/arch/arm/mach-tegra/include/mach/usb_phy.h
+++ b/include/linux/usb/tegra_usb_phy.h
@@ -1,6 +1,4 @@
 /*
- * arch/arm/mach-tegra/include/mach/usb_phy.h
- *
  * Copyright (C) 2010 Google, Inc.
  *
  * This software is licensed under the terms of the GNU General Public
@@ -14,8 +12,8 @@
  *
  */
 
-#ifndef __MACH_USB_PHY_H
-#define __MACH_USB_PHY_H
+#ifndef __TEGRA_USB_PHY_H
+#define __TEGRA_USB_PHY_H
 
 #include <linux/clk.h>
 #include <linux/usb/otg.h>
@@ -59,19 +57,17 @@
 	enum tegra_usb_phy_mode mode;
 	void *config;
 	struct usb_phy *ulpi;
+	struct usb_phy u_phy;
+	struct device *dev;
 };
 
 struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
 	void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode);
 
-int tegra_usb_phy_power_on(struct tegra_usb_phy *phy);
-
 void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy);
 
 void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy);
 
-void tegra_usb_phy_power_off(struct tegra_usb_phy *phy);
-
 void tegra_usb_phy_preresume(struct tegra_usb_phy *phy);
 
 void tegra_usb_phy_postresume(struct tegra_usb_phy *phy);
@@ -81,6 +77,4 @@
 
 void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy);
 
-void tegra_usb_phy_close(struct tegra_usb_phy *phy);
-
-#endif /* __MACH_USB_PHY_H */
+#endif /* __TEGRA_USB_PHY_H */