usb: dwc2: WA for Full speed ISOC IN in DDMA mode.
authorArtur Petrosyan <Arthur.Petrosyan@synopsys.com>
Mon, 16 Apr 2018 12:45:31 +0000 (08:45 -0400)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Mon, 21 May 2018 07:36:14 +0000 (10:36 +0300)
By clearing NAK status of EP, core will send ZLP
to IN token and assert NAK interrupt relying
on TxFIFO status only.

The WA applies only to core versions from 2.72a
to 4.00a (including both). Also for FS_IOT_1.00a
and HS_IOT_1.00a.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/dwc2/core.h
drivers/usb/dwc2/gadget.c

index 6d304e91c20e78749f5bb7331f1195e71a528dab..4a56ac772a3c35360d3834f5542aad22d5b1b720 100644 (file)
@@ -1102,6 +1102,7 @@ struct dwc2_hsotg {
 
        /* DWC OTG HW Release versions */
 #define DWC2_CORE_REV_2_71a    0x4f54271a
+#define DWC2_CORE_REV_2_72a     0x4f54272a
 #define DWC2_CORE_REV_2_80a    0x4f54280a
 #define DWC2_CORE_REV_2_90a    0x4f54290a
 #define DWC2_CORE_REV_2_91a    0x4f54291a
@@ -1109,6 +1110,7 @@ struct dwc2_hsotg {
 #define DWC2_CORE_REV_2_94a    0x4f54294a
 #define DWC2_CORE_REV_3_00a    0x4f54300a
 #define DWC2_CORE_REV_3_10a    0x4f54310a
+#define DWC2_CORE_REV_4_00a    0x4f54400a
 #define DWC2_FS_IOT_REV_1_00a  0x5531100a
 #define DWC2_HS_IOT_REV_1_00a  0x5532100a
 
index 684b4f544c9b65e64b8eb0d20f582372c8b5093c..f0d9ccf1d665ad37b2f23786806bde8c16da11ea 100644 (file)
@@ -3945,6 +3945,27 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
        if (index && !hs_ep->isochronous)
                epctrl |= DXEPCTL_SETD0PID;
 
+       /* WA for Full speed ISOC IN in DDMA mode.
+        * By Clear NAK status of EP, core will send ZLP
+        * to IN token and assert NAK interrupt relying
+        * on TxFIFO status only
+        */
+
+       if (hsotg->gadget.speed == USB_SPEED_FULL &&
+           hs_ep->isochronous && dir_in) {
+               /* The WA applies only to core versions from 2.72a
+                * to 4.00a (including both). Also for FS_IOT_1.00a
+                * and HS_IOT_1.00a.
+                */
+               u32 gsnpsid = dwc2_readl(hsotg->regs + GSNPSID);
+
+               if ((gsnpsid >= DWC2_CORE_REV_2_72a &&
+                    gsnpsid <= DWC2_CORE_REV_4_00a) ||
+                    gsnpsid == DWC2_FS_IOT_REV_1_00a ||
+                    gsnpsid == DWC2_HS_IOT_REV_1_00a)
+                       epctrl |= DXEPCTL_CNAK;
+       }
+
        dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n",
                __func__, epctrl);