On 8/22/2016 12:49 AM, Felipe Balbi wrote: > > Hi, > > John Youn <johnyoun@xxxxxxxxxxxx> writes: >> 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@xxxxxxxxxxxx> >> --- >> drivers/usb/dwc3/core.c | 11 +++++++++++ >> drivers/usb/dwc3/core.h | 4 ++++ >> drivers/usb/dwc3/gadget.c | 31 ++++++++++++++++++++++++++++++- >> 3 files changed, 45 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c >> index 71ac7c2..057739d 100644 >> --- a/drivers/usb/dwc3/core.c >> +++ b/drivers/usb/dwc3/core.c >> @@ -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: >> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h >> index 002e647..b2317e7 100644 >> --- a/drivers/usb/dwc3/core.h >> +++ b/drivers/usb/dwc3/core.h >> @@ -109,6 +109,7 @@ >> #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 >> @@ -288,6 +289,9 @@ >> #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) >> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c >> index c6fe9a3..823e65d 100644 >> --- a/drivers/usb/dwc3/gadget.c >> +++ b/drivers/usb/dwc3/gadget.c >> @@ -2202,6 +2202,7 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force) >> struct dwc3_gadget_ep_cmd_params params; >> u32 cmd; >> int ret; >> + unsigned int timeout; >> >> dep = dwc->eps[epnum]; >> >> @@ -2225,6 +2226,14 @@ 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 mode is NOT available on the DWC_usb31 IP. >> */ >> >> cmd = DWC3_DEPCMD_ENDTRANSFER; >> @@ -2236,7 +2245,27 @@ 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); >> + return; >> + } >> + >> + timeout = 100; >> + >> + do { >> + cmd = dwc3_readl(dep->regs, DWC3_DEPCMD); >> + if (!(cmd & DWC3_DEPCMD_CMDACT)) >> + break; > > we're already polling CMDACT bit when we send the command. Do we _need_ > to poll it again? Seems like the check above for running udelay(100) is > enough. Just remove the return call from there. You're right. I missed that. We just need the check. > >> + timeout--; >> + if (!timeout) { >> + dev_err(dwc->dev, "EndTransfer didn't complete\n"); >> + break; >> + } >> + >> + udelay(1); >> + } while (1); > > not into infinite loops, actually :-) See my recent patches removing > these infinite loops and udelay(1) calls. > Ok. Regards, John -- 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