diff options
Diffstat (limited to 'drivers/usb/gadget/atmel_usba_udc.c')
-rw-r--r-- | drivers/usb/gadget/atmel_usba_udc.c | 57 |
1 files changed, 48 insertions, 9 deletions
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 2bb28a583937..4fb5ff469574 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c | |||
@@ -989,8 +989,44 @@ static int usba_udc_get_frame(struct usb_gadget *gadget) | |||
989 | return USBA_BFEXT(FRAME_NUMBER, usba_readl(udc, FNUM)); | 989 | return USBA_BFEXT(FRAME_NUMBER, usba_readl(udc, FNUM)); |
990 | } | 990 | } |
991 | 991 | ||
992 | static int usba_udc_wakeup(struct usb_gadget *gadget) | ||
993 | { | ||
994 | struct usba_udc *udc = to_usba_udc(gadget); | ||
995 | unsigned long flags; | ||
996 | u32 ctrl; | ||
997 | int ret = -EINVAL; | ||
998 | |||
999 | spin_lock_irqsave(&udc->lock, flags); | ||
1000 | if (udc->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { | ||
1001 | ctrl = usba_readl(udc, CTRL); | ||
1002 | usba_writel(udc, CTRL, ctrl | USBA_REMOTE_WAKE_UP); | ||
1003 | ret = 0; | ||
1004 | } | ||
1005 | spin_unlock_irqrestore(&udc->lock, flags); | ||
1006 | |||
1007 | return ret; | ||
1008 | } | ||
1009 | |||
1010 | static int | ||
1011 | usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered) | ||
1012 | { | ||
1013 | struct usba_udc *udc = to_usba_udc(gadget); | ||
1014 | unsigned long flags; | ||
1015 | |||
1016 | spin_lock_irqsave(&udc->lock, flags); | ||
1017 | if (is_selfpowered) | ||
1018 | udc->devstatus |= 1 << USB_DEVICE_SELF_POWERED; | ||
1019 | else | ||
1020 | udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED); | ||
1021 | spin_unlock_irqrestore(&udc->lock, flags); | ||
1022 | |||
1023 | return 0; | ||
1024 | } | ||
1025 | |||
992 | static const struct usb_gadget_ops usba_udc_ops = { | 1026 | static const struct usb_gadget_ops usba_udc_ops = { |
993 | .get_frame = usba_udc_get_frame, | 1027 | .get_frame = usba_udc_get_frame, |
1028 | .wakeup = usba_udc_wakeup, | ||
1029 | .set_selfpowered = usba_udc_set_selfpowered, | ||
994 | }; | 1030 | }; |
995 | 1031 | ||
996 | #define EP(nam, idx, maxpkt, maxbk, dma, isoc) \ | 1032 | #define EP(nam, idx, maxpkt, maxbk, dma, isoc) \ |
@@ -1068,8 +1104,11 @@ static void reset_all_endpoints(struct usba_udc *udc) | |||
1068 | } | 1104 | } |
1069 | 1105 | ||
1070 | list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { | 1106 | list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { |
1071 | if (ep->desc) | 1107 | if (ep->desc) { |
1108 | spin_unlock(&udc->lock); | ||
1072 | usba_ep_disable(&ep->ep); | 1109 | usba_ep_disable(&ep->ep); |
1110 | spin_lock(&udc->lock); | ||
1111 | } | ||
1073 | } | 1112 | } |
1074 | } | 1113 | } |
1075 | 1114 | ||
@@ -1238,8 +1277,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, | |||
1238 | u16 status; | 1277 | u16 status; |
1239 | 1278 | ||
1240 | if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_DEVICE)) { | 1279 | if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_DEVICE)) { |
1241 | /* Self-powered, no remote wakeup */ | 1280 | status = cpu_to_le16(udc->devstatus); |
1242 | status = __constant_cpu_to_le16(1 << 0); | ||
1243 | } else if (crq->bRequestType | 1281 | } else if (crq->bRequestType |
1244 | == (USB_DIR_IN | USB_RECIP_INTERFACE)) { | 1282 | == (USB_DIR_IN | USB_RECIP_INTERFACE)) { |
1245 | status = __constant_cpu_to_le16(0); | 1283 | status = __constant_cpu_to_le16(0); |
@@ -1268,12 +1306,12 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, | |||
1268 | 1306 | ||
1269 | case USB_REQ_CLEAR_FEATURE: { | 1307 | case USB_REQ_CLEAR_FEATURE: { |
1270 | if (crq->bRequestType == USB_RECIP_DEVICE) { | 1308 | if (crq->bRequestType == USB_RECIP_DEVICE) { |
1271 | if (feature_is_dev_remote_wakeup(crq)) { | 1309 | if (feature_is_dev_remote_wakeup(crq)) |
1272 | /* TODO: Handle REMOTE_WAKEUP */ | 1310 | udc->devstatus |
1273 | } else { | 1311 | &= ~(1 << USB_DEVICE_REMOTE_WAKEUP); |
1312 | else | ||
1274 | /* Can't CLEAR_FEATURE TEST_MODE */ | 1313 | /* Can't CLEAR_FEATURE TEST_MODE */ |
1275 | goto stall; | 1314 | goto stall; |
1276 | } | ||
1277 | } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { | 1315 | } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { |
1278 | struct usba_ep *target; | 1316 | struct usba_ep *target; |
1279 | 1317 | ||
@@ -1304,7 +1342,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, | |||
1304 | udc->test_mode = le16_to_cpu(crq->wIndex); | 1342 | udc->test_mode = le16_to_cpu(crq->wIndex); |
1305 | return 0; | 1343 | return 0; |
1306 | } else if (feature_is_dev_remote_wakeup(crq)) { | 1344 | } else if (feature_is_dev_remote_wakeup(crq)) { |
1307 | /* TODO: Handle REMOTE_WAKEUP */ | 1345 | udc->devstatus |= 1 << USB_DEVICE_REMOTE_WAKEUP; |
1308 | } else { | 1346 | } else { |
1309 | goto stall; | 1347 | goto stall; |
1310 | } | 1348 | } |
@@ -1791,6 +1829,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) | |||
1791 | return -EBUSY; | 1829 | return -EBUSY; |
1792 | } | 1830 | } |
1793 | 1831 | ||
1832 | udc->devstatus = 1 << USB_DEVICE_SELF_POWERED; | ||
1794 | udc->driver = driver; | 1833 | udc->driver = driver; |
1795 | udc->gadget.dev.driver = &driver->driver; | 1834 | udc->gadget.dev.driver = &driver->driver; |
1796 | spin_unlock_irqrestore(&udc->lock, flags); | 1835 | spin_unlock_irqrestore(&udc->lock, flags); |