aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorHaavard Skinnemoen <hskinnemoen@atmel.com>2007-10-11 16:40:30 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-10-12 17:55:35 -0400
commit58ed7b94d98245fbad54a0af7ea3317ab1dd6876 (patch)
treecc5df430c9a4a152d8b264f9f0c613ed40a2c333 /drivers/usb
parentd466a9190ff1ceddfee50686e61d63590fc820d9 (diff)
atmel_usba_udc: Keep track of the device status
Keep track of the device status (as returned by the GET_STATUS request) and allow it to be manipulated by set_selfpowered() as well as SET_FEATURE/CLEAR_FEATURE (for remote wakeup) Implement the wakeup() op, which refuses to do anything if the DEVICE_REMOTE_WAKEUP feature wasn't set by the host. Now this driver passes USBCV (at least, with gadget zero). Fix one more locking bug; lockdep is every developer's friend. Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c57
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.h4
2 files changed, 51 insertions, 10 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
992static 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
1010static int
1011usba_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
992static const struct usb_gadget_ops usba_udc_ops = { 1026static 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);
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
index f4f0f8bf812c..a68304e31a68 100644
--- a/drivers/usb/gadget/atmel_usba_udc.h
+++ b/drivers/usb/gadget/atmel_usba_udc.h
@@ -320,7 +320,9 @@ struct usba_udc {
320 struct clk *pclk; 320 struct clk *pclk;
321 struct clk *hclk; 321 struct clk *hclk;
322 322
323 int test_mode; 323 u16 devstatus;
324
325 u16 test_mode;
324 int vbus_prev; 326 int vbus_prev;
325 327
326#ifdef CONFIG_USB_GADGET_DEBUG_FS 328#ifdef CONFIG_USB_GADGET_DEBUG_FS