diff options
author | Neil Zhang <zhangwm@marvell.com> | 2011-10-12 04:49:38 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2011-10-13 13:42:08 -0400 |
commit | fb22cbac8242e92d643e5d5cb81bc6307fa6fc9c (patch) | |
tree | f13405c72d094662af750ef4c72228f9f062f423 /drivers/usb | |
parent | 46e172dfb38c9dad2ea52d8c161834c1f0bd2473 (diff) |
usb: gadget: mv_udc: add test mode support
Add test mode support for marvell udc driver.
Signed-off-by: Neil Zhang <zhangwm@marvell.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/gadget/mv_udc.h | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/mv_udc_core.c | 71 |
2 files changed, 54 insertions, 19 deletions
diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h index d3d26454b8bb..3e5e6ea7b0fb 100644 --- a/drivers/usb/gadget/mv_udc.h +++ b/drivers/usb/gadget/mv_udc.h | |||
@@ -202,6 +202,7 @@ struct mv_udc { | |||
202 | unsigned int ep0_dir; | 202 | unsigned int ep0_dir; |
203 | 203 | ||
204 | unsigned int dev_addr; | 204 | unsigned int dev_addr; |
205 | unsigned int test_mode; | ||
205 | 206 | ||
206 | int errors; | 207 | int errors; |
207 | unsigned softconnect:1, | 208 | unsigned softconnect:1, |
@@ -238,6 +239,7 @@ struct mv_req { | |||
238 | struct mv_dtd *dtd, *head, *tail; | 239 | struct mv_dtd *dtd, *head, *tail; |
239 | struct mv_ep *ep; | 240 | struct mv_ep *ep; |
240 | struct list_head queue; | 241 | struct list_head queue; |
242 | unsigned int test_mode; | ||
241 | unsigned dtd_count; | 243 | unsigned dtd_count; |
242 | unsigned mapped:1; | 244 | unsigned mapped:1; |
243 | }; | 245 | }; |
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 1f47d03d6871..333b85b96292 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c | |||
@@ -1204,11 +1204,6 @@ static const struct usb_gadget_ops mv_ops = { | |||
1204 | .stop = mv_udc_stop, | 1204 | .stop = mv_udc_stop, |
1205 | }; | 1205 | }; |
1206 | 1206 | ||
1207 | static void mv_udc_testmode(struct mv_udc *udc, u16 index, bool enter) | ||
1208 | { | ||
1209 | dev_info(&udc->dev->dev, "Test Mode is not support yet\n"); | ||
1210 | } | ||
1211 | |||
1212 | static int eps_init(struct mv_udc *udc) | 1207 | static int eps_init(struct mv_udc *udc) |
1213 | { | 1208 | { |
1214 | struct mv_ep *ep; | 1209 | struct mv_ep *ep; |
@@ -1359,6 +1354,31 @@ static int mv_udc_stop(struct usb_gadget_driver *driver) | |||
1359 | return 0; | 1354 | return 0; |
1360 | } | 1355 | } |
1361 | 1356 | ||
1357 | static void mv_set_ptc(struct mv_udc *udc, u32 mode) | ||
1358 | { | ||
1359 | u32 portsc; | ||
1360 | |||
1361 | portsc = readl(&udc->op_regs->portsc[0]); | ||
1362 | portsc |= mode << 16; | ||
1363 | writel(portsc, &udc->op_regs->portsc[0]); | ||
1364 | } | ||
1365 | |||
1366 | static void prime_status_complete(struct usb_ep *ep, struct usb_request *_req) | ||
1367 | { | ||
1368 | struct mv_udc *udc = the_controller; | ||
1369 | struct mv_req *req = container_of(_req, struct mv_req, req); | ||
1370 | unsigned long flags; | ||
1371 | |||
1372 | dev_info(&udc->dev->dev, "switch to test mode %d\n", req->test_mode); | ||
1373 | |||
1374 | spin_lock_irqsave(&udc->lock, flags); | ||
1375 | if (req->test_mode) { | ||
1376 | mv_set_ptc(udc, req->test_mode); | ||
1377 | req->test_mode = 0; | ||
1378 | } | ||
1379 | spin_unlock_irqrestore(&udc->lock, flags); | ||
1380 | } | ||
1381 | |||
1362 | static int | 1382 | static int |
1363 | udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty) | 1383 | udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty) |
1364 | { | 1384 | { |
@@ -1382,7 +1402,12 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty) | |||
1382 | req->ep = ep; | 1402 | req->ep = ep; |
1383 | req->req.status = -EINPROGRESS; | 1403 | req->req.status = -EINPROGRESS; |
1384 | req->req.actual = 0; | 1404 | req->req.actual = 0; |
1385 | req->req.complete = NULL; | 1405 | if (udc->test_mode) { |
1406 | req->req.complete = prime_status_complete; | ||
1407 | req->test_mode = udc->test_mode; | ||
1408 | udc->test_mode = 0; | ||
1409 | } else | ||
1410 | req->req.complete = NULL; | ||
1386 | req->dtd_count = 0; | 1411 | req->dtd_count = 0; |
1387 | 1412 | ||
1388 | if (req->req.dma == DMA_ADDR_INVALID) { | 1413 | if (req->req.dma == DMA_ADDR_INVALID) { |
@@ -1412,6 +1437,17 @@ out: | |||
1412 | return retval; | 1437 | return retval; |
1413 | } | 1438 | } |
1414 | 1439 | ||
1440 | static void mv_udc_testmode(struct mv_udc *udc, u16 index) | ||
1441 | { | ||
1442 | if (index <= TEST_FORCE_EN) { | ||
1443 | udc->test_mode = index; | ||
1444 | if (udc_prime_status(udc, EP_DIR_IN, 0, true)) | ||
1445 | ep0_stall(udc); | ||
1446 | } else | ||
1447 | dev_err(&udc->dev->dev, | ||
1448 | "This test mode(%d) is not supported\n", index); | ||
1449 | } | ||
1450 | |||
1415 | static void ch9setaddress(struct mv_udc *udc, struct usb_ctrlrequest *setup) | 1451 | static void ch9setaddress(struct mv_udc *udc, struct usb_ctrlrequest *setup) |
1416 | { | 1452 | { |
1417 | udc->dev_addr = (u8)setup->wValue; | 1453 | udc->dev_addr = (u8)setup->wValue; |
@@ -1470,9 +1506,6 @@ static void ch9clearfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup) | |||
1470 | case USB_DEVICE_REMOTE_WAKEUP: | 1506 | case USB_DEVICE_REMOTE_WAKEUP: |
1471 | udc->remote_wakeup = 0; | 1507 | udc->remote_wakeup = 0; |
1472 | break; | 1508 | break; |
1473 | case USB_DEVICE_TEST_MODE: | ||
1474 | mv_udc_testmode(udc, 0, false); | ||
1475 | break; | ||
1476 | default: | 1509 | default: |
1477 | goto out; | 1510 | goto out; |
1478 | } | 1511 | } |
@@ -1518,16 +1551,16 @@ static void ch9setfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup) | |||
1518 | break; | 1551 | break; |
1519 | case USB_DEVICE_TEST_MODE: | 1552 | case USB_DEVICE_TEST_MODE: |
1520 | if (setup->wIndex & 0xFF | 1553 | if (setup->wIndex & 0xFF |
1521 | && udc->gadget.speed != USB_SPEED_HIGH) | 1554 | || udc->gadget.speed != USB_SPEED_HIGH) |
1522 | goto out; | 1555 | ep0_stall(udc); |
1523 | if (udc->usb_state == USB_STATE_CONFIGURED | 1556 | |
1524 | || udc->usb_state == USB_STATE_ADDRESS | 1557 | if (udc->usb_state != USB_STATE_CONFIGURED |
1525 | || udc->usb_state == USB_STATE_DEFAULT) | 1558 | && udc->usb_state != USB_STATE_ADDRESS |
1526 | mv_udc_testmode(udc, | 1559 | && udc->usb_state != USB_STATE_DEFAULT) |
1527 | setup->wIndex & 0xFF00, true); | 1560 | ep0_stall(udc); |
1528 | else | 1561 | |
1529 | goto out; | 1562 | mv_udc_testmode(udc, (setup->wIndex >> 8)); |
1530 | break; | 1563 | goto out; |
1531 | default: | 1564 | default: |
1532 | goto out; | 1565 | goto out; |
1533 | } | 1566 | } |