Commit fb22cbac authored by Neil Zhang's avatar Neil Zhang Committed by Felipe Balbi

usb: gadget: mv_udc: add test mode support

Add test mode support for marvell udc driver.
Signed-off-by: default avatarNeil Zhang <zhangwm@marvell.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 46e172df
...@@ -202,6 +202,7 @@ struct mv_udc { ...@@ -202,6 +202,7 @@ struct mv_udc {
unsigned int ep0_dir; unsigned int ep0_dir;
unsigned int dev_addr; unsigned int dev_addr;
unsigned int test_mode;
int errors; int errors;
unsigned softconnect:1, unsigned softconnect:1,
...@@ -238,6 +239,7 @@ struct mv_req { ...@@ -238,6 +239,7 @@ struct mv_req {
struct mv_dtd *dtd, *head, *tail; struct mv_dtd *dtd, *head, *tail;
struct mv_ep *ep; struct mv_ep *ep;
struct list_head queue; struct list_head queue;
unsigned int test_mode;
unsigned dtd_count; unsigned dtd_count;
unsigned mapped:1; unsigned mapped:1;
}; };
......
...@@ -1204,11 +1204,6 @@ static const struct usb_gadget_ops mv_ops = { ...@@ -1204,11 +1204,6 @@ static const struct usb_gadget_ops mv_ops = {
.stop = mv_udc_stop, .stop = mv_udc_stop,
}; };
static void mv_udc_testmode(struct mv_udc *udc, u16 index, bool enter)
{
dev_info(&udc->dev->dev, "Test Mode is not support yet\n");
}
static int eps_init(struct mv_udc *udc) static int eps_init(struct mv_udc *udc)
{ {
struct mv_ep *ep; struct mv_ep *ep;
...@@ -1359,6 +1354,31 @@ static int mv_udc_stop(struct usb_gadget_driver *driver) ...@@ -1359,6 +1354,31 @@ static int mv_udc_stop(struct usb_gadget_driver *driver)
return 0; return 0;
} }
static void mv_set_ptc(struct mv_udc *udc, u32 mode)
{
u32 portsc;
portsc = readl(&udc->op_regs->portsc[0]);
portsc |= mode << 16;
writel(portsc, &udc->op_regs->portsc[0]);
}
static void prime_status_complete(struct usb_ep *ep, struct usb_request *_req)
{
struct mv_udc *udc = the_controller;
struct mv_req *req = container_of(_req, struct mv_req, req);
unsigned long flags;
dev_info(&udc->dev->dev, "switch to test mode %d\n", req->test_mode);
spin_lock_irqsave(&udc->lock, flags);
if (req->test_mode) {
mv_set_ptc(udc, req->test_mode);
req->test_mode = 0;
}
spin_unlock_irqrestore(&udc->lock, flags);
}
static int static int
udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty) udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
{ {
...@@ -1382,6 +1402,11 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty) ...@@ -1382,6 +1402,11 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
req->ep = ep; req->ep = ep;
req->req.status = -EINPROGRESS; req->req.status = -EINPROGRESS;
req->req.actual = 0; req->req.actual = 0;
if (udc->test_mode) {
req->req.complete = prime_status_complete;
req->test_mode = udc->test_mode;
udc->test_mode = 0;
} else
req->req.complete = NULL; req->req.complete = NULL;
req->dtd_count = 0; req->dtd_count = 0;
...@@ -1412,6 +1437,17 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty) ...@@ -1412,6 +1437,17 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
return retval; return retval;
} }
static void mv_udc_testmode(struct mv_udc *udc, u16 index)
{
if (index <= TEST_FORCE_EN) {
udc->test_mode = index;
if (udc_prime_status(udc, EP_DIR_IN, 0, true))
ep0_stall(udc);
} else
dev_err(&udc->dev->dev,
"This test mode(%d) is not supported\n", index);
}
static void ch9setaddress(struct mv_udc *udc, struct usb_ctrlrequest *setup) static void ch9setaddress(struct mv_udc *udc, struct usb_ctrlrequest *setup)
{ {
udc->dev_addr = (u8)setup->wValue; udc->dev_addr = (u8)setup->wValue;
...@@ -1470,9 +1506,6 @@ static void ch9clearfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup) ...@@ -1470,9 +1506,6 @@ static void ch9clearfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup)
case USB_DEVICE_REMOTE_WAKEUP: case USB_DEVICE_REMOTE_WAKEUP:
udc->remote_wakeup = 0; udc->remote_wakeup = 0;
break; break;
case USB_DEVICE_TEST_MODE:
mv_udc_testmode(udc, 0, false);
break;
default: default:
goto out; goto out;
} }
...@@ -1518,16 +1551,16 @@ static void ch9setfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup) ...@@ -1518,16 +1551,16 @@ static void ch9setfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup)
break; break;
case USB_DEVICE_TEST_MODE: case USB_DEVICE_TEST_MODE:
if (setup->wIndex & 0xFF if (setup->wIndex & 0xFF
&& udc->gadget.speed != USB_SPEED_HIGH) || udc->gadget.speed != USB_SPEED_HIGH)
goto out; ep0_stall(udc);
if (udc->usb_state == USB_STATE_CONFIGURED
|| udc->usb_state == USB_STATE_ADDRESS if (udc->usb_state != USB_STATE_CONFIGURED
|| udc->usb_state == USB_STATE_DEFAULT) && udc->usb_state != USB_STATE_ADDRESS
mv_udc_testmode(udc, && udc->usb_state != USB_STATE_DEFAULT)
setup->wIndex & 0xFF00, true); ep0_stall(udc);
else
mv_udc_testmode(udc, (setup->wIndex >> 8));
goto out; goto out;
break;
default: default:
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment