[PATCH 3/7 v2] usb: gadget: mv_udc: add otg relative code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add otg relative code, make it possible to switch between host and
device.

Signed-off-by: Neil Zhang <zhangwm@xxxxxxxxxxx>
---
 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 daa75c1..b2c36ee 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 8924121..c7c0bfa 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:
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux