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. > + 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. -- balbi
Attachment:
signature.asc
Description: PGP signature