aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorNeil Zhang <zhangwm@marvell.com>2011-10-12 04:49:38 -0400
committerFelipe Balbi <balbi@ti.com>2011-10-13 13:42:08 -0400
commitfb22cbac8242e92d643e5d5cb81bc6307fa6fc9c (patch)
treef13405c72d094662af750ef4c72228f9f062f423 /drivers/usb
parent46e172dfb38c9dad2ea52d8c161834c1f0bd2473 (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.h2
-rw-r--r--drivers/usb/gadget/mv_udc_core.c71
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
1207static 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
1212static int eps_init(struct mv_udc *udc) 1207static 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
1357static 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
1366static 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
1362static int 1382static int
1363udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty) 1383udc_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
1440static 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
1415static void ch9setaddress(struct mv_udc *udc, struct usb_ctrlrequest *setup) 1451static 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 }