diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/gadget/atmel_usba_udc.c | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index e756023362c2..07e5a0b5dcda 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c | |||
@@ -649,7 +649,13 @@ static int usba_ep_disable(struct usb_ep *_ep) | |||
649 | 649 | ||
650 | if (!ep->desc) { | 650 | if (!ep->desc) { |
651 | spin_unlock_irqrestore(&udc->lock, flags); | 651 | spin_unlock_irqrestore(&udc->lock, flags); |
652 | DBG(DBG_ERR, "ep_disable: %s not enabled\n", ep->ep.name); | 652 | /* REVISIT because this driver disables endpoints in |
653 | * reset_all_endpoints() before calling disconnect(), | ||
654 | * most gadget drivers would trigger this non-error ... | ||
655 | */ | ||
656 | if (udc->gadget.speed != USB_SPEED_UNKNOWN) | ||
657 | DBG(DBG_ERR, "ep_disable: %s not enabled\n", | ||
658 | ep->ep.name); | ||
653 | return -EINVAL; | 659 | return -EINVAL; |
654 | } | 660 | } |
655 | ep->desc = NULL; | 661 | ep->desc = NULL; |
@@ -1032,8 +1038,6 @@ static struct usba_udc the_udc = { | |||
1032 | .release = nop_release, | 1038 | .release = nop_release, |
1033 | }, | 1039 | }, |
1034 | }, | 1040 | }, |
1035 | |||
1036 | .lock = SPIN_LOCK_UNLOCKED, | ||
1037 | }; | 1041 | }; |
1038 | 1042 | ||
1039 | /* | 1043 | /* |
@@ -1052,6 +1056,12 @@ static void reset_all_endpoints(struct usba_udc *udc) | |||
1052 | request_complete(ep, req, -ECONNRESET); | 1056 | request_complete(ep, req, -ECONNRESET); |
1053 | } | 1057 | } |
1054 | 1058 | ||
1059 | /* NOTE: normally, the next call to the gadget driver is in | ||
1060 | * charge of disabling endpoints... usually disconnect(). | ||
1061 | * The exception would be entering a high speed test mode. | ||
1062 | * | ||
1063 | * FIXME remove this code ... and retest thoroughly. | ||
1064 | */ | ||
1055 | list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { | 1065 | list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { |
1056 | if (ep->desc) { | 1066 | if (ep->desc) { |
1057 | spin_unlock(&udc->lock); | 1067 | spin_unlock(&udc->lock); |
@@ -1219,7 +1229,7 @@ static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq) | |||
1219 | static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, | 1229 | static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, |
1220 | struct usb_ctrlrequest *crq) | 1230 | struct usb_ctrlrequest *crq) |
1221 | { | 1231 | { |
1222 | int retval = 0;; | 1232 | int retval = 0; |
1223 | 1233 | ||
1224 | switch (crq->bRequest) { | 1234 | switch (crq->bRequest) { |
1225 | case USB_REQ_GET_STATUS: { | 1235 | case USB_REQ_GET_STATUS: { |
@@ -1693,6 +1703,14 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) | |||
1693 | usba_writel(udc, INT_CLR, USBA_END_OF_RESET); | 1703 | usba_writel(udc, INT_CLR, USBA_END_OF_RESET); |
1694 | reset_all_endpoints(udc); | 1704 | reset_all_endpoints(udc); |
1695 | 1705 | ||
1706 | if (udc->gadget.speed != USB_SPEED_UNKNOWN | ||
1707 | && udc->driver->disconnect) { | ||
1708 | udc->gadget.speed = USB_SPEED_UNKNOWN; | ||
1709 | spin_unlock(&udc->lock); | ||
1710 | udc->driver->disconnect(&udc->gadget); | ||
1711 | spin_lock(&udc->lock); | ||
1712 | } | ||
1713 | |||
1696 | if (status & USBA_HIGH_SPEED) { | 1714 | if (status & USBA_HIGH_SPEED) { |
1697 | DBG(DBG_BUS, "High-speed bus reset detected\n"); | 1715 | DBG(DBG_BUS, "High-speed bus reset detected\n"); |
1698 | udc->gadget.speed = USB_SPEED_HIGH; | 1716 | udc->gadget.speed = USB_SPEED_HIGH; |
@@ -1716,9 +1734,13 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) | |||
1716 | | USBA_DET_SUSPEND | 1734 | | USBA_DET_SUSPEND |
1717 | | USBA_END_OF_RESUME)); | 1735 | | USBA_END_OF_RESUME)); |
1718 | 1736 | ||
1737 | /* | ||
1738 | * Unclear why we hit this irregularly, e.g. in usbtest, | ||
1739 | * but it's clearly harmless... | ||
1740 | */ | ||
1719 | if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED)) | 1741 | if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED)) |
1720 | dev_warn(&udc->pdev->dev, | 1742 | dev_dbg(&udc->pdev->dev, |
1721 | "WARNING: EP0 configuration is invalid!\n"); | 1743 | "ODD: EP0 configuration is invalid!\n"); |
1722 | } | 1744 | } |
1723 | 1745 | ||
1724 | spin_unlock(&udc->lock); | 1746 | spin_unlock(&udc->lock); |
@@ -1751,9 +1773,11 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid) | |||
1751 | reset_all_endpoints(udc); | 1773 | reset_all_endpoints(udc); |
1752 | toggle_bias(0); | 1774 | toggle_bias(0); |
1753 | usba_writel(udc, CTRL, USBA_DISABLE_MASK); | 1775 | usba_writel(udc, CTRL, USBA_DISABLE_MASK); |
1754 | spin_unlock(&udc->lock); | 1776 | if (udc->driver->disconnect) { |
1755 | udc->driver->disconnect(&udc->gadget); | 1777 | spin_unlock(&udc->lock); |
1756 | spin_lock(&udc->lock); | 1778 | udc->driver->disconnect(&udc->gadget); |
1779 | spin_lock(&udc->lock); | ||
1780 | } | ||
1757 | } | 1781 | } |
1758 | udc->vbus_prev = vbus; | 1782 | udc->vbus_prev = vbus; |
1759 | } | 1783 | } |
@@ -1825,7 +1849,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
1825 | 1849 | ||
1826 | if (!udc->pdev) | 1850 | if (!udc->pdev) |
1827 | return -ENODEV; | 1851 | return -ENODEV; |
1828 | if (driver != udc->driver) | 1852 | if (driver != udc->driver || !driver->unbind) |
1829 | return -EINVAL; | 1853 | return -EINVAL; |
1830 | 1854 | ||
1831 | if (udc->vbus_pin != -1) | 1855 | if (udc->vbus_pin != -1) |
@@ -1840,6 +1864,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
1840 | toggle_bias(0); | 1864 | toggle_bias(0); |
1841 | usba_writel(udc, CTRL, USBA_DISABLE_MASK); | 1865 | usba_writel(udc, CTRL, USBA_DISABLE_MASK); |
1842 | 1866 | ||
1867 | if (udc->driver->disconnect) | ||
1868 | udc->driver->disconnect(&udc->gadget); | ||
1869 | |||
1843 | driver->unbind(&udc->gadget); | 1870 | driver->unbind(&udc->gadget); |
1844 | udc->gadget.dev.driver = NULL; | 1871 | udc->gadget.dev.driver = NULL; |
1845 | udc->driver = NULL; | 1872 | udc->driver = NULL; |
@@ -1879,6 +1906,7 @@ static int __init usba_udc_probe(struct platform_device *pdev) | |||
1879 | goto err_get_hclk; | 1906 | goto err_get_hclk; |
1880 | } | 1907 | } |
1881 | 1908 | ||
1909 | spin_lock_init(&udc->lock); | ||
1882 | udc->pdev = pdev; | 1910 | udc->pdev = pdev; |
1883 | udc->pclk = pclk; | 1911 | udc->pclk = pclk; |
1884 | udc->hclk = hclk; | 1912 | udc->hclk = hclk; |