usb: otg: support for multiple transceivers by a single controller

Add a linked list for keeping multiple PHY instances with different
types so that we can have separate USB2 and USB3 PHYs on one single
board. _get_phy_ has been changed so that the controller gets
the transceiver by type. _remove_phy_ has been added to let the phy
be removed from the phy list.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 4468f2c..a06d28b 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -1687,7 +1687,7 @@
 
 	udc->gadget.ep0 = &udc->ep0in->ep;
 
-	udc->transceiver = usb_get_phy();
+	udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 
 	if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
 		if (udc->transceiver == NULL) {
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index d703850..0808820 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -2455,7 +2455,7 @@
 
 #ifdef CONFIG_USB_OTG
 	if (pdata->operating_mode == FSL_USB2_DR_OTG) {
-		udc_controller->transceiver = usb_get_phy();
+		udc_controller->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 		if (!udc_controller->transceiver) {
 			ERR("Can't find OTG driver!\n");
 			ret = -ENODEV;
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index 5d77995..75ff41a 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -2180,7 +2180,7 @@
 
 #ifdef CONFIG_USB_OTG_UTILS
 	if (pdata->mode == MV_USB_MODE_OTG)
-		udc->transceiver = usb_get_phy();
+		udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 #endif
 
 	udc->clknum = pdata->clknum;
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 74b9bb8..cf8bf26 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -2865,7 +2865,7 @@
 		 * use it.  Except for OTG, we don't _need_ to talk to one;
 		 * but not having one probably means no VBUS detection.
 		 */
-		xceiv = usb_get_phy();
+		xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 		if (xceiv)
 			type = xceiv->label;
 		else if (config->otg) {
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index a658e44..cc0b1e6 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -2159,7 +2159,7 @@
 	dev->dev = &pdev->dev;
 	dev->mach = pdev->dev.platform_data;
 
-	dev->transceiver = usb_get_phy();
+	dev->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 
 	if (gpio_is_valid(dev->mach->gpio_pullup)) {
 		if ((retval = gpio_request(dev->mach->gpio_pullup,
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index b982304..8f744aa 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -2464,7 +2464,7 @@
 
 	udc->dev = &pdev->dev;
 	udc->mach = pdev->dev.platform_data;
-	udc->transceiver = usb_get_phy();
+	udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 
 	gpio = udc->mach->gpio_pullup;
 	if (gpio_is_valid(gpio)) {
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index 9ad3339..22326f2 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -1282,7 +1282,7 @@
 	hsudc->dev = dev;
 	hsudc->pd = pdev->dev.platform_data;
 
-	hsudc->transceiver = usb_get_phy();
+	hsudc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 
 	for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++)
 		hsudc->supplies[i].supply = s3c_hsudc_supply_names[i];
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 0e8976a..ba29058 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -142,7 +142,7 @@
 	if (pdata->operating_mode == FSL_USB2_DR_OTG) {
 		struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 
-		ehci->transceiver = usb_get_phy();
+		ehci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 		dev_dbg(&pdev->dev, "hcd=0x%p  ehci=0x%p, transceiver=0x%p\n",
 			hcd, ehci, ehci->transceiver);
 
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 7badd5d..c7615fb 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -145,7 +145,7 @@
 	 * powering up VBUS, mapping of registers address space and power
 	 * management.
 	 */
-	phy = usb_get_phy();
+	phy = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (!phy) {
 		dev_err(&pdev->dev, "unable to find transceiver\n");
 		ret = -ENODEV;
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index 24f838f..ef7aa0d 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -253,7 +253,7 @@
 	ehci_mv->mode = pdata->mode;
 	if (ehci_mv->mode == MV_USB_MODE_OTG) {
 #ifdef CONFIG_USB_OTG_UTILS
-		ehci_mv->otg = usb_get_phy();
+		ehci_mv->otg = usb_get_phy(USB_PHY_TYPE_USB2);
 		if (!ehci_mv->otg) {
 			dev_err(&pdev->dev,
 				"unable to find transceiver\n");
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index ee17d19..14df2f5 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -749,7 +749,7 @@
 
 #ifdef CONFIG_USB_OTG_UTILS
 	if (pdata->operating_mode == TEGRA_USB_OTG) {
-		tegra->transceiver = usb_get_phy();
+		tegra->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 		if (tegra->transceiver)
 			otg_set_host(tegra->transceiver->otg, &hcd->self);
 	}
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index c2c1f55..92a77df 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -211,7 +211,7 @@
 
 #ifdef	CONFIG_USB_OTG
 	if (need_transceiver) {
-		ohci->transceiver = usb_get_phy();
+		ohci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 		if (ohci->transceiver) {
 			int	status = otg_set_host(ohci->transceiver->otg,
 						&ohci_to_hcd(ohci)->self);
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index a75989b..4a8cbf0e 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -364,7 +364,7 @@
 		return -ENODEV;
 
 	usb_nop_xceiv_register();
-	musb->xceiv = usb_get_phy();
+	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (!musb->xceiv)
 		return -ENODEV;
 
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index 522a4a2..4529409 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -415,7 +415,7 @@
 	gpio_direction_output(musb->config->gpio_vrsel, 0);
 
 	usb_nop_xceiv_register();
-	musb->xceiv = usb_get_phy();
+	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (!musb->xceiv) {
 		gpio_free(musb->config->gpio_vrsel);
 		return -ENODEV;
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 61868d6..d731c80 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -425,7 +425,7 @@
 		goto fail;
 
 	usb_nop_xceiv_register();
-	musb->xceiv = usb_get_phy();
+	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (!musb->xceiv)
 		goto fail;
 
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 441f776..582268d 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -384,7 +384,7 @@
 	u32		revision;
 
 	usb_nop_xceiv_register();
-	musb->xceiv = usb_get_phy();
+	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (!musb->xceiv)
 		goto unregister;
 
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 716c113..92603e4 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -376,7 +376,7 @@
 
 	/* NOP driver needs change if supporting dual instance */
 	usb_nop_xceiv_register();
-	musb->xceiv = usb_get_phy();
+	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (!musb->xceiv)
 		return -ENODEV;
 
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index e16dbbf..e279cf3 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -292,7 +292,7 @@
 	 * up through ULPI.  TWL4030-family PMICs include one,
 	 * which needs a driver, drivers aren't always needed.
 	 */
-	musb->xceiv = usb_get_phy();
+	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (!musb->xceiv) {
 		pr_err("HS USB OTG: no transceiver configured\n");
 		return -ENODEV;
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index a004736..8ddf3d5 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1078,7 +1078,7 @@
 	int			ret;
 
 	usb_nop_xceiv_register();
-	musb->xceiv = usb_get_phy();
+	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (!musb->xceiv)
 		return -ENODEV;
 
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index 53006b1..46cf80a 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -37,7 +37,7 @@
 
 static int ux500_musb_init(struct musb *musb)
 {
-	musb->xceiv = usb_get_phy();
+	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (!musb->xceiv) {
 		pr_err("HS USB OTG: no transceiver configured\n");
 		return -ENODEV;
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
index 672e28c..ae8ad56 100644
--- a/drivers/usb/otg/ab8500-usb.c
+++ b/drivers/usb/otg/ab8500-usb.c
@@ -529,7 +529,7 @@
 	if (err < 0)
 		goto fail0;
 
-	err = usb_add_phy(&ab->phy);
+	err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2);
 	if (err) {
 		dev_err(&pdev->dev, "Can't register transceiver\n");
 		goto fail1;
@@ -556,7 +556,7 @@
 
 	cancel_work_sync(&ab->phy_dis_work);
 
-	usb_add_phy(NULL);
+	usb_remove_phy(&ab->phy);
 
 	ab8500_usb_host_phy_dis(ab);
 	ab8500_usb_peri_phy_dis(ab);
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c
index 73561ed..23c798c 100644
--- a/drivers/usb/otg/fsl_otg.c
+++ b/drivers/usb/otg/fsl_otg.c
@@ -806,7 +806,7 @@
 	fsl_otg_dev = fsl_otg_tc;
 
 	/* Store the otg transceiver */
-	status = usb_add_phy(&fsl_otg_tc->phy);
+	status = usb_add_phy(&fsl_otg_tc->phy, USB_PHY_TYPE_USB2);
 	if (status) {
 		pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n");
 		goto err;
@@ -824,7 +824,7 @@
 int usb_otg_start(struct platform_device *pdev)
 {
 	struct fsl_otg *p_otg;
-	struct usb_phy *otg_trans = usb_get_phy();
+	struct usb_phy *otg_trans = usb_get_phy(USB_PHY_TYPE_USB2);
 	struct otg_fsm *fsm;
 	int status;
 	struct resource *res;
@@ -1134,7 +1134,7 @@
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 
-	usb_add_phy(NULL);
+	usb_remove_phy(&fsl_otg_dev->phy);
 	free_irq(fsl_otg_dev->irq, fsl_otg_dev);
 
 	iounmap((void *)usb_dr_regs);
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c
index 9b3c264..a67ffe2 100644
--- a/drivers/usb/otg/gpio_vbus.c
+++ b/drivers/usb/otg/gpio_vbus.c
@@ -320,7 +320,7 @@
 	}
 
 	/* only active when a gadget is registered */
-	err = usb_add_phy(&gpio_vbus->phy);
+	err = usb_add_phy(&gpio_vbus->phy, USB_PHY_TYPE_USB2);
 	if (err) {
 		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
 			err);
@@ -354,7 +354,7 @@
 	cancel_delayed_work_sync(&gpio_vbus->work);
 	regulator_put(gpio_vbus->vbus_draw);
 
-	usb_add_phy(NULL);
+	usb_remove_phy(&gpio_vbus->phy);
 
 	free_irq(gpio_vbus->irq, pdev);
 	if (gpio_is_valid(pdata->gpio_pullup))
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
index b74df3f..75cea4a 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/otg/isp1301_omap.c
@@ -1611,7 +1611,7 @@
 	dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
 #endif
 
-	status = usb_add_phy(&isp->phy);
+	status = usb_add_phy(&isp->phy, USB_PHY_TYPE_USB2);
 	if (status < 0)
 		dev_err(&i2c->dev, "can't register transceiver, %d\n",
 			status);
@@ -1650,7 +1650,7 @@
 static void __exit isp_exit(void)
 {
 	if (the_transceiver)
-		usb_add_phy(NULL);
+		usb_remove_phy(&the_transceiver->phy);
 	i2c_del_driver(&isp1301_driver);
 }
 module_exit(isp_exit);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index dd606c0..9f5fc90 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1555,7 +1555,7 @@
 	phy->otg->set_host = msm_otg_set_host;
 	phy->otg->set_peripheral = msm_otg_set_peripheral;
 
-	ret = usb_add_phy(&motg->phy);
+	ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2);
 	if (ret) {
 		dev_err(&pdev->dev, "usb_add_phy failed\n");
 		goto free_irq;
@@ -1624,7 +1624,7 @@
 	device_init_wakeup(&pdev->dev, 0);
 	pm_runtime_disable(&pdev->dev);
 
-	usb_add_phy(NULL);
+	usb_remove_phy(phy);
 	free_irq(motg->irq, motg);
 
 	/*
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c
index 18e90fe..3f124e8 100644
--- a/drivers/usb/otg/mv_otg.c
+++ b/drivers/usb/otg/mv_otg.c
@@ -690,7 +690,7 @@
 	for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++)
 		clk_put(mvotg->clk[clk_i]);
 
-	usb_add_phy(NULL);
+	usb_remove_phy(&mvotg->phy);
 	platform_set_drvdata(pdev, NULL);
 
 	kfree(mvotg->phy.otg);
@@ -853,7 +853,7 @@
 		goto err_disable_clk;
 	}
 
-	retval = usb_add_phy(&mvotg->phy);
+	retval = usb_add_phy(&mvotg->phy, USB_PHY_TYPE_USB2);
 	if (retval < 0) {
 		dev_err(&pdev->dev, "can't register transceiver, %d\n",
 			retval);
@@ -880,7 +880,7 @@
 	return 0;
 
 err_set_transceiver:
-	usb_add_phy(NULL);
+	usb_remove_phy(&mvotg->phy);
 err_free_irq:
 	free_irq(mvotg->irq, mvotg);
 err_disable_clk:
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
index 33000da..803f958 100644
--- a/drivers/usb/otg/nop-usb-xceiv.c
+++ b/drivers/usb/otg/nop-usb-xceiv.c
@@ -117,7 +117,7 @@
 	nop->phy.otg->set_host		= nop_set_host;
 	nop->phy.otg->set_peripheral	= nop_set_peripheral;
 
-	err = usb_add_phy(&nop->phy);
+	err = usb_add_phy(&nop->phy, USB_PHY_TYPE_USB2);
 	if (err) {
 		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
 			err);
@@ -139,7 +139,7 @@
 {
 	struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
 
-	usb_add_phy(NULL);
+	usb_remove_phy(&nop->phy);
 
 	platform_set_drvdata(pdev, NULL);
 	kfree(nop->phy.otg);
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
index 300a995..a230658 100644
--- a/drivers/usb/otg/otg.c
+++ b/drivers/usb/otg/otg.c
@@ -11,14 +11,32 @@
 
 #include <linux/kernel.h>
 #include <linux/export.h>
+#include <linux/err.h>
 #include <linux/device.h>
 
 #include <linux/usb/otg.h>
 
-static struct usb_phy *phy;
+static LIST_HEAD(phy_list);
+static DEFINE_SPINLOCK(phy_lock);
+
+static struct usb_phy *__usb_find_phy(struct list_head *list,
+	enum usb_phy_type type)
+{
+	struct usb_phy  *phy = NULL;
+
+	list_for_each_entry(phy, list, head) {
+		if (phy->type != type)
+			continue;
+
+		return phy;
+	}
+
+	return ERR_PTR(-ENODEV);
+}
 
 /**
- * usb_get_phy - find the (single) USB PHY
+ * usb_get_phy - find the USB PHY
+ * @type - the type of the phy the controller requires
  *
  * Returns the phy driver, after getting a refcount to it; or
  * null if there is no such phy.  The caller is responsible for
@@ -26,16 +44,30 @@
  *
  * For use by USB host and peripheral drivers.
  */
-struct usb_phy *usb_get_phy(void)
+struct usb_phy *usb_get_phy(enum usb_phy_type type)
 {
-	if (phy)
-		get_device(phy->dev);
+	struct usb_phy	*phy = NULL;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&phy_lock, flags);
+
+	phy = __usb_find_phy(&phy_list, type);
+	if (IS_ERR(phy)) {
+		pr_err("unable to find transceiver of type %s\n",
+			usb_phy_type_string(type));
+		return phy;
+	}
+
+	get_device(phy->dev);
+
+	spin_unlock_irqrestore(&phy_lock, flags);
+
 	return phy;
 }
 EXPORT_SYMBOL(usb_get_phy);
 
 /**
- * usb_put_phy - release the (single) USB PHY
+ * usb_put_phy - release the USB PHY
  * @x: the phy returned by usb_get_phy()
  *
  * Releases a refcount the caller received from usb_get_phy().
@@ -50,22 +82,62 @@
 EXPORT_SYMBOL(usb_put_phy);
 
 /**
- * usb_add_phy - declare the (single) USB PHY
+ * usb_add_phy - declare the USB PHY
  * @x: the USB phy to be used; or NULL
+ * @type - the type of this PHY
  *
  * This call is exclusively for use by phy drivers, which
  * coordinate the activities of drivers for host and peripheral
  * controllers, and in some cases for VBUS current regulation.
  */
-int usb_add_phy(struct usb_phy *x)
+int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
 {
-	if (phy && x)
-		return -EBUSY;
-	phy = x;
-	return 0;
+	int		ret = 0;
+	unsigned long	flags;
+	struct usb_phy	*phy;
+
+	if (x && x->type != USB_PHY_TYPE_UNDEFINED) {
+		dev_err(x->dev, "not accepting initialized PHY %s\n", x->label);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&phy_lock, flags);
+
+	list_for_each_entry(phy, &phy_list, head) {
+		if (phy->type == type) {
+			ret = -EBUSY;
+			dev_err(x->dev, "transceiver type %s already exists\n",
+						usb_phy_type_string(type));
+			goto out;
+		}
+	}
+
+	x->type = type;
+	list_add_tail(&x->head, &phy_list);
+
+out:
+	spin_unlock_irqrestore(&phy_lock, flags);
+	return ret;
 }
 EXPORT_SYMBOL(usb_add_phy);
 
+/**
+ * usb_remove_phy - remove the OTG PHY
+ * @x: the USB OTG PHY to be removed;
+ *
+ * This reverts the effects of usb_add_phy
+ */
+void usb_remove_phy(struct usb_phy *x)
+{
+	unsigned long	flags;
+
+	spin_lock_irqsave(&phy_lock, flags);
+	if (x)
+		list_del(&x->head);
+	spin_unlock_irqrestore(&phy_lock, flags);
+}
+EXPORT_SYMBOL(usb_remove_phy);
+
 const char *otg_state_string(enum usb_otg_state state)
 {
 	switch (state) {
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index 01022c8..25a09fa 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -633,7 +633,7 @@
 		kfree(twl);
 		return err;
 	}
-	usb_add_phy(&twl->phy);
+	usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
 
 	platform_set_drvdata(pdev, twl);
 	if (device_create_file(&pdev->dev, &dev_attr_vbus))
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index a8be208..dbee00a 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -443,7 +443,7 @@
 		kfree(twl);
 		return err;
 	}
-	usb_add_phy(&twl->phy);
+	usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
 
 	platform_set_drvdata(pdev, twl);
 	if (device_create_file(&pdev->dev, &dev_attr_vbus))