On 8/22/2016 12:49 AM, Felipe Balbi wrote:
> 
> Hi,
> 
> John Youn <[email protected]> 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 <[email protected]>
>> ---
>>  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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to