Implement the test modes mentioned in 7.1.20 section of USB 2.0 specification. High-speed capable devices must support these test modes to facilitate compliance testing. Signed-off-by: Pavankumar Kondeti <pkondeti@xxxxxxxxxxxxxx> Signed-off-by: Vamsi Krishna <vskrishn@xxxxxxxxxxxxxx> --- drivers/usb/gadget/msm72k_udc.c | 52 +++++++++++++++++++++++++++++++++++++- include/linux/usb/msm_hsusb_hw.h | 11 ++++++++ 2 files changed, 62 insertions(+), 1 deletions(-) diff --git a/drivers/usb/gadget/msm72k_udc.c b/drivers/usb/gadget/msm72k_udc.c index 51e9f2e..2b476a6 100644 --- a/drivers/usb/gadget/msm72k_udc.c +++ b/drivers/usb/gadget/msm72k_udc.c @@ -180,6 +180,7 @@ static void usb_do_work(struct work_struct *w); * @pclk: clock struct of usb_hs_pclk. * @ep0_dir: direction of ep0 setup data transfer. * @remote_wakeup: indicates remote wakeup capability enabled by host + * @test_mode: electrical test mode set by host * */ struct usb_info { @@ -223,6 +224,7 @@ struct usb_info { unsigned int ep0_dir; u8 remote_wakeup; + u16 test_mode; }; static const struct usb_ep_ops msm72k_ep_ops; @@ -571,11 +573,49 @@ static void ep0_queue_ack_complete(struct usb_ep *ep, struct usb_request *req) ep0_complete(ep, req); } +static void ep0_setup_ack_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct msm_endpoint *ept = to_msm_endpoint(ep); + struct usb_info *ui = ept->ui; + unsigned int temp; + + if (!ui->test_mode) + return; + + switch (ui->test_mode) { + case J_TEST: + dev_info(&ui->pdev->dev, "usb electrical test mode: (J)\n"); + temp = readl(USB_PORTSC) & (~PORTSC_PTC); + writel(temp | PORTSC_PTC_J_STATE, USB_PORTSC); + break; + + case K_TEST: + dev_info(&ui->pdev->dev, "usb electrical test mode: (K)\n"); + temp = readl(USB_PORTSC) & (~PORTSC_PTC); + writel(temp | PORTSC_PTC_K_STATE, USB_PORTSC); + break; + + case SE0_NAK_TEST: + dev_info(&ui->pdev->dev, "usb electrical test mode:" + "(SE0-NAK)\n"); + temp = readl(USB_PORTSC) & (~PORTSC_PTC); + writel(temp | PORTSC_PTC_SE0_NAK, USB_PORTSC); + break; + + case TST_PKT_TEST: + dev_info(&ui->pdev->dev, "usb electrical test mode:" + "(TEST_PKT)\n"); + temp = readl(USB_PORTSC) & (~PORTSC_PTC); + writel(temp | PORTSC_PTC_TST_PKT, USB_PORTSC); + break; + } +} + static void ep0_setup_ack(struct usb_info *ui) { struct usb_request *req = ui->setup_req; req->length = 0; - req->complete = 0; + req->complete = ep0_setup_ack_complete; usb_ept_queue_xfer(&ui->ep0in, req); } @@ -701,6 +741,16 @@ static void handle_setup(struct usb_info *ui) goto ack; } else if (ctl.bRequest == USB_REQ_SET_FEATURE) { switch (ctl.wValue) { + case USB_DEVICE_TEST_MODE: + switch (ctl.wIndex) { + case J_TEST: + case K_TEST: + case SE0_NAK_TEST: + case TST_PKT_TEST: + ui->test_mode = ctl.wIndex; + goto ack; + } + goto stall; case USB_DEVICE_REMOTE_WAKEUP: ui->remote_wakeup = 1; goto ack; diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h index 6f54268..743e6b9 100644 --- a/include/linux/usb/msm_hsusb_hw.h +++ b/include/linux/usb/msm_hsusb_hw.h @@ -175,6 +175,17 @@ struct ept_queue_item { #define PORTSC_FPR (1 << 6) #define PORTSC_SUSP (1 << 7) +/* test mode support */ +#define J_TEST (0x0100) +#define K_TEST (0x0200) +#define SE0_NAK_TEST (0x0300) +#define TST_PKT_TEST (0x0400) +#define PORTSC_PTC (0xf << 16) +#define PORTSC_PTC_J_STATE (0x01 << 16) +#define PORTSC_PTC_K_STATE (0x02 << 16) +#define PORTSC_PTC_SE0_NAK (0x03 << 16) +#define PORTSC_PTC_TST_PKT (0x04 << 16) + #define PORTSC_PTS_MASK (3 << 30) #define PORTSC_PTS_ULPI (2 << 30) #define PORTSC_PTS_SERIAL (3 << 30) -- 1.7.1 -- Sent by a consultant of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum. -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html