platform: msm_shared: Fix USB hang issue
Existing driver does not handle CLEAR_FEATURE request
from host, due to this the USB transactions hang as host
is expecting device to perform the CLEAR_FEATURE on requested
end point. Add support to handle End point CLEAR FEATURE.
CRs-Fixed: 600178
Change-Id: I269bf074a294bc30dac70a880e8c4c30038f8e88
diff --git a/include/dev/udc.h b/include/dev/udc.h
index 0dd1f86..f550410 100644
--- a/include/dev/udc.h
+++ b/include/dev/udc.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2009, Google Inc.
* All rights reserved.
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -120,6 +120,10 @@
#define PORTSC_PTC_SE0_NAK (0x03 << 16)
#define PORTSC_PTC_TST_PKT (0x4 << 16)
+#define USB_EP_NUM_MASK 0x0f
+#define USB_EP_DIR_MASK 0x80
+#define USB_EP_DIR_IN 0x80
+
struct setup_packet {
unsigned char type;
unsigned char request;
diff --git a/platform/msm_shared/usb30_udc.c b/platform/msm_shared/usb30_udc.c
index 072330b..765391e 100644
--- a/platform/msm_shared/usb30_udc.c
+++ b/platform/msm_shared/usb30_udc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -610,8 +610,40 @@
break;
case SETUP(ENDPOINT_WRITE, CLEAR_FEATURE):
{
- DBG("\n DEVICE_WRITE : CLEAR_FEATURE");
- goto stall;
+ uint8_t usb_epnum;
+ uint8_t dir;
+
+ DBG("\n ENDPOINT_WRITE : CLEAR_FEATURE");
+
+ /*
+ * setup packet received from the host has
+ * index field containing information about the USB
+ * endpoint as below:
+ * __________________________________
+ * | (7) | (6 - 4) | (3 - 0) |
+ * |DIR | Reserved | EP number |
+ * |______|_____________|_____________|
+ */
+ usb_epnum = (s.index & USB_EP_NUM_MASK);
+ dir = (s.index & USB_EP_DIR_MASK == USB_EP_DIR_IN) ? 0x1 : 0x0;
+
+ /*
+ * Convert the logical ep number to physical before
+ * sending the clear stall command.
+ * As per the data book we use fixed mapping as
+ * below:
+ * physical ep 0 --> logical ep0 OUT
+ * physical ep 1 --> logical ep0 IN
+ * physical ep 2 --> logical ep 1 OUT
+ * physical ep 3 --> logical ep 1 IN
+ * :
+ * :
+ * physical ep 30 --> logical ep 15 OUT
+ * physical ep 31 --> logical ep 15 IN
+ */
+ dwc_ep_cmd_clear_stall(dwc, DWC_EP_PHY_NUM(usb_epnum, dir));
+
+ return DWC_SETUP_2_STAGE;
}
break;
case SETUP(DEVICE_WRITE, SET_SEL):