usb: dwc3: Add ENDXFER command polling
authorJohn Youn <johnyoun@synopsys.com>
Mon, 22 Aug 2016 22:39:13 +0000 (15:39 -0700)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Thu, 25 Aug 2016 09:13:19 +0000 (12:13 +0300)
ENDXFER polling is available on version 3.10a and later of the
DWC_usb3 (USB 3.0) controller. With this feature, the software can poll
the CMDACT bit in the DEPCMD register after issuing an ENDXFER command.
This feature is enabled by writing GUCTL2[14].

This feature is NOT available on the DWC_usb31 (USB 3.1) IP.

Signed-off-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/gadget.c

index 25e424e404624bc19a48a3537ecaec99ceee9c65..d6d3fa0fa5285855425d2999b19465c1cb51625d 100644 (file)
@@ -704,6 +704,17 @@ static int dwc3_core_init(struct dwc3 *dwc)
                break;
        }
 
+       /*
+        * ENDXFER polling is available on version 3.10a and later of
+        * the DWC_usb3 controller. It is NOT available in the
+        * DWC_usb31 controller.
+        */
+       if (!dwc3_is_usb31(dwc) && dwc->revision >= DWC3_REVISION_310A) {
+               reg = dwc3_readl(dwc->regs, DWC3_GUCTL2);
+               reg |= DWC3_GUCTL2_RST_ACTBITLATER;
+               dwc3_writel(dwc->regs, DWC3_GUCTL2, reg);
+       }
+
        return 0;
 
 err4:
index 002e6477d586ff287425b92d1c4a8cc5bb22b6f9..b2317e702f57a532e4fe8be7a04a6ef372fd41c6 100644 (file)
 #define DWC3_GPRTBIMAP_HS1     0xc184
 #define DWC3_GPRTBIMAP_FS0     0xc188
 #define DWC3_GPRTBIMAP_FS1     0xc18c
+#define DWC3_GUCTL2            0xc19c
 
 #define DWC3_VER_NUMBER                0xc1a0
 #define DWC3_VER_TYPE          0xc1a4
 #define DWC3_GFLADJ_30MHZ_SDBND_SEL            (1 << 7)
 #define DWC3_GFLADJ_30MHZ_MASK                 0x3f
 
+/* Global User Control Register 2 */
+#define DWC3_GUCTL2_RST_ACTBITLATER            (1 << 14)
+
 /* Device Configuration Register */
 #define DWC3_DCFG_DEVADDR(addr)        ((addr) << 3)
 #define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f)
index 0288ea99c85ae1a383bc7f8f5387dc6ba09c7f76..161a6bfcb84e10b3b94d31262def5b0d5c4976a4 100644 (file)
@@ -2228,6 +2228,18 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force)
         *
         * - Issue EndTransfer WITH CMDIOC bit set
         * - Wait 100us
+        *
+        * As of IP version 3.10a of the DWC_usb3 IP, the controller
+        * supports a mode to work around the above limitation. The
+        * software can poll the CMDACT bit in the DEPCMD register
+        * after issuing a EndTransfer command. This mode is enabled
+        * by writing GUCTL2[14]. This polling is already done in the
+        * dwc3_send_gadget_ep_cmd() function so if the mode is
+        * enabled, the EndTransfer command will have completed upon
+        * returning from this function and we don't need to delay for
+        * 100us.
+        *
+        * This mode is NOT available on the DWC_usb31 IP.
         */
 
        cmd = DWC3_DEPCMD_ENDTRANSFER;
@@ -2239,7 +2251,9 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force)
        WARN_ON_ONCE(ret);
        dep->resource_index = 0;
        dep->flags &= ~DWC3_EP_BUSY;
-       udelay(100);
+
+       if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A)
+               udelay(100);
 }
 
 static void dwc3_stop_active_transfers(struct dwc3 *dwc)