aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/chipidea/udc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/chipidea/udc.c')
-rw-r--r--drivers/usb/chipidea/udc.c78
1 files changed, 49 insertions, 29 deletions
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index e475fcda1d68..6b4c2f2eb946 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -27,6 +27,7 @@
27#include "udc.h" 27#include "udc.h"
28#include "bits.h" 28#include "bits.h"
29#include "debug.h" 29#include "debug.h"
30#include "otg.h"
30 31
31/* control endpoint description */ 32/* control endpoint description */
32static const struct usb_endpoint_descriptor 33static const struct usb_endpoint_descriptor
@@ -84,8 +85,10 @@ static int hw_device_state(struct ci_hdrc *ci, u32 dma)
84 /* interrupt, error, port change, reset, sleep/suspend */ 85 /* interrupt, error, port change, reset, sleep/suspend */
85 hw_write(ci, OP_USBINTR, ~0, 86 hw_write(ci, OP_USBINTR, ~0,
86 USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); 87 USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
88 hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
87 } else { 89 } else {
88 hw_write(ci, OP_USBINTR, ~0, 0); 90 hw_write(ci, OP_USBINTR, ~0, 0);
91 hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
89 } 92 }
90 return 0; 93 return 0;
91} 94}
@@ -1445,9 +1448,6 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
1445 unsigned long flags; 1448 unsigned long flags;
1446 int gadget_ready = 0; 1449 int gadget_ready = 0;
1447 1450
1448 if (!(ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS))
1449 return -EOPNOTSUPP;
1450
1451 spin_lock_irqsave(&ci->lock, flags); 1451 spin_lock_irqsave(&ci->lock, flags);
1452 ci->vbus_active = is_active; 1452 ci->vbus_active = is_active;
1453 if (ci->driver) 1453 if (ci->driver)
@@ -1459,6 +1459,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
1459 pm_runtime_get_sync(&_gadget->dev); 1459 pm_runtime_get_sync(&_gadget->dev);
1460 hw_device_reset(ci, USBMODE_CM_DC); 1460 hw_device_reset(ci, USBMODE_CM_DC);
1461 hw_device_state(ci, ci->ep0out->qh.dma); 1461 hw_device_state(ci, ci->ep0out->qh.dma);
1462 dev_dbg(ci->dev, "Connected to host\n");
1462 } else { 1463 } else {
1463 hw_device_state(ci, 0); 1464 hw_device_state(ci, 0);
1464 if (ci->platdata->notify_event) 1465 if (ci->platdata->notify_event)
@@ -1466,6 +1467,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
1466 CI_HDRC_CONTROLLER_STOPPED_EVENT); 1467 CI_HDRC_CONTROLLER_STOPPED_EVENT);
1467 _gadget_stop_activity(&ci->gadget); 1468 _gadget_stop_activity(&ci->gadget);
1468 pm_runtime_put_sync(&_gadget->dev); 1469 pm_runtime_put_sync(&_gadget->dev);
1470 dev_dbg(ci->dev, "Disconnected from host\n");
1469 } 1471 }
1470 } 1472 }
1471 1473
@@ -1509,6 +1511,9 @@ static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on)
1509{ 1511{
1510 struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); 1512 struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget);
1511 1513
1514 if (!ci->vbus_active)
1515 return -EOPNOTSUPP;
1516
1512 if (is_on) 1517 if (is_on)
1513 hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); 1518 hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
1514 else 1519 else
@@ -1630,14 +1635,11 @@ static int ci_udc_start(struct usb_gadget *gadget,
1630 1635
1631 ci->driver = driver; 1636 ci->driver = driver;
1632 pm_runtime_get_sync(&ci->gadget.dev); 1637 pm_runtime_get_sync(&ci->gadget.dev);
1633 if (ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS) { 1638 if (ci->vbus_active) {
1634 if (ci->vbus_active) { 1639 hw_device_reset(ci, USBMODE_CM_DC);
1635 if (ci->platdata->flags & CI_HDRC_REGS_SHARED) 1640 } else {
1636 hw_device_reset(ci, USBMODE_CM_DC); 1641 pm_runtime_put_sync(&ci->gadget.dev);
1637 } else { 1642 goto done;
1638 pm_runtime_put_sync(&ci->gadget.dev);
1639 goto done;
1640 }
1641 } 1643 }
1642 1644
1643 retval = hw_device_state(ci, ci->ep0out->qh.dma); 1645 retval = hw_device_state(ci, ci->ep0out->qh.dma);
@@ -1660,8 +1662,7 @@ static int ci_udc_stop(struct usb_gadget *gadget,
1660 1662
1661 spin_lock_irqsave(&ci->lock, flags); 1663 spin_lock_irqsave(&ci->lock, flags);
1662 1664
1663 if (!(ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS) || 1665 if (ci->vbus_active) {
1664 ci->vbus_active) {
1665 hw_device_state(ci, 0); 1666 hw_device_state(ci, 0);
1666 if (ci->platdata->notify_event) 1667 if (ci->platdata->notify_event)
1667 ci->platdata->notify_event(ci, 1668 ci->platdata->notify_event(ci,
@@ -1796,16 +1797,15 @@ static int udc_start(struct ci_hdrc *ci)
1796 } 1797 }
1797 } 1798 }
1798 1799
1799 if (!(ci->platdata->flags & CI_HDRC_REGS_SHARED)) {
1800 retval = hw_device_reset(ci, USBMODE_CM_DC);
1801 if (retval)
1802 goto put_transceiver;
1803 }
1804
1805 if (ci->transceiver) { 1800 if (ci->transceiver) {
1806 retval = otg_set_peripheral(ci->transceiver->otg, 1801 retval = otg_set_peripheral(ci->transceiver->otg,
1807 &ci->gadget); 1802 &ci->gadget);
1808 if (retval) 1803 /*
1804 * If we implement all USB functions using chipidea drivers,
1805 * it doesn't need to call above API, meanwhile, if we only
1806 * use gadget function, calling above API is useless.
1807 */
1808 if (retval && retval != -ENOTSUPP)
1809 goto put_transceiver; 1809 goto put_transceiver;
1810 } 1810 }
1811 1811
@@ -1816,6 +1816,9 @@ static int udc_start(struct ci_hdrc *ci)
1816 pm_runtime_no_callbacks(&ci->gadget.dev); 1816 pm_runtime_no_callbacks(&ci->gadget.dev);
1817 pm_runtime_enable(&ci->gadget.dev); 1817 pm_runtime_enable(&ci->gadget.dev);
1818 1818
1819 /* Update ci->vbus_active */
1820 ci_handle_vbus_change(ci);
1821
1819 return retval; 1822 return retval;
1820 1823
1821remove_trans: 1824remove_trans:
@@ -1839,13 +1842,13 @@ free_qh_pool:
1839} 1842}
1840 1843
1841/** 1844/**
1842 * udc_remove: parent remove must call this to remove UDC 1845 * ci_hdrc_gadget_destroy: parent remove must call this to remove UDC
1843 * 1846 *
1844 * No interrupts active, the IRQ has been released 1847 * No interrupts active, the IRQ has been released
1845 */ 1848 */
1846static void udc_stop(struct ci_hdrc *ci) 1849void ci_hdrc_gadget_destroy(struct ci_hdrc *ci)
1847{ 1850{
1848 if (ci == NULL) 1851 if (!ci->roles[CI_ROLE_GADGET])
1849 return; 1852 return;
1850 1853
1851 usb_del_gadget_udc(&ci->gadget); 1854 usb_del_gadget_udc(&ci->gadget);
@@ -1860,15 +1863,32 @@ static void udc_stop(struct ci_hdrc *ci)
1860 if (ci->global_phy) 1863 if (ci->global_phy)
1861 usb_put_phy(ci->transceiver); 1864 usb_put_phy(ci->transceiver);
1862 } 1865 }
1863 /* my kobject is dynamic, I swear! */ 1866}
1864 memset(&ci->gadget, 0, sizeof(ci->gadget)); 1867
1868static int udc_id_switch_for_device(struct ci_hdrc *ci)
1869{
1870 if (ci->is_otg) {
1871 ci_clear_otg_interrupt(ci, OTGSC_BSVIS);
1872 ci_enable_otg_interrupt(ci, OTGSC_BSVIE);
1873 }
1874
1875 return 0;
1876}
1877
1878static void udc_id_switch_for_host(struct ci_hdrc *ci)
1879{
1880 if (ci->is_otg) {
1881 /* host doesn't care B_SESSION_VALID event */
1882 ci_clear_otg_interrupt(ci, OTGSC_BSVIS);
1883 ci_disable_otg_interrupt(ci, OTGSC_BSVIE);
1884 }
1865} 1885}
1866 1886
1867/** 1887/**
1868 * ci_hdrc_gadget_init - initialize device related bits 1888 * ci_hdrc_gadget_init - initialize device related bits
1869 * ci: the controller 1889 * ci: the controller
1870 * 1890 *
1871 * This function enables the gadget role, if the device is "device capable". 1891 * This function initializes the gadget, if the device is "device capable".
1872 */ 1892 */
1873int ci_hdrc_gadget_init(struct ci_hdrc *ci) 1893int ci_hdrc_gadget_init(struct ci_hdrc *ci)
1874{ 1894{
@@ -1881,11 +1901,11 @@ int ci_hdrc_gadget_init(struct ci_hdrc *ci)
1881 if (!rdrv) 1901 if (!rdrv)
1882 return -ENOMEM; 1902 return -ENOMEM;
1883 1903
1884 rdrv->start = udc_start; 1904 rdrv->start = udc_id_switch_for_device;
1885 rdrv->stop = udc_stop; 1905 rdrv->stop = udc_id_switch_for_host;
1886 rdrv->irq = udc_irq; 1906 rdrv->irq = udc_irq;
1887 rdrv->name = "gadget"; 1907 rdrv->name = "gadget";
1888 ci->roles[CI_ROLE_GADGET] = rdrv; 1908 ci->roles[CI_ROLE_GADGET] = rdrv;
1889 1909
1890 return 0; 1910 return udc_start(ci);
1891} 1911}