summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/chipidea/udc.c17
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c17
-rw-r--r--drivers/usb/gadget/mv_udc_core.c15
-rw-r--r--drivers/usb/gadget/omap_udc.c31
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c17
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c15
-rw-r--r--drivers/usb/gadget/s3c-hsudc.c13
-rw-r--r--drivers/usb/host/ehci-fsl.c11
-rw-r--r--drivers/usb/host/ehci-msm.c8
-rw-r--r--drivers/usb/host/ehci-mv.c13
-rw-r--r--drivers/usb/host/ehci-tegra.c13
-rw-r--r--drivers/usb/host/ohci-omap.c11
-rw-r--r--drivers/usb/musb/am35x.c7
-rw-r--r--drivers/usb/musb/blackfin.c7
-rw-r--r--drivers/usb/musb/da8xx.c7
-rw-r--r--drivers/usb/musb/davinci.c9
-rw-r--r--drivers/usb/musb/musb_core.c2
-rw-r--r--drivers/usb/musb/musb_core.h2
-rw-r--r--drivers/usb/musb/musb_dsps.c9
-rw-r--r--drivers/usb/musb/omap2430.c124
-rw-r--r--drivers/usb/musb/tusb6010.c9
-rw-r--r--drivers/usb/musb/ux500.c7
-rw-r--r--drivers/usb/otg/ab8500-usb.c4
-rw-r--r--drivers/usb/otg/fsl_otg.c6
-rw-r--r--drivers/usb/otg/gpio_vbus.c4
-rw-r--r--drivers/usb/otg/isp1301_omap.c19
-rw-r--r--drivers/usb/otg/msm_otg.c6
-rw-r--r--drivers/usb/otg/mv_otg.c6
-rw-r--r--drivers/usb/otg/nop-usb-xceiv.c4
-rw-r--r--drivers/usb/otg/otg.c181
-rw-r--r--drivers/usb/otg/twl4030-usb.c73
-rw-r--r--drivers/usb/otg/twl6030-usb.c69
32 files changed, 441 insertions, 295 deletions
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 51f96942dc5..4688ab71bd2 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -14,6 +14,7 @@
#include <linux/device.h>
#include <linux/dmapool.h>
#include <linux/dma-mapping.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/module.h>
@@ -1687,7 +1688,7 @@ static int udc_start(struct ci13xxx *udc)
udc->gadget.ep0 = &udc->ep0in->ep;
- udc->transceiver = usb_get_transceiver();
+ udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
if (udc->transceiver == NULL) {
@@ -1712,7 +1713,7 @@ static int udc_start(struct ci13xxx *udc)
if (retval)
goto unreg_device;
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval)
@@ -1729,9 +1730,9 @@ static int udc_start(struct ci13xxx *udc)
return retval;
remove_trans:
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
- usb_put_transceiver(udc->transceiver);
+ usb_put_phy(udc->transceiver);
}
dev_err(dev, "error = %i\n", retval);
@@ -1740,8 +1741,8 @@ remove_dbg:
unreg_device:
device_unregister(&udc->gadget.dev);
put_transceiver:
- if (udc->transceiver)
- usb_put_transceiver(udc->transceiver);
+ if (!IS_ERR_OR_NULL(udc->transceiver))
+ usb_put_phy(udc->transceiver);
free_pools:
dma_pool_destroy(udc->td_pool);
free_qh_pool:
@@ -1772,9 +1773,9 @@ static void udc_stop(struct ci13xxx *udc)
dma_pool_destroy(udc->td_pool);
dma_pool_destroy(udc->qh_pool);
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
otg_set_peripheral(udc->transceiver->otg, NULL);
- usb_put_transceiver(udc->transceiver);
+ usb_put_phy(udc->transceiver);
}
dbg_remove_files(&udc->gadget.dev);
device_unregister(&udc->gadget.dev);
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index a65ca0f5d8c..3def828f85e 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -24,6 +24,7 @@
#include <linux/ioport.h>
#include <linux/types.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/list.h>
@@ -1229,7 +1230,7 @@ static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA)
struct fsl_udc *udc;
udc = container_of(gadget, struct fsl_udc, gadget);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -ENOTSUPP;
}
@@ -1983,13 +1984,13 @@ static int fsl_start(struct usb_gadget_driver *driver,
goto out;
}
- if (udc_controller->transceiver) {
+ if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
/* Suspend the controller until OTG enable it */
udc_controller->stopped = 1;
printk(KERN_INFO "Suspend udc for OTG auto detect\n");
/* connect to bus through transceiver */
- if (udc_controller->transceiver) {
+ if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
retval = otg_set_peripheral(
udc_controller->transceiver->otg,
&udc_controller->gadget);
@@ -2030,7 +2031,7 @@ static int fsl_stop(struct usb_gadget_driver *driver)
if (!driver || driver != udc_controller->driver || !driver->unbind)
return -EINVAL;
- if (udc_controller->transceiver)
+ if (!IS_ERR_OR_NULL(udc_controller->transceiver))
otg_set_peripheral(udc_controller->transceiver->otg, NULL);
/* stop DR, disable intr */
@@ -2455,8 +2456,8 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
#ifdef CONFIG_USB_OTG
if (pdata->operating_mode == FSL_USB2_DR_OTG) {
- udc_controller->transceiver = usb_get_transceiver();
- if (!udc_controller->transceiver) {
+ udc_controller->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
ERR("Can't find OTG driver!\n");
ret = -ENODEV;
goto err_kfree;
@@ -2540,7 +2541,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
goto err_free_irq;
}
- if (!udc_controller->transceiver) {
+ if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
/* initialize usb hw reg except for regs for EP,
* leave usbintr reg untouched */
dr_controller_setup(udc_controller);
@@ -2565,7 +2566,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
if (ret < 0)
goto err_free_irq;
- if (udc_controller->transceiver)
+ if (!IS_ERR_OR_NULL(udc_controller->transceiver))
udc_controller->gadget.is_otg = 1;
/* setup QH and epctrl for ep0 */
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index 117a4bba1b8..75db2c306ce 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -19,6 +19,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
@@ -1381,7 +1382,7 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
return retval;
}
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval) {
@@ -2107,7 +2108,7 @@ static int __devexit mv_udc_remove(struct platform_device *dev)
* then vbus irq will not be requested in udc driver.
*/
if (udc->pdata && udc->pdata->vbus
- && udc->clock_gating && udc->transceiver == NULL)
+ && udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
free_irq(udc->pdata->vbus->irq, &dev->dev);
/* free memory allocated in probe */
@@ -2180,7 +2181,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
#ifdef CONFIG_USB_OTG_UTILS
if (pdata->mode == MV_USB_MODE_OTG)
- udc->transceiver = usb_get_transceiver();
+ udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
#endif
udc->clknum = pdata->clknum;
@@ -2325,7 +2326,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
eps_init(udc);
/* VBUS detect: we can disable/enable clock on demand.*/
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
udc->clock_gating = 1;
else if (pdata->vbus) {
udc->clock_gating = 1;
@@ -2369,7 +2370,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
err_unregister:
if (udc->pdata && udc->pdata->vbus
- && udc->clock_gating && udc->transceiver == NULL)
+ && udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
free_irq(pdata->vbus->irq, &dev->dev);
device_unregister(&udc->gadget.dev);
err_free_irq:
@@ -2404,7 +2405,7 @@ static int mv_udc_suspend(struct device *_dev)
struct mv_udc *udc = the_controller;
/* if OTG is enabled, the following will be done in OTG driver*/
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return 0;
if (udc->pdata->vbus && udc->pdata->vbus->poll)
@@ -2437,7 +2438,7 @@ static int mv_udc_resume(struct device *_dev)
int retval;
/* if OTG is enabled, the following will be done in OTG driver*/
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return 0;
if (!udc->clock_gating) {
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index b26c7d68cc0..d7df89e72ef 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -35,6 +35,7 @@
#include <linux/usb/otg.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/prefetch.h>
#include <linux/io.h>
@@ -1152,7 +1153,7 @@ static int omap_wakeup(struct usb_gadget *gadget)
/* NOTE: non-OTG systems may use SRP TOO... */
} else if (!(udc->devstat & UDC_ATT)) {
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
retval = otg_start_srp(udc->transceiver->otg);
}
spin_unlock_irqrestore(&udc->lock, flags);
@@ -1284,7 +1285,7 @@ static int omap_vbus_draw(struct usb_gadget *gadget, unsigned mA)
struct omap_udc *udc;
udc = container_of(gadget, struct omap_udc, gadget);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -EOPNOTSUPP;
}
@@ -1734,12 +1735,12 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
if (devstat & UDC_ATT) {
udc->gadget.speed = USB_SPEED_FULL;
VDBG("connect\n");
- if (!udc->transceiver)
+ if (IS_ERR_OR_NULL(udc->transceiver))
pullup_enable(udc);
/* if (driver->connect) call it */
} else if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
udc->gadget.speed = USB_SPEED_UNKNOWN;
- if (!udc->transceiver)
+ if (IS_ERR_OR_NULL(udc->transceiver))
pullup_disable(udc);
DBG("disconnect, gadget %s\n",
udc->driver->driver.name);
@@ -1779,12 +1780,12 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
udc->driver->suspend(&udc->gadget);
spin_lock(&udc->lock);
}
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
usb_phy_set_suspend(
udc->transceiver, 1);
} else {
VDBG("resume\n");
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
usb_phy_set_suspend(
udc->transceiver, 0);
if (udc->gadget.speed == USB_SPEED_FULL
@@ -2092,7 +2093,7 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
/* connect to bus through transceiver */
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
status = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (status < 0) {
@@ -2139,7 +2140,7 @@ static int omap_udc_stop(struct usb_gadget_driver *driver)
if (machine_without_vbus_sense())
omap_vbus_session(&udc->gadget, 0);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
(void) otg_set_peripheral(udc->transceiver->otg, NULL);
else
pullup_disable(udc);
@@ -2829,8 +2830,8 @@ static int __devinit omap_udc_probe(struct platform_device *pdev)
* 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_transceiver();
- if (xceiv)
+ xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (!IS_ERR_OR_NULL(xceiv))
type = xceiv->label;
else if (config->otg) {
DBG("OTG requires external transceiver!\n");
@@ -2854,7 +2855,7 @@ static int __devinit omap_udc_probe(struct platform_device *pdev)
case 16:
case 19:
case 25:
- if (!xceiv) {
+ if (IS_ERR_OR_NULL(xceiv)) {
DBG("external transceiver not registered!\n");
type = "unknown";
}
@@ -2956,8 +2957,8 @@ cleanup1:
udc = NULL;
cleanup0:
- if (xceiv)
- usb_put_transceiver(xceiv);
+ if (!IS_ERR_OR_NULL(xceiv))
+ usb_put_phy(xceiv);
if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
clk_disable(hhc_clk);
@@ -2986,8 +2987,8 @@ static int __devexit omap_udc_remove(struct platform_device *pdev)
udc->done = &done;
pullup_disable(udc);
- if (udc->transceiver) {
- usb_put_transceiver(udc->transceiver);
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
+ usb_put_phy(udc->transceiver);
udc->transceiver = NULL;
}
omap_writew(0, UDC_SYSCON1);
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index f7ff9e8e746..53c093b941e 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -21,6 +21,7 @@
#include <linux/ioport.h>
#include <linux/types.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
@@ -993,7 +994,7 @@ static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
udc = container_of(_gadget, struct pxa25x_udc, gadget);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -EOPNOTSUPP;
}
@@ -1299,7 +1300,7 @@ fail:
DMSG("registered gadget driver '%s'\n", driver->driver.name);
/* connect to bus through transceiver */
- if (dev->transceiver) {
+ if (!IS_ERR_OR_NULL(dev->transceiver)) {
retval = otg_set_peripheral(dev->transceiver->otg,
&dev->gadget);
if (retval) {
@@ -1359,7 +1360,7 @@ static int pxa25x_stop(struct usb_gadget_driver *driver)
stop_activity(dev, driver);
local_irq_enable();
- if (dev->transceiver)
+ if (!IS_ERR_OR_NULL(dev->transceiver))
(void) otg_set_peripheral(dev->transceiver->otg, NULL);
driver->unbind(&dev->gadget);
@@ -2159,7 +2160,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
dev->dev = &pdev->dev;
dev->mach = pdev->dev.platform_data;
- dev->transceiver = usb_get_transceiver();
+ 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,
@@ -2237,8 +2238,8 @@ lubbock_fail0:
if (gpio_is_valid(dev->mach->gpio_pullup))
gpio_free(dev->mach->gpio_pullup);
err_gpio_pullup:
- if (dev->transceiver) {
- usb_put_transceiver(dev->transceiver);
+ if (!IS_ERR_OR_NULL(dev->transceiver)) {
+ usb_put_phy(dev->transceiver);
dev->transceiver = NULL;
}
clk_put(dev->clk);
@@ -2279,8 +2280,8 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
clk_put(dev->clk);
- if (dev->transceiver) {
- usb_put_transceiver(dev->transceiver);
+ if (!IS_ERR_OR_NULL(dev->transceiver)) {
+ usb_put_phy(dev->transceiver);
dev->transceiver = NULL;
}
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 98acb3ab9e1..644b4305cb9 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/list.h>
@@ -1573,7 +1574,7 @@ static int should_enable_udc(struct pxa_udc *udc)
int put_on;
put_on = ((udc->pullup_on) && (udc->driver));
- put_on &= ((udc->vbus_sensed) || (!udc->transceiver));
+ put_on &= ((udc->vbus_sensed) || (IS_ERR_OR_NULL(udc->transceiver)));
return put_on;
}
@@ -1594,7 +1595,7 @@ static int should_disable_udc(struct pxa_udc *udc)
int put_off;
put_off = ((!udc->pullup_on) || (!udc->driver));
- put_off |= ((!udc->vbus_sensed) && (udc->transceiver));
+ put_off |= ((!udc->vbus_sensed) && (!IS_ERR_OR_NULL(udc->transceiver)));
return put_off;
}
@@ -1665,7 +1666,7 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
struct pxa_udc *udc;
udc = to_gadget_udc(_gadget);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -EOPNOTSUPP;
}
@@ -1834,7 +1835,7 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver,
dev_dbg(udc->dev, "registered gadget driver '%s'\n",
driver->driver.name);
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval) {
@@ -1908,7 +1909,7 @@ static int pxa27x_udc_stop(struct usb_gadget_driver *driver)
dev_info(udc->dev, "unregistered gadget driver '%s'\n",
driver->driver.name);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return otg_set_peripheral(udc->transceiver->otg, NULL);
return 0;
}
@@ -2464,7 +2465,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
udc->dev = &pdev->dev;
udc->mach = pdev->dev.platform_data;
- udc->transceiver = usb_get_transceiver();
+ udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
gpio = udc->mach->gpio_pullup;
if (gpio_is_valid(gpio)) {
@@ -2543,7 +2544,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev)
if (gpio_is_valid(gpio))
gpio_free(gpio);
- usb_put_transceiver(udc->transceiver);
+ usb_put_phy(udc->transceiver);
udc->transceiver = NULL;
platform_set_drvdata(_dev, NULL);
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index 236b271871a..e26a4e7ed2b 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -24,6 +24,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
@@ -1165,7 +1166,7 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,
}
/* connect to bus through transceiver */
- if (hsudc->transceiver) {
+ if (!IS_ERR_OR_NULL(hsudc->transceiver)) {
ret = otg_set_peripheral(hsudc->transceiver->otg,
&hsudc->gadget);
if (ret) {
@@ -1220,7 +1221,7 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget,
s3c_hsudc_stop_activity(hsudc);
spin_unlock_irqrestore(&hsudc->lock, flags);
- if (hsudc->transceiver)
+ if (!IS_ERR_OR_NULL(hsudc->transceiver))
(void) otg_set_peripheral(hsudc->transceiver->otg, NULL);
disable_irq(hsudc->irq);
@@ -1249,7 +1250,7 @@ static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA)
if (!hsudc)
return -ENODEV;
- if (hsudc->transceiver)
+ if (!IS_ERR_OR_NULL(hsudc->transceiver))
return usb_phy_set_power(hsudc->transceiver, mA);
return -EOPNOTSUPP;
@@ -1282,7 +1283,7 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev)
hsudc->dev = dev;
hsudc->pd = pdev->dev.platform_data;
- hsudc->transceiver = usb_get_transceiver();
+ 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];
@@ -1385,8 +1386,8 @@ err_irq:
err_remap:
release_mem_region(res->start, resource_size(res));
err_res:
- if (hsudc->transceiver)
- usb_put_transceiver(hsudc->transceiver);
+ if (!IS_ERR_OR_NULL(hsudc->transceiver))
+ usb_put_phy(hsudc->transceiver);
regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
err_supplies:
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 3379945b095..74914de8b9b 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -27,6 +27,7 @@
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/pm.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
@@ -142,15 +143,15 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
if (pdata->operating_mode == FSL_USB2_DR_OTG) {
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- hcd->phy = usb_get_transceiver();
+ hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2);
dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, phy=0x%p\n",
hcd, ehci, hcd->phy);
- if (hcd->phy) {
+ if (!IS_ERR_OR_NULL(hcd->phy)) {
retval = otg_set_host(hcd->phy->otg,
&ehci_to_hcd(ehci)->self);
if (retval) {
- usb_put_transceiver(hcd->phy);
+ usb_put_phy(hcd->phy);
goto err4;
}
} else {
@@ -191,9 +192,9 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
- if (hcd->phy) {
+ if (!IS_ERR_OR_NULL(hcd->phy)) {
otg_set_host(hcd->phy->otg, NULL);
- usb_put_transceiver(hcd->phy);
+ usb_put_phy(hcd->phy);
}
usb_remove_hcd(hcd);
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 9803a55fd5f..6b4ffb598db 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -145,8 +145,8 @@ static int ehci_msm_probe(struct platform_device *pdev)
* powering up VBUS, mapping of registers address space and power
* management.
*/
- phy = usb_get_transceiver();
- if (!phy) {
+ phy = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(phy)) {
dev_err(&pdev->dev, "unable to find transceiver\n");
ret = -ENODEV;
goto unmap;
@@ -169,7 +169,7 @@ static int ehci_msm_probe(struct platform_device *pdev)
return 0;
put_transceiver:
- usb_put_transceiver(phy);
+ usb_put_phy(phy);
unmap:
iounmap(hcd->regs);
put_hcd:
@@ -187,7 +187,7 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev)
pm_runtime_set_suspended(&pdev->dev);
otg_set_host(phy->otg, NULL);
- usb_put_transceiver(phy);
+ usb_put_phy(phy);
usb_put_hcd(hcd);
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index a936bbcff8f..0e8c168ca24 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/usb/otg.h>
#include <linux/platform_data/mv_usb.h>
@@ -253,8 +254,8 @@ static int mv_ehci_probe(struct platform_device *pdev)
ehci_mv->mode = pdata->mode;
if (ehci_mv->mode == MV_USB_MODE_OTG) {
#ifdef CONFIG_USB_OTG_UTILS
- ehci_mv->otg = usb_get_transceiver();
- if (!ehci_mv->otg) {
+ ehci_mv->otg = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(ehci_mv->otg)) {
dev_err(&pdev->dev,
"unable to find transceiver\n");
retval = -ENODEV;
@@ -302,8 +303,8 @@ err_set_vbus:
pdata->set_vbus(0);
#ifdef CONFIG_USB_OTG_UTILS
err_put_transceiver:
- if (ehci_mv->otg)
- usb_put_transceiver(ehci_mv->otg);
+ if (!IS_ERR_OR_NULL(ehci_mv->otg))
+ usb_put_phy(ehci_mv->otg);
#endif
err_disable_clk:
mv_ehci_disable(ehci_mv);
@@ -331,9 +332,9 @@ static int mv_ehci_remove(struct platform_device *pdev)
if (hcd->rh_registered)
usb_remove_hcd(hcd);
- if (ehci_mv->otg) {
+ if (!IS_ERR_OR_NULL(ehci_mv->otg)) {
otg_set_host(ehci_mv->otg->otg, NULL);
- usb_put_transceiver(ehci_mv->otg);
+ usb_put_phy(ehci_mv->otg);
}
if (ehci_mv->mode == MV_USB_MODE_HOST) {
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 68548236ec4..477ecfa0515 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -17,6 +17,7 @@
*/
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/platform_data/tegra_usb.h>
#include <linux/irq.h>
@@ -749,8 +750,8 @@ static int tegra_ehci_probe(struct platform_device *pdev)
#ifdef CONFIG_USB_OTG_UTILS
if (pdata->operating_mode == TEGRA_USB_OTG) {
- tegra->transceiver = usb_get_transceiver();
- if (tegra->transceiver)
+ tegra->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (!IS_ERR_OR_NULL(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, &hcd->self);
}
#endif
@@ -773,9 +774,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
fail:
#ifdef CONFIG_USB_OTG_UTILS
- if (tegra->transceiver) {
+ if (!IS_ERR_OR_NULL(tegra->transceiver)) {
otg_set_host(tegra->transceiver->otg, NULL);
- usb_put_transceiver(tegra->transceiver);
+ usb_put_phy(tegra->transceiver);
}
#endif
tegra_usb_phy_close(tegra->phy);
@@ -808,9 +809,9 @@ static int tegra_ehci_remove(struct platform_device *pdev)
pm_runtime_put_noidle(&pdev->dev);
#ifdef CONFIG_USB_OTG_UTILS
- if (tegra->transceiver) {
+ if (!IS_ERR_OR_NULL(tegra->transceiver)) {
otg_set_host(tegra->transceiver->otg, NULL);
- usb_put_transceiver(tegra->transceiver);
+ usb_put_phy(tegra->transceiver);
}
#endif
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index eccddb46139..076d2018e6d 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -18,6 +18,7 @@
#include <linux/jiffies.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
@@ -212,14 +213,14 @@ static int ohci_omap_init(struct usb_hcd *hcd)
#ifdef CONFIG_USB_OTG
if (need_transceiver) {
- hcd->phy = usb_get_transceiver();
- if (hcd->phy) {
+ hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (!IS_ERR_OR_NULL(hcd->phy)) {
int status = otg_set_host(hcd->phy->otg,
&ohci_to_hcd(ohci)->self);
dev_dbg(hcd->self.controller, "init %s phy, status %d\n",
hcd->phy->label, status);
if (status) {
- usb_put_transceiver(hcd->phy);
+ usb_put_phy(hcd->phy);
return status;
}
} else {
@@ -404,9 +405,9 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
usb_remove_hcd(hcd);
- if (hcd->phy) {
+ if (!IS_ERR_OR_NULL(hcd->phy)) {
(void) otg_set_host(hcd->phy->otg, 0);
- usb_put_transceiver(hcd->phy);
+ usb_put_phy(hcd->phy);
}
if (machine_is_omap_osk())
gpio_free(9);
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index 9f3eda91ea4..7a95ab87ac0 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -29,6 +29,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
@@ -364,8 +365,8 @@ static int am35x_musb_init(struct musb *musb)
return -ENODEV;
usb_nop_xceiv_register();
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv)
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV;
if (is_host_enabled(musb))
@@ -406,7 +407,7 @@ static int am35x_musb_exit(struct musb *musb)
if (data->set_phy_power)
data->set_phy_power(0);
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index a087ed6c3be..428e6aa3e78 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/gpio.h>
#include <linux/io.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/prefetch.h>
@@ -415,8 +416,8 @@ static int bfin_musb_init(struct musb *musb)
gpio_direction_output(musb->config->gpio_vrsel, 0);
usb_nop_xceiv_register();
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv) {
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv)) {
gpio_free(musb->config->gpio_vrsel);
return -ENODEV;
}
@@ -440,7 +441,7 @@ static int bfin_musb_exit(struct musb *musb)
{
gpio_free(musb->config->gpio_vrsel);
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
}
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 8bd9566f3fb..0f9fcec4e1d 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -29,6 +29,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
@@ -425,8 +426,8 @@ static int da8xx_musb_init(struct musb *musb)
goto fail;
usb_nop_xceiv_register();
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv)
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv))
goto fail;
if (is_host_enabled(musb))
@@ -458,7 +459,7 @@ static int da8xx_musb_exit(struct musb *musb)
phy_off();
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 9d63ba4d10d..472c8b42d38 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -28,6 +28,7 @@
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
@@ -385,8 +386,8 @@ static int davinci_musb_init(struct musb *musb)
u32 revision;
usb_nop_xceiv_register();
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv)
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv))
goto unregister;
musb->mregs += DAVINCI_BASE_OFFSET;
@@ -444,7 +445,7 @@ static int davinci_musb_init(struct musb *musb)
return 0;
fail:
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
unregister:
usb_nop_xceiv_unregister();
return -ENODEV;
@@ -494,7 +495,7 @@ static int davinci_musb_exit(struct musb *musb)
phy_off();
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index db3dff854b7..26f1befb489 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -1909,7 +1909,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
/* The musb_platform_init() call:
* - adjusts musb->mregs and musb->isr if needed,
* - may initialize an integrated tranceiver
- * - initializes musb->xceiv, usually by otg_get_transceiver()
+ * - initializes musb->xceiv, usually by otg_get_phy()
* - stops powering VBUS
*
* There are various transceiver configurations. Blackfin,
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index f4a40f001c8..dbcdeea30f0 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -327,7 +327,6 @@ struct musb {
irqreturn_t (*isr)(int, void *);
struct work_struct irq_work;
- struct work_struct otg_notifier_work;
u16 hwvers;
/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
@@ -373,7 +372,6 @@ struct musb {
u16 int_tx;
struct usb_phy *xceiv;
- u8 xceiv_event;
int nIrq;
unsigned irq_wake:1;
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 23db42db761..217808d9fbe 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -31,6 +31,7 @@
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
@@ -376,8 +377,8 @@ static int dsps_musb_init(struct musb *musb)
/* NOP driver needs change if supporting dual instance */
usb_nop_xceiv_register();
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv)
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV;
/* Returns zero if e.g. not clocked */
@@ -409,7 +410,7 @@ static int dsps_musb_init(struct musb *musb)
return 0;
err0:
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return status;
}
@@ -430,7 +431,7 @@ static int dsps_musb_exit(struct musb *musb)
data->set_phy_power(0);
/* NOP driver needs change if supporting dual instance */
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index c7785e81254..5fdb9da8dd5 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -34,6 +34,7 @@
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/err.h>
+#include <linux/usb/musb-omap.h>
#include "musb_core.h"
#include "omap2430.h"
@@ -41,9 +42,13 @@
struct omap2430_glue {
struct device *dev;
struct platform_device *musb;
+ enum omap_musb_vbus_id_status status;
+ struct work_struct omap_musb_mailbox_work;
};
#define glue_to_musb(g) platform_get_drvdata(g->musb)
+struct omap2430_glue *_glue;
+
static struct timer_list musb_idle_timer;
static void musb_do_idle(unsigned long _musb)
@@ -223,50 +228,63 @@ static inline void omap2430_low_level_init(struct musb *musb)
musb_writel(musb->mregs, OTG_FORCESTDBY, l);
}
-static int musb_otg_notifications(struct notifier_block *nb,
- unsigned long event, void *unused)
+void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
{
- struct musb *musb = container_of(nb, struct musb, nb);
+ struct omap2430_glue *glue = _glue;
+ struct musb *musb = glue_to_musb(glue);
- musb->xceiv_event = event;
- schedule_work(&musb->otg_notifier_work);
+ glue->status = status;
+ if (!musb) {
+ dev_err(glue->dev, "musb core is not yet ready\n");
+ return;
+ }
- return NOTIFY_OK;
+ schedule_work(&glue->omap_musb_mailbox_work);
}
+EXPORT_SYMBOL_GPL(omap_musb_mailbox);
-static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
+static void omap_musb_set_mailbox(struct omap2430_glue *glue)
{
- struct musb *musb = container_of(data_notifier_work, struct musb, otg_notifier_work);
+ struct musb *musb = glue_to_musb(glue);
struct device *dev = musb->controller;
struct musb_hdrc_platform_data *pdata = dev->platform_data;
struct omap_musb_board_data *data = pdata->board_data;
+ struct usb_otg *otg = musb->xceiv->otg;
- switch (musb->xceiv_event) {
- case USB_EVENT_ID:
- dev_dbg(musb->controller, "ID GND\n");
+ switch (glue->status) {
+ case OMAP_MUSB_ID_GROUND:
+ dev_dbg(dev, "ID GND\n");
+ otg->default_a = true;
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->last_event = USB_EVENT_ID;
if (!is_otg_enabled(musb) || musb->gadget_driver) {
- pm_runtime_get_sync(musb->controller);
+ pm_runtime_get_sync(dev);
usb_phy_init(musb->xceiv);
omap2430_musb_set_vbus(musb, 1);
}
break;
- case USB_EVENT_VBUS:
- dev_dbg(musb->controller, "VBUS Connect\n");
+ case OMAP_MUSB_VBUS_VALID:
+ dev_dbg(dev, "VBUS Connect\n");
+ otg->default_a = false;
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->last_event = USB_EVENT_VBUS;
if (musb->gadget_driver)
- pm_runtime_get_sync(musb->controller);
+ pm_runtime_get_sync(dev);
usb_phy_init(musb->xceiv);
break;
- case USB_EVENT_NONE:
- dev_dbg(musb->controller, "VBUS Disconnect\n");
+ case OMAP_MUSB_ID_FLOAT:
+ case OMAP_MUSB_VBUS_OFF:
+ dev_dbg(dev, "VBUS Disconnect\n");
+ musb->xceiv->last_event = USB_EVENT_NONE;
if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
if (musb->gadget_driver) {
- pm_runtime_mark_last_busy(musb->controller);
- pm_runtime_put_autosuspend(musb->controller);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
}
if (data->interface_type == MUSB_INTERFACE_UTMI) {
@@ -276,15 +294,24 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
usb_phy_shutdown(musb->xceiv);
break;
default:
- dev_dbg(musb->controller, "ID float\n");
+ dev_dbg(dev, "ID float\n");
}
}
+
+static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
+{
+ struct omap2430_glue *glue = container_of(mailbox_work,
+ struct omap2430_glue, omap_musb_mailbox_work);
+ omap_musb_set_mailbox(glue);
+}
+
static int omap2430_musb_init(struct musb *musb)
{
u32 l;
int status = 0;
struct device *dev = musb->controller;
+ struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct omap_musb_board_data *data = plat->board_data;
@@ -292,14 +319,12 @@ static int omap2430_musb_init(struct musb *musb)
* up through ULPI. TWL4030-family PMICs include one,
* which needs a driver, drivers aren't always needed.
*/
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv) {
+ musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv)) {
pr_err("HS USB OTG: no transceiver configured\n");
return -ENODEV;
}
- INIT_WORK(&musb->otg_notifier_work, musb_otg_notifier_work);
-
status = pm_runtime_get_sync(dev);
if (status < 0) {
dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
@@ -326,14 +351,11 @@ static int omap2430_musb_init(struct musb *musb)
musb_readl(musb->mregs, OTG_INTERFSEL),
musb_readl(musb->mregs, OTG_SIMENABLE));
- musb->nb.notifier_call = musb_otg_notifications;
- status = usb_register_notifier(musb->xceiv, &musb->nb);
-
- if (status)
- dev_dbg(musb->controller, "notification register failed\n");
-
setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
+ if (glue->status != OMAP_MUSB_UNKNOWN)
+ omap_musb_set_mailbox(glue);
+
pm_runtime_put_noidle(musb->controller);
return 0;
@@ -346,12 +368,13 @@ static void omap2430_musb_enable(struct musb *musb)
u8 devctl;
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
struct device *dev = musb->controller;
+ struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
struct musb_hdrc_platform_data *pdata = dev->platform_data;
struct omap_musb_board_data *data = pdata->board_data;
- switch (musb->xceiv->last_event) {
+ switch (glue->status) {
- case USB_EVENT_ID:
+ case OMAP_MUSB_ID_GROUND:
usb_phy_init(musb->xceiv);
if (data->interface_type != MUSB_INTERFACE_UTMI)
break;
@@ -370,7 +393,7 @@ static void omap2430_musb_enable(struct musb *musb)
}
break;
- case USB_EVENT_VBUS:
+ case OMAP_MUSB_VBUS_VALID:
usb_phy_init(musb->xceiv);
break;
@@ -381,17 +404,18 @@ static void omap2430_musb_enable(struct musb *musb)
static void omap2430_musb_disable(struct musb *musb)
{
- if (musb->xceiv->last_event)
+ struct device *dev = musb->controller;
+ struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
+
+ if (glue->status != OMAP_MUSB_UNKNOWN)
usb_phy_shutdown(musb->xceiv);
}
static int omap2430_musb_exit(struct musb *musb)
{
del_timer_sync(&musb_idle_timer);
- cancel_work_sync(&musb->otg_notifier_work);
omap2430_low_level_exit(musb);
- usb_put_transceiver(musb->xceiv);
return 0;
}
@@ -418,7 +442,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
struct omap2430_glue *glue;
int ret = -ENOMEM;
- glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+ glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
if (!glue) {
dev_err(&pdev->dev, "failed to allocate glue context\n");
goto err0;
@@ -427,7 +451,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
musb = platform_device_alloc("musb-hdrc", -1);
if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n");
- goto err1;
+ goto err0;
}
musb->dev.parent = &pdev->dev;
@@ -436,22 +460,31 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
glue->dev = &pdev->dev;
glue->musb = musb;
+ glue->status = OMAP_MUSB_UNKNOWN;
pdata->platform_ops = &omap2430_ops;
platform_set_drvdata(pdev, glue);
+ /*
+ * REVISIT if we ever have two instances of the wrapper, we will be
+ * in big trouble
+ */
+ _glue = glue;
+
+ INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
+
ret = platform_device_add_resources(musb, pdev->resource,
pdev->num_resources);
if (ret) {
dev_err(&pdev->dev, "failed to add resources\n");
- goto err2;
+ goto err1;
}
ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
if (ret) {
dev_err(&pdev->dev, "failed to add platform_data\n");
- goto err2;
+ goto err1;
}
pm_runtime_enable(&pdev->dev);
@@ -459,16 +492,13 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
ret = platform_device_add(musb);
if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n");
- goto err2;
+ goto err1;
}
return 0;
-err2:
- platform_device_put(musb);
-
err1:
- kfree(glue);
+ platform_device_put(musb);
err0:
return ret;
@@ -478,9 +508,9 @@ static int __devexit omap2430_remove(struct platform_device *pdev)
{
struct omap2430_glue *glue = platform_get_drvdata(pdev);
+ cancel_work_sync(&glue->omap_musb_mailbox_work);
platform_device_del(glue->musb);
platform_device_put(glue->musb);
- kfree(glue);
return 0;
}
@@ -546,7 +576,7 @@ static int __init omap2430_init(void)
{
return platform_driver_register(&omap2430_driver);
}
-module_init(omap2430_init);
+subsys_initcall(omap2430_init);
static void __exit omap2430_exit(void)
{
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index de1355946a8..1a1bd9cf40c 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/prefetch.h>
#include <linux/usb.h>
@@ -1078,8 +1079,8 @@ static int tusb_musb_init(struct musb *musb)
int ret;
usb_nop_xceiv_register();
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv)
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV;
pdev = to_platform_device(musb->controller);
@@ -1130,7 +1131,7 @@ done:
if (sync)
iounmap(sync);
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
}
return ret;
@@ -1146,7 +1147,7 @@ static int tusb_musb_exit(struct musb *musb)
iounmap(musb->sync_va);
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
}
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index aa09dd417b9..a8c0fadce1b 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
@@ -37,8 +38,8 @@ struct ux500_glue {
static int ux500_musb_init(struct musb *musb)
{
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv) {
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv)) {
pr_err("HS USB OTG: no transceiver configured\n");
return -ENODEV;
}
@@ -48,7 +49,7 @@ static int ux500_musb_init(struct musb *musb)
static int ux500_musb_exit(struct musb *musb)
{
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
return 0;
}
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
index a84af677dc5..ae8ad561f08 100644
--- a/drivers/usb/otg/ab8500-usb.c
+++ b/drivers/usb/otg/ab8500-usb.c
@@ -529,7 +529,7 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev)
if (err < 0)
goto fail0;
- err = usb_set_transceiver(&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 @@ static int __devexit ab8500_usb_remove(struct platform_device *pdev)
cancel_work_sync(&ab->phy_dis_work);
- usb_set_transceiver(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 be4a63e8302..23c798cb2d7 100644
--- a/drivers/usb/otg/fsl_otg.c
+++ b/drivers/usb/otg/fsl_otg.c
@@ -806,7 +806,7 @@ static int fsl_otg_conf(struct platform_device *pdev)
fsl_otg_dev = fsl_otg_tc;
/* Store the otg transceiver */
- status = usb_set_transceiver(&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 @@ err:
int usb_otg_start(struct platform_device *pdev)
{
struct fsl_otg *p_otg;
- struct usb_phy *otg_trans = usb_get_transceiver();
+ 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 @@ static int __devexit fsl_otg_remove(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
- usb_set_transceiver(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 bde6298a969..a67ffe22179 100644
--- a/drivers/usb/otg/gpio_vbus.c
+++ b/drivers/usb/otg/gpio_vbus.c
@@ -320,7 +320,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
}
/* only active when a gadget is registered */
- err = usb_set_transceiver(&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 @@ static int __exit gpio_vbus_remove(struct platform_device *pdev)
cancel_delayed_work_sync(&gpio_vbus->work);
regulator_put(gpio_vbus->vbus_draw);
- usb_set_transceiver(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 70cf5d7bca4..75cea4ab098 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/otg/isp1301_omap.c
@@ -1336,9 +1336,6 @@ static int
isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
{
struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy);
-#ifndef CONFIG_USB_OTG
- u32 l;
-#endif
if (!otg || isp != the_transceiver)
return -ENODEV;
@@ -1365,10 +1362,14 @@ isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
otg->gadget = gadget;
// FIXME update its refcount
- l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
- l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS);
- l |= OTG_ID;
- omap_writel(l, OTG_CTRL);
+ {
+ u32 l;
+
+ l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
+ l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS);
+ l |= OTG_ID;
+ omap_writel(l, OTG_CTRL);
+ }
power_up(isp);
isp->phy.state = OTG_STATE_B_IDLE;
@@ -1610,7 +1611,7 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
#endif
- status = usb_set_transceiver(&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);
@@ -1649,7 +1650,7 @@ subsys_initcall(isp_init);
static void __exit isp_exit(void)
{
if (the_transceiver)
- usb_set_transceiver(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 1d0347c247d..9f5fc906041 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1555,9 +1555,9 @@ static int __init msm_otg_probe(struct platform_device *pdev)
phy->otg->set_host = msm_otg_set_host;
phy->otg->set_peripheral = msm_otg_set_peripheral;
- ret = usb_set_transceiver(&motg->phy);
+ ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2);
if (ret) {
- dev_err(&pdev->dev, "usb_set_transceiver failed\n");
+ dev_err(&pdev->dev, "usb_add_phy failed\n");
goto free_irq;
}
@@ -1624,7 +1624,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 0);
pm_runtime_disable(&pdev->dev);
- usb_set_transceiver(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 6cc6c3ffbb8..3f124e8f579 100644
--- a/drivers/usb/otg/mv_otg.c
+++ b/drivers/usb/otg/mv_otg.c
@@ -690,7 +690,7 @@ int mv_otg_remove(struct platform_device *pdev)
for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++)
clk_put(mvotg->clk[clk_i]);
- usb_set_transceiver(NULL);
+ usb_remove_phy(&mvotg->phy);
platform_set_drvdata(pdev, NULL);
kfree(mvotg->phy.otg);
@@ -853,7 +853,7 @@ static int mv_otg_probe(struct platform_device *pdev)
goto err_disable_clk;
}
- retval = usb_set_transceiver(&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 @@ static int mv_otg_probe(struct platform_device *pdev)
return 0;
err_set_transceiver:
- usb_set_transceiver(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 58b26df6afd..803f958f413 100644
--- a/drivers/usb/otg/nop-usb-xceiv.c
+++ b/drivers/usb/otg/nop-usb-xceiv.c
@@ -117,7 +117,7 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev)
nop->phy.otg->set_host = nop_set_host;
nop->phy.otg->set_peripheral = nop_set_peripheral;
- err = usb_set_transceiver(&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 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
{
struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
- usb_set_transceiver(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 801e597a154..1bf60a22595 100644
--- a/drivers/usb/otg/otg.c
+++ b/drivers/usb/otg/otg.c
@@ -11,60 +11,195 @@
#include <linux/kernel.h>
#include <linux/export.h>
+#include <linux/err.h>
#include <linux/device.h>
+#include <linux/slab.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);
+}
+
+static void devm_usb_phy_release(struct device *dev, void *res)
+{
+ struct usb_phy *phy = *(struct usb_phy **)res;
+
+ usb_put_phy(phy);
+}
+
+static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
+{
+ return res == match_data;
+}
/**
- * usb_get_transceiver - find the (single) USB transceiver
+ * devm_usb_get_phy - find the USB PHY
+ * @dev - device that requests this phy
+ * @type - the type of the phy the controller requires
*
- * Returns the transceiver driver, after getting a refcount to it; or
- * null if there is no such transceiver. The caller is responsible for
- * calling usb_put_transceiver() to release that count.
+ * Gets the phy using usb_get_phy(), and associates a device with it using
+ * devres. On driver detach, release function is invoked on the devres data,
+ * then, devres data is freed.
*
* For use by USB host and peripheral drivers.
*/
-struct usb_phy *usb_get_transceiver(void)
+struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type)
{
- if (phy)
- get_device(phy->dev);
+ struct usb_phy **ptr, *phy;
+
+ ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return NULL;
+
+ phy = usb_get_phy(type);
+ if (!IS_ERR(phy)) {
+ *ptr = phy;
+ devres_add(dev, ptr);
+ } else
+ devres_free(ptr);
+
+ return phy;
+}
+EXPORT_SYMBOL(devm_usb_get_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
+ * -ENODEV if there is no such phy. The caller is responsible for
+ * calling usb_put_phy() to release that count.
+ *
+ * For use by USB host and peripheral drivers.
+ */
+struct usb_phy *usb_get_phy(enum usb_phy_type type)
+{
+ 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));
+ goto err0;
+ }
+
+ get_device(phy->dev);
+
+err0:
+ spin_unlock_irqrestore(&phy_lock, flags);
+
return phy;
}
-EXPORT_SYMBOL(usb_get_transceiver);
+EXPORT_SYMBOL(usb_get_phy);
+
+/**
+ * devm_usb_put_phy - release the USB PHY
+ * @dev - device that wants to release this phy
+ * @phy - the phy returned by devm_usb_get_phy()
+ *
+ * destroys the devres associated with this phy and invokes usb_put_phy
+ * to release the phy.
+ *
+ * For use by USB host and peripheral drivers.
+ */
+void devm_usb_put_phy(struct device *dev, struct usb_phy *phy)
+{
+ int r;
+
+ r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy);
+ dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
+}
+EXPORT_SYMBOL(devm_usb_put_phy);
/**
- * usb_put_transceiver - release the (single) USB transceiver
- * @x: the transceiver returned by usb_get_transceiver()
+ * usb_put_phy - release the USB PHY
+ * @x: the phy returned by usb_get_phy()
*
- * Releases a refcount the caller received from usb_get_transceiver().
+ * Releases a refcount the caller received from usb_get_phy().
*
* For use by USB host and peripheral drivers.
*/
-void usb_put_transceiver(struct usb_phy *x)
+void usb_put_phy(struct usb_phy *x)
{
if (x)
put_device(x->dev);
}
-EXPORT_SYMBOL(usb_put_transceiver);
+EXPORT_SYMBOL(usb_put_phy);
/**
- * usb_set_transceiver - declare the (single) USB transceiver
- * @x: the USB transceiver to be used; or NULL
+ * 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 transceiver drivers, which
+ * 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_set_transceiver(struct usb_phy *x)
+int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
+{
+ 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)
{
- if (phy && x)
- return -EBUSY;
- phy = x;
- return 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&phy_lock, flags);
+ if (x)
+ list_del(&x->head);
+ spin_unlock_irqrestore(&phy_lock, flags);
}
-EXPORT_SYMBOL(usb_set_transceiver);
+EXPORT_SYMBOL(usb_remove_phy);
const char *otg_state_string(enum usb_otg_state state)
{
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index c4a86da858e..523cad5bfea 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -33,11 +33,11 @@
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/usb/otg.h>
+#include <linux/usb/musb-omap.h>
#include <linux/usb/ulpi.h>
#include <linux/i2c/twl.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
-#include <linux/notifier.h>
#include <linux/slab.h>
/* Register defines */
@@ -159,7 +159,7 @@ struct twl4030_usb {
enum twl4030_usb_mode usb_mode;
int irq;
- u8 linkstat;
+ enum omap_musb_vbus_id_status linkstat;
bool vbus_supplied;
u8 asleep;
bool irq_enabled;
@@ -246,11 +246,11 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
/*-------------------------------------------------------------------------*/
-static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
+static enum omap_musb_vbus_id_status
+ twl4030_usb_linkstat(struct twl4030_usb *twl)
{
int status;
- int linkstat = USB_EVENT_NONE;
- struct usb_otg *otg = twl->phy.otg;
+ enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN;
twl->vbus_supplied = false;
@@ -273,30 +273,23 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
twl->vbus_supplied = true;
if (status & BIT(2))
- linkstat = USB_EVENT_ID;
+ linkstat = OMAP_MUSB_ID_GROUND;
else
- linkstat = USB_EVENT_VBUS;
- } else
- linkstat = USB_EVENT_NONE;
+ linkstat = OMAP_MUSB_VBUS_VALID;
+ } else {
+ if (twl->linkstat != OMAP_MUSB_UNKNOWN)
+ linkstat = OMAP_MUSB_VBUS_OFF;
+ }
dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
status, status, linkstat);
- twl->phy.last_event = linkstat;
-
/* REVISIT this assumes host and peripheral controllers
* are registered, and that both are active...
*/
spin_lock_irq(&twl->lock);
twl->linkstat = linkstat;
- if (linkstat == USB_EVENT_ID) {
- otg->default_a = true;
- twl->phy.state = OTG_STATE_A_IDLE;
- } else {
- otg->default_a = false;
- twl->phy.state = OTG_STATE_B_IDLE;
- }
spin_unlock_irq(&twl->lock);
return linkstat;
@@ -501,10 +494,10 @@ static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL);
static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
{
struct twl4030_usb *twl = _twl;
- int status;
+ enum omap_musb_vbus_id_status status;
status = twl4030_usb_linkstat(twl);
- if (status >= 0) {
+ if (status > 0) {
/* FIXME add a set_power() method so that B-devices can
* configure the charger appropriately. It's not always
* correct to consume VBUS power, and how much current to
@@ -516,13 +509,13 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
* USB_LINK_VBUS state. musb_hdrc won't care until it
* starts to handle softconnect right.
*/
- if (status == USB_EVENT_NONE)
+ if (status == OMAP_MUSB_VBUS_OFF ||
+ status == OMAP_MUSB_ID_FLOAT)
twl4030_phy_suspend(twl, 0);
else
twl4030_phy_resume(twl);
- atomic_notifier_call_chain(&twl->phy.notifier, status,
- twl->phy.otg->gadget);
+ omap_musb_mailbox(twl->linkstat);
}
sysfs_notify(&twl->dev->kobj, NULL, "vbus");
@@ -531,11 +524,12 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
static void twl4030_usb_phy_init(struct twl4030_usb *twl)
{
- int status;
+ enum omap_musb_vbus_id_status status;
status = twl4030_usb_linkstat(twl);
- if (status >= 0) {
- if (status == USB_EVENT_NONE) {
+ if (status > 0) {
+ if (status == OMAP_MUSB_VBUS_OFF ||
+ status == OMAP_MUSB_ID_FLOAT) {
__twl4030_phy_power(twl, 0);
twl->asleep = 1;
} else {
@@ -543,8 +537,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl)
twl->asleep = 0;
}
- atomic_notifier_call_chain(&twl->phy.notifier, status,
- twl->phy.otg->gadget);
+ omap_musb_mailbox(twl->linkstat);
}
sysfs_notify(&twl->dev->kobj, NULL, "vbus");
}
@@ -598,21 +591,20 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
return -EINVAL;
}
- twl = kzalloc(sizeof *twl, GFP_KERNEL);
+ twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL);
if (!twl)
return -ENOMEM;
- otg = kzalloc(sizeof *otg, GFP_KERNEL);
- if (!otg) {
- kfree(twl);
+ 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;
twl->phy.dev = twl->dev;
twl->phy.label = "twl4030";
@@ -629,18 +621,14 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
err = twl4030_usb_ldo_init(twl);
if (err) {
dev_err(&pdev->dev, "ldo init failed\n");
- kfree(otg);
- kfree(twl);
return err;
}
- usb_set_transceiver(&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))
dev_warn(&pdev->dev, "could not create sysfs file\n");
- ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
-
/* Our job is to use irqs and status from the power module
* to keep the transceiver disabled when nothing's connected.
*
@@ -651,13 +639,11 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
*/
twl->irq_enabled = true;
status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- "twl4030_usb", twl);
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT, "twl4030_usb", twl);
if (status < 0) {
dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
twl->irq, status);
- kfree(otg);
- kfree(twl);
return status;
}
@@ -701,9 +687,6 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev)
regulator_put(twl->usb1v8);
regulator_put(twl->usb3v1);
- kfree(twl->phy.otg);
- kfree(twl);
-
return 0;
}
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index 0eabb049b6a..a3d0c0405cc 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -26,10 +26,10 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/usb/otg.h>
+#include <linux/usb/musb-omap.h>
#include <linux/i2c/twl.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
-#include <linux/notifier.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -100,7 +100,7 @@ struct twl6030_usb {
int irq1;
int irq2;
- u8 linkstat;
+ enum omap_musb_vbus_id_status linkstat;
u8 asleep;
bool irq_enabled;
bool vbus_enable;
@@ -147,7 +147,7 @@ static int twl6030_phy_init(struct usb_phy *x)
dev = twl->dev;
pdata = dev->platform_data;
- if (twl->linkstat == USB_EVENT_ID)
+ if (twl->linkstat == OMAP_MUSB_ID_GROUND)
pdata->phy_power(twl->dev, 1, 1);
else
pdata->phy_power(twl->dev, 0, 1);
@@ -235,13 +235,13 @@ static ssize_t twl6030_usb_vbus_show(struct device *dev,
spin_lock_irqsave(&twl->lock, flags);
switch (twl->linkstat) {
- case USB_EVENT_VBUS:
+ case OMAP_MUSB_VBUS_VALID:
ret = snprintf(buf, PAGE_SIZE, "vbus\n");
break;
- case USB_EVENT_ID:
+ case OMAP_MUSB_ID_GROUND:
ret = snprintf(buf, PAGE_SIZE, "id\n");
break;
- case USB_EVENT_NONE:
+ case OMAP_MUSB_VBUS_OFF:
ret = snprintf(buf, PAGE_SIZE, "none\n");
break;
default:
@@ -256,8 +256,7 @@ static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
{
struct twl6030_usb *twl = _twl;
- struct usb_otg *otg = twl->phy.otg;
- int status;
+ enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
u8 vbus_state, hw_state;
hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@@ -268,22 +267,18 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
if (vbus_state & VBUS_DET) {
regulator_enable(twl->usb3v3);
twl->asleep = 1;
- status = USB_EVENT_VBUS;
- otg->default_a = false;
- twl->phy.state = OTG_STATE_B_IDLE;
+ status = OMAP_MUSB_VBUS_VALID;
twl->linkstat = status;
- twl->phy.last_event = status;
- atomic_notifier_call_chain(&twl->phy.notifier,
- status, otg->gadget);
+ omap_musb_mailbox(status);
} else {
- status = USB_EVENT_NONE;
- twl->linkstat = status;
- twl->phy.last_event = status;
- atomic_notifier_call_chain(&twl->phy.notifier,
- status, otg->gadget);
- if (twl->asleep) {
- regulator_disable(twl->usb3v3);
- twl->asleep = 0;
+ if (twl->linkstat != OMAP_MUSB_UNKNOWN) {
+ status = OMAP_MUSB_VBUS_OFF;
+ twl->linkstat = status;
+ omap_musb_mailbox(status);
+ if (twl->asleep) {
+ regulator_disable(twl->usb3v3);
+ twl->asleep = 0;
+ }
}
}
}
@@ -295,8 +290,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
{
struct twl6030_usb *twl = _twl;
- struct usb_otg *otg = twl->phy.otg;
- int status = USB_EVENT_NONE;
+ enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
u8 hw_state;
hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@@ -307,13 +301,11 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
twl->asleep = 1;
twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
- status = USB_EVENT_ID;
+ status = OMAP_MUSB_ID_GROUND;
otg->default_a = true;
twl->phy.state = OTG_STATE_A_IDLE;
twl->linkstat = status;
- twl->phy.last_event = status;
- atomic_notifier_call_chain(&twl->phy.notifier, status,
- otg->gadget);
+ omap_musb_mailbox(status);
} else {
twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
@@ -402,20 +394,19 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
pdata = dev->platform_data;
- twl = kzalloc(sizeof *twl, GFP_KERNEL);
+ twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL);
if (!twl)
return -ENOMEM;
- otg = kzalloc(sizeof *otg, GFP_KERNEL);
- if (!otg) {
- kfree(twl);
+ 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";
@@ -436,18 +427,14 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
err = twl6030_usb_ldo_init(twl);
if (err) {
dev_err(&pdev->dev, "ldo init failed\n");
- kfree(otg);
- kfree(twl);
return err;
}
- usb_set_transceiver(&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))
dev_warn(&pdev->dev, "could not create sysfs file\n");
- ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
-
INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
twl->irq_enabled = true;
@@ -458,8 +445,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
twl->irq1, status);
device_remove_file(twl->dev, &dev_attr_vbus);
- kfree(otg);
- kfree(twl);
return status;
}
@@ -471,8 +456,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
twl->irq2, status);
free_irq(twl->irq1, twl);
device_remove_file(twl->dev, &dev_attr_vbus);
- kfree(otg);
- kfree(twl);
return status;
}
@@ -503,8 +486,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev)
pdata->phy_exit(twl->dev);
device_remove_file(twl->dev, &dev_attr_vbus);
cancel_work_sync(&twl->set_vbus_work);
- kfree(twl->phy.otg);
- kfree(twl);
return 0;
}