浏览代码

usb: dwc3: Add ENDXFER command polling

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>
John Youn 9 年之前
父节点
当前提交
06281d460f
共有 3 个文件被更改,包括 30 次插入1 次删除
  1. 11 0
      drivers/usb/dwc3/core.c
  2. 4 0
      drivers/usb/dwc3/core.h
  3. 15 1
      drivers/usb/dwc3/gadget.c

+ 11 - 0
drivers/usb/dwc3/core.c

@@ -704,6 +704,17 @@ static int dwc3_core_init(struct dwc3 *dwc)
 		break;
 		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;
 	return 0;
 
 
 err4:
 err4:

+ 4 - 0
drivers/usb/dwc3/core.h

@@ -109,6 +109,7 @@
 #define DWC3_GPRTBIMAP_HS1	0xc184
 #define DWC3_GPRTBIMAP_HS1	0xc184
 #define DWC3_GPRTBIMAP_FS0	0xc188
 #define DWC3_GPRTBIMAP_FS0	0xc188
 #define DWC3_GPRTBIMAP_FS1	0xc18c
 #define DWC3_GPRTBIMAP_FS1	0xc18c
+#define DWC3_GUCTL2		0xc19c
 
 
 #define DWC3_VER_NUMBER		0xc1a0
 #define DWC3_VER_NUMBER		0xc1a0
 #define DWC3_VER_TYPE		0xc1a4
 #define DWC3_VER_TYPE		0xc1a4
@@ -288,6 +289,9 @@
 #define DWC3_GFLADJ_30MHZ_SDBND_SEL		(1 << 7)
 #define DWC3_GFLADJ_30MHZ_SDBND_SEL		(1 << 7)
 #define DWC3_GFLADJ_30MHZ_MASK			0x3f
 #define DWC3_GFLADJ_30MHZ_MASK			0x3f
 
 
+/* Global User Control Register 2 */
+#define DWC3_GUCTL2_RST_ACTBITLATER		(1 << 14)
+
 /* Device Configuration Register */
 /* Device Configuration Register */
 #define DWC3_DCFG_DEVADDR(addr)	((addr) << 3)
 #define DWC3_DCFG_DEVADDR(addr)	((addr) << 3)
 #define DWC3_DCFG_DEVADDR_MASK	DWC3_DCFG_DEVADDR(0x7f)
 #define DWC3_DCFG_DEVADDR_MASK	DWC3_DCFG_DEVADDR(0x7f)

+ 15 - 1
drivers/usb/dwc3/gadget.c

@@ -2228,6 +2228,18 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force)
 	 *
 	 *
 	 * - Issue EndTransfer WITH CMDIOC bit set
 	 * - Issue EndTransfer WITH CMDIOC bit set
 	 * - Wait 100us
 	 * - 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;
 	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);
 	WARN_ON_ONCE(ret);
 	dep->resource_index = 0;
 	dep->resource_index = 0;
 	dep->flags &= ~DWC3_EP_BUSY;
 	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)
 static void dwc3_stop_active_transfers(struct dwc3 *dwc)