aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/chipidea/udc.c
diff options
context:
space:
mode:
authorRichard Zhao <richard.zhao@freescale.com>2012-09-12 07:58:09 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-12 14:20:38 -0400
commit8c4fc031954b4eb72daf13d3c907a985a3eee208 (patch)
tree0c55afe1e363f14ec6847c3ea8b7d3b1d24e10db /drivers/usb/chipidea/udc.c
parent984f753cf120db60d97271e34cf16c95761f0278 (diff)
USB: chipidea: add vbus detect for udc
Using vbus valid interrupt to detect vbus. Tested-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Tested-by: Marc Kleine-Budde <mkl@pengutronix.de> Signed-off-by: Richard Zhao <richard.zhao@freescale.com> Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/chipidea/udc.c')
-rw-r--r--drivers/usb/chipidea/udc.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index d214448b677e..2f45bba8561d 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -305,6 +305,18 @@ static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci)
305 return reg; 305 return reg;
306} 306}
307 307
308static void hw_enable_vbus_intr(struct ci13xxx *ci)
309{
310 hw_write(ci, OP_OTGSC, OTGSC_AVVIS, OTGSC_AVVIS);
311 hw_write(ci, OP_OTGSC, OTGSC_AVVIE, OTGSC_AVVIE);
312 queue_work(ci->wq, &ci->vbus_work);
313}
314
315static void hw_disable_vbus_intr(struct ci13xxx *ci)
316{
317 hw_write(ci, OP_OTGSC, OTGSC_AVVIE, 0);
318}
319
308/** 320/**
309 * hw_test_and_clear_setup_guard: test & clear setup guard (execute without 321 * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
310 * interruption) 322 * interruption)
@@ -371,6 +383,16 @@ static int hw_usb_reset(struct ci13xxx *ci)
371 return 0; 383 return 0;
372} 384}
373 385
386static void vbus_work(struct work_struct *work)
387{
388 struct ci13xxx *ci = container_of(work, struct ci13xxx, vbus_work);
389
390 if (hw_read(ci, OP_OTGSC, OTGSC_AVV))
391 usb_gadget_vbus_connect(&ci->gadget);
392 else
393 usb_gadget_vbus_disconnect(&ci->gadget);
394}
395
374/****************************************************************************** 396/******************************************************************************
375 * UTIL block 397 * UTIL block
376 *****************************************************************************/ 398 *****************************************************************************/
@@ -1370,6 +1392,7 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
1370 if (is_active) { 1392 if (is_active) {
1371 pm_runtime_get_sync(&_gadget->dev); 1393 pm_runtime_get_sync(&_gadget->dev);
1372 hw_device_reset(ci, USBMODE_CM_DC); 1394 hw_device_reset(ci, USBMODE_CM_DC);
1395 hw_enable_vbus_intr(ci);
1373 hw_device_state(ci, ci->ep0out->qh.dma); 1396 hw_device_state(ci, ci->ep0out->qh.dma);
1374 } else { 1397 } else {
1375 hw_device_state(ci, 0); 1398 hw_device_state(ci, 0);
@@ -1544,8 +1567,10 @@ static int ci13xxx_start(struct usb_gadget *gadget,
1544 pm_runtime_get_sync(&ci->gadget.dev); 1567 pm_runtime_get_sync(&ci->gadget.dev);
1545 if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) { 1568 if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) {
1546 if (ci->vbus_active) { 1569 if (ci->vbus_active) {
1547 if (ci->platdata->flags & CI13XXX_REGS_SHARED) 1570 if (ci->platdata->flags & CI13XXX_REGS_SHARED) {
1548 hw_device_reset(ci, USBMODE_CM_DC); 1571 hw_device_reset(ci, USBMODE_CM_DC);
1572 hw_enable_vbus_intr(ci);
1573 }
1549 } else { 1574 } else {
1550 pm_runtime_put_sync(&ci->gadget.dev); 1575 pm_runtime_put_sync(&ci->gadget.dev);
1551 goto done; 1576 goto done;
@@ -1651,6 +1676,13 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)
1651 } else { 1676 } else {
1652 retval = IRQ_NONE; 1677 retval = IRQ_NONE;
1653 } 1678 }
1679
1680 intr = hw_read(ci, OP_OTGSC, ~0);
1681 hw_write(ci, OP_OTGSC, ~0, intr);
1682
1683 if (intr & (OTGSC_AVVIE & OTGSC_AVVIS))
1684 queue_work(ci->wq, &ci->vbus_work);
1685
1654 spin_unlock(&ci->lock); 1686 spin_unlock(&ci->lock);
1655 1687
1656 return retval; 1688 return retval;
@@ -1726,6 +1758,7 @@ static int udc_start(struct ci13xxx *ci)
1726 retval = hw_device_reset(ci, USBMODE_CM_DC); 1758 retval = hw_device_reset(ci, USBMODE_CM_DC);
1727 if (retval) 1759 if (retval)
1728 goto put_transceiver; 1760 goto put_transceiver;
1761 hw_enable_vbus_intr(ci);
1729 } 1762 }
1730 1763
1731 retval = device_register(&ci->gadget.dev); 1764 retval = device_register(&ci->gadget.dev);
@@ -1788,6 +1821,9 @@ static void udc_stop(struct ci13xxx *ci)
1788 if (ci == NULL) 1821 if (ci == NULL)
1789 return; 1822 return;
1790 1823
1824 hw_disable_vbus_intr(ci);
1825 cancel_work_sync(&ci->vbus_work);
1826
1791 usb_del_gadget_udc(&ci->gadget); 1827 usb_del_gadget_udc(&ci->gadget);
1792 1828
1793 destroy_eps(ci); 1829 destroy_eps(ci);
@@ -1828,6 +1864,7 @@ int ci_hdrc_gadget_init(struct ci13xxx *ci)
1828 rdrv->irq = udc_irq; 1864 rdrv->irq = udc_irq;
1829 rdrv->name = "gadget"; 1865 rdrv->name = "gadget";
1830 ci->roles[CI_ROLE_GADGET] = rdrv; 1866 ci->roles[CI_ROLE_GADGET] = rdrv;
1867 INIT_WORK(&ci->vbus_work, vbus_work);
1831 1868
1832 return 0; 1869 return 0;
1833} 1870}