From: Vahram Aharonyan <vahr...@synopsys.com>

Check if endpoint is enabled during dwc2_hsotg_ep_disable() function
processing and call dwc2_hsotg_ep_stop_xfr() to disable it and flush
associated FIFO.

Move dwc2_hsotg_ep_stop_xfr() and dwc2_hsotg_wait_bit_set() functions
upper before dwc2_hsotg_ep_enable and dwc2_hsotg_ep_disable function
definitions.

Signed-off-by: Vahram Aharonyan <vahr...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/gadget.c | 182 +++++++++++++++++++++++-----------------------
 1 file changed, 93 insertions(+), 89 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 7da9f5d..ea8c010 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3590,6 +3590,95 @@ static irqreturn_t dwc2_hsotg_irq(int irq, void *pw)
        return IRQ_HANDLED;
 }
 
+static int dwc2_hsotg_wait_bit_set(struct dwc2_hsotg *hs_otg, u32 reg,
+                                  u32 bit, u32 timeout)
+{
+       u32 i;
+
+       for (i = 0; i < timeout; i++) {
+               if (dwc2_readl(hs_otg->regs + reg) & bit)
+                       return 0;
+               udelay(1);
+       }
+
+       return -ETIMEDOUT;
+}
+
+static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
+                                  struct dwc2_hsotg_ep *hs_ep)
+{
+       u32 epctrl_reg;
+       u32 epint_reg;
+
+       epctrl_reg = hs_ep->dir_in ? DIEPCTL(hs_ep->index) :
+               DOEPCTL(hs_ep->index);
+       epint_reg = hs_ep->dir_in ? DIEPINT(hs_ep->index) :
+               DOEPINT(hs_ep->index);
+
+       dev_dbg(hsotg->dev, "%s: stopping transfer on %s\n", __func__,
+               hs_ep->name);
+
+       if (hs_ep->dir_in) {
+               if (hsotg->dedicated_fifos || hs_ep->periodic) {
+                       __orr32(hsotg->regs + epctrl_reg, DXEPCTL_SNAK);
+                       /* Wait for Nak effect */
+                       if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg,
+                                                   DXEPINT_INEPNAKEFF, 100))
+                               dev_warn(hsotg->dev,
+                                        "%s: timeout DIEPINT.NAKEFF\n",
+                                        __func__);
+               } else {
+                       __orr32(hsotg->regs + DCTL, DCTL_SGNPINNAK);
+                       /* Wait for Nak effect */
+                       if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
+                                                   GINTSTS_GINNAKEFF, 100))
+                               dev_warn(hsotg->dev,
+                                        "%s: timeout GINTSTS.GINNAKEFF\n",
+                                        __func__);
+               }
+       } else {
+               if (!(dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_GOUTNAKEFF))
+                       __orr32(hsotg->regs + DCTL, DCTL_SGOUTNAK);
+
+               /* Wait for global nak to take effect */
+               if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
+                                           GINTSTS_GOUTNAKEFF, 100))
+                       dev_warn(hsotg->dev, "%s: timeout GINTSTS.GOUTNAKEFF\n",
+                                __func__);
+       }
+
+       /* Disable ep */
+       __orr32(hsotg->regs + epctrl_reg, DXEPCTL_EPDIS | DXEPCTL_SNAK);
+
+       /* Wait for ep to be disabled */
+       if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg, DXEPINT_EPDISBLD, 100))
+               dev_warn(hsotg->dev,
+                        "%s: timeout DOEPCTL.EPDisable\n", __func__);
+
+       /* Clear EPDISBLD interrupt */
+       __orr32(hsotg->regs + epint_reg, DXEPINT_EPDISBLD);
+
+       if (hs_ep->dir_in) {
+               unsigned short fifo_index;
+
+               if (hsotg->dedicated_fifos || hs_ep->periodic)
+                       fifo_index = hs_ep->fifo_index;
+               else
+                       fifo_index = 0;
+
+               /* Flush TX FIFO */
+               dwc2_flush_tx_fifo(hsotg, fifo_index);
+
+               /* Clear Global In NP NAK in Shared FIFO for non periodic ep */
+               if (!hsotg->dedicated_fifos && !hs_ep->periodic)
+                       __orr32(hsotg->regs + DCTL, DCTL_CGNPINNAK);
+
+       } else {
+               /* Remove global NAKs */
+               __orr32(hsotg->regs + DCTL, DCTL_CGOUTNAK);
+       }
+}
+
 /**
  * dwc2_hsotg_ep_enable - enable the given endpoint
  * @ep: The USB endpint to configure
@@ -3811,6 +3900,10 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
        spin_lock_irqsave(&hsotg->lock, flags);
 
        ctrl = dwc2_readl(hsotg->regs + epctrl_reg);
+
+       if (ctrl & DXEPCTL_EPENA)
+               dwc2_hsotg_ep_stop_xfr(hsotg, hs_ep);
+
        ctrl &= ~DXEPCTL_EPENA;
        ctrl &= ~DXEPCTL_USBACTEP;
        ctrl |= DXEPCTL_SNAK;
@@ -3849,95 +3942,6 @@ static bool on_list(struct dwc2_hsotg_ep *ep, struct 
dwc2_hsotg_req *test)
        return false;
 }
 
-static int dwc2_hsotg_wait_bit_set(struct dwc2_hsotg *hs_otg, u32 reg,
-                                                       u32 bit, u32 timeout)
-{
-       u32 i;
-
-       for (i = 0; i < timeout; i++) {
-               if (dwc2_readl(hs_otg->regs + reg) & bit)
-                       return 0;
-               udelay(1);
-       }
-
-       return -ETIMEDOUT;
-}
-
-static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
-                                               struct dwc2_hsotg_ep *hs_ep)
-{
-       u32 epctrl_reg;
-       u32 epint_reg;
-
-       epctrl_reg = hs_ep->dir_in ? DIEPCTL(hs_ep->index) :
-               DOEPCTL(hs_ep->index);
-       epint_reg = hs_ep->dir_in ? DIEPINT(hs_ep->index) :
-               DOEPINT(hs_ep->index);
-
-       dev_dbg(hsotg->dev, "%s: stopping transfer on %s\n", __func__,
-               hs_ep->name);
-
-       if (hs_ep->dir_in) {
-               if (hsotg->dedicated_fifos || hs_ep->periodic) {
-                       __orr32(hsotg->regs + epctrl_reg, DXEPCTL_SNAK);
-                       /* Wait for Nak effect */
-                       if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg,
-                                                   DXEPINT_INEPNAKEFF, 100))
-                               dev_warn(hsotg->dev,
-                                        "%s: timeout DIEPINT.NAKEFF\n",
-                                        __func__);
-               } else {
-                       __orr32(hsotg->regs + DCTL, DCTL_SGNPINNAK);
-                       /* Wait for Nak effect */
-                       if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
-                                                   GINTSTS_GINNAKEFF, 100))
-                               dev_warn(hsotg->dev,
-                                        "%s: timeout GINTSTS.GINNAKEFF\n",
-                                        __func__);
-               }
-       } else {
-               if (!(dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_GOUTNAKEFF))
-                       __orr32(hsotg->regs + DCTL, DCTL_SGOUTNAK);
-
-               /* Wait for global nak to take effect */
-               if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
-                                           GINTSTS_GOUTNAKEFF, 100))
-                       dev_warn(hsotg->dev, "%s: timeout GINTSTS.GOUTNAKEFF\n",
-                                __func__);
-       }
-
-       /* Disable ep */
-       __orr32(hsotg->regs + epctrl_reg, DXEPCTL_EPDIS | DXEPCTL_SNAK);
-
-       /* Wait for ep to be disabled */
-       if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg, DXEPINT_EPDISBLD, 100))
-               dev_warn(hsotg->dev,
-                        "%s: timeout DOEPCTL.EPDisable\n", __func__);
-
-       /* Clear EPDISBLD interrupt */
-       __orr32(hsotg->regs + epint_reg, DXEPINT_EPDISBLD);
-
-       if (hs_ep->dir_in) {
-               unsigned short fifo_index;
-
-               if (hsotg->dedicated_fifos || hs_ep->periodic)
-                       fifo_index = hs_ep->fifo_index;
-               else
-                       fifo_index = 0;
-
-               /* Flush TX FIFO */
-               dwc2_flush_tx_fifo(hsotg, fifo_index);
-
-               /* Clear Global In NP NAK in Shared FIFO for non periodic ep */
-               if (!hsotg->dedicated_fifos && !hs_ep->periodic)
-                       __orr32(hsotg->regs + DCTL, DCTL_CGNPINNAK);
-
-       } else {
-               /* Remove global NAKs */
-               __orr32(hsotg->regs + DCTL, DCTL_CGOUTNAK);
-       }
-}
-
 /**
  * dwc2_hsotg_ep_dequeue - dequeue given endpoint
  * @ep: The endpoint to dequeue.
-- 
2.10.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to