diff options
author | Neil Zhang <zhangwm@marvell.com> | 2011-11-30 09:57:13 +0800 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2011-12-12 11:45:22 +0200 |
commit | 487d54d172b3afd3d2bf124b24eaf7f7e7b8a668 (patch) | |
tree | a2c5665ce64d902afea5508db90ab8de3093fe7d | |
parent | 9823a52539adce658f2414e33f2838b896ea4971 (diff) | |
download | linux-487d54d172b3afd3d2bf124b24eaf7f7e7b8a668.tar.gz linux-487d54d172b3afd3d2bf124b24eaf7f7e7b8a668.tar.bz2 linux-487d54d172b3afd3d2bf124b24eaf7f7e7b8a668.zip |
usb: gadget: mv_udc: add otg relative code
Add otg relative code, make it possible to switch between host and
device.
Signed-off-by: Neil Zhang <zhangwm@marvell.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r-- | drivers/usb/gadget/mv_udc.h | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/mv_udc_core.c | 33 |
2 files changed, 32 insertions, 3 deletions
diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h index daa75c12f336..b2c36ee3c82c 100644 --- a/drivers/usb/gadget/mv_udc.h +++ b/drivers/usb/gadget/mv_udc.h @@ -216,6 +216,8 @@ struct mv_udc { struct work_struct vbus_work; struct workqueue_struct *qwork; + struct otg_transceiver *transceiver; + struct mv_usb_platform_data *pdata; /* some SOC has mutiple clock sources for USB*/ diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 9376a7483c9b..647cc3ab1709 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -1407,6 +1407,20 @@ static int mv_udc_start(struct usb_gadget_driver *driver, return retval; } + if (udc->transceiver) { + retval = otg_set_peripheral(udc->transceiver, &udc->gadget); + if (retval) { + dev_err(&udc->dev->dev, + "unable to register peripheral to otg\n"); + if (driver->unbind) { + driver->unbind(&udc->gadget); + udc->gadget.dev.driver = NULL; + udc->driver = NULL; + } + return retval; + } + } + /* pullup is always on */ mv_udc_pullup(&udc->gadget, 1); @@ -2109,7 +2123,12 @@ static int __devexit mv_udc_remove(struct platform_device *dev) destroy_workqueue(udc->qwork); } - if (udc->pdata && udc->pdata->vbus && udc->clock_gating) + /* + * If we have transceiver inited, + * then vbus irq will not be requested in udc driver. + */ + if (udc->pdata && udc->pdata->vbus + && udc->clock_gating && udc->transceiver == NULL) free_irq(udc->pdata->vbus->irq, &dev->dev); /* free memory allocated in probe */ @@ -2182,6 +2201,11 @@ static int __devinit mv_udc_probe(struct platform_device *dev) udc->dev = dev; +#ifdef CONFIG_USB_OTG_UTILS + if (pdata->mode == MV_USB_MODE_OTG) + udc->transceiver = otg_get_transceiver(); +#endif + udc->clknum = pdata->clknum; for (clk_i = 0; clk_i < udc->clknum; clk_i++) { udc->clk[clk_i] = clk_get(&dev->dev, pdata->clkname[clk_i]); @@ -2328,7 +2352,9 @@ static int __devinit mv_udc_probe(struct platform_device *dev) eps_init(udc); /* VBUS detect: we can disable/enable clock on demand.*/ - if (pdata->vbus) { + if (udc->transceiver) + udc->clock_gating = 1; + else if (pdata->vbus) { udc->clock_gating = 1; retval = request_threaded_irq(pdata->vbus->irq, NULL, mv_udc_vbus_irq, IRQF_ONESHOT, "vbus", udc); @@ -2371,7 +2397,8 @@ static int __devinit mv_udc_probe(struct platform_device *dev) return 0; err_unregister: - if (udc->pdata && udc->pdata->vbus && udc->clock_gating) + if (udc->pdata && udc->pdata->vbus + && udc->clock_gating && udc->transceiver == NULL) free_irq(pdata->vbus->irq, &dev->dev); device_unregister(&udc->gadget.dev); err_free_irq: |