From 487d54d172b3afd3d2bf124b24eaf7f7e7b8a668 Mon Sep 17 00:00:00 2001 From: Neil Zhang Date: Wed, 30 Nov 2011 09:57:13 +0800 Subject: [PATCH] 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 Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_udc.h | 2 ++ 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: -- 2.34.1