Starting from DWC_usb31 version 1.90a and later, the DCTL.CSFRST bit
will not be cleared until after all the internal clocks are synchronized
during soft-reset. This may take a little more than 50ms. Set the
polling rate at 20ms instead.

Signed-off-by: Thinh Nguyen <thi...@synopsys.com>
---
 drivers/usb/dwc3/core.c | 23 ++++++++++++++++++-----
 drivers/usb/dwc3/core.h |  2 ++
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 98bce85c29d0..252c397860ef 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -252,12 +252,25 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
        reg |= DWC3_DCTL_CSFTRST;
        dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 
+       /*
+        * For DWC_usb31 controller 1.90a and later, the DCTL.CSFRST bit
+        * is cleared only after all the clocks are synchronized. This can
+        * take a little more than 50ms. Set the polling rate at 20ms
+        * for 10 times instead.
+        */
+       if (dwc3_is_usb31(dwc) && dwc->revision >= DWC3_USB31_REVISION_190A)
+               retries = 10;
+
        do {
                reg = dwc3_readl(dwc->regs, DWC3_DCTL);
                if (!(reg & DWC3_DCTL_CSFTRST))
                        goto done;
 
-               udelay(1);
+               if (dwc3_is_usb31(dwc) &&
+                   dwc->revision >= DWC3_USB31_REVISION_190A)
+                       msleep(20);
+               else
+                       udelay(1);
        } while (--retries);
 
        phy_exit(dwc->usb3_generic_phy);
@@ -267,11 +280,11 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
 
 done:
        /*
-        * For DWC_usb31 controller, once DWC3_DCTL_CSFTRST bit is cleared,
-        * we must wait at least 50ms before accessing the PHY domain
-        * (synchronization delay). DWC_usb31 programming guide section 1.3.2.
+        * For DWC_usb31 controller 1.80a and prior, once DCTL.CSFRST bit
+        * is cleared, we must wait at least 50ms before accessing the PHY
+        * domain (synchronization delay).
         */
-       if (dwc3_is_usb31(dwc))
+       if (dwc3_is_usb31(dwc) && dwc->revision <= DWC3_USB31_REVISION_180A)
                msleep(50);
 
        return 0;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 3dd783b889cb..1c8b349379af 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1137,6 +1137,8 @@ struct dwc3 {
 #define DWC3_USB31_REVISION_120A       (0x3132302a | DWC3_REVISION_IS_DWC31)
 #define DWC3_USB31_REVISION_160A       (0x3136302a | DWC3_REVISION_IS_DWC31)
 #define DWC3_USB31_REVISION_170A       (0x3137302a | DWC3_REVISION_IS_DWC31)
+#define DWC3_USB31_REVISION_180A       (0x3138302a | DWC3_REVISION_IS_DWC31)
+#define DWC3_USB31_REVISION_190A       (0x3139302a | DWC3_REVISION_IS_DWC31)
 
        u32                     version_type;
 
-- 
2.11.0

Reply via email to