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):