we don't need to enable IRQs until we have
a gadget driver loaded and ready to work,
so let's delay IRQ enable to ->udc_start()
and IRQ disable to ->udc_stop().

While at that, also move the related use of
request_irq() and free_irq().

Tested-by: Vivek Gautam <gautam.vi...@samsung.com>
Signed-off-by: Felipe Balbi <ba...@ti.com>
---
 drivers/usb/dwc3/gadget.c | 80 ++++++++++++++++++++++++++---------------------
 1 file changed, 45 insertions(+), 35 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 65493b6..db20317 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1469,6 +1469,32 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
        return ret;
 }
 
+static void dwc3_gadget_enable_irq(struct dwc3 *dwc)
+{
+       u32                     reg;
+
+       /* Enable all but Start and End of Frame IRQs */
+       reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
+                       DWC3_DEVTEN_EVNTOVERFLOWEN |
+                       DWC3_DEVTEN_CMDCMPLTEN |
+                       DWC3_DEVTEN_ERRTICERREN |
+                       DWC3_DEVTEN_WKUPEVTEN |
+                       DWC3_DEVTEN_ULSTCNGEN |
+                       DWC3_DEVTEN_CONNECTDONEEN |
+                       DWC3_DEVTEN_USBRSTEN |
+                       DWC3_DEVTEN_DISCONNEVTEN);
+
+       dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
+}
+
+static void dwc3_gadget_disable_irq(struct dwc3 *dwc)
+{
+       /* mask all interrupts */
+       dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
+}
+
+static irqreturn_t dwc3_interrupt(int irq, void *_dwc);
+
 static int dwc3_gadget_start(struct usb_gadget *g,
                struct usb_gadget_driver *driver)
 {
@@ -1476,6 +1502,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        struct dwc3_ep          *dep;
        unsigned long           flags;
        int                     ret = 0;
+       int                     irq;
        u32                     reg;
 
        spin_lock_irqsave(&dwc->lock, flags);
@@ -1536,6 +1563,17 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        dwc->ep0state = EP0_SETUP_PHASE;
        dwc3_ep0_out_start(dwc);
 
+       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+       ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED,
+                       "dwc3", dwc);
+       if (ret) {
+               dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+                               irq, ret);
+               goto err1;
+       }
+
+       dwc3_gadget_enable_irq(dwc);
+
        spin_unlock_irqrestore(&dwc->lock, flags);
 
        return 0;
@@ -1554,9 +1592,14 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
 {
        struct dwc3             *dwc = gadget_to_dwc(g);
        unsigned long           flags;
+       int                     irq;
 
        spin_lock_irqsave(&dwc->lock, flags);
 
+       dwc3_gadget_disable_irq(dwc);
+       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+       free_irq(irq, dwc);
+
        __dwc3_gadget_ep_disable(dwc->eps[0]);
        __dwc3_gadget_ep_disable(dwc->eps[1]);
 
@@ -2454,7 +2497,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 {
        u32                                     reg;
        int                                     ret;
-       int                                     irq;
 
        dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
                        &dwc->ctrl_req_addr, GFP_KERNEL);
@@ -2510,33 +2552,11 @@ int dwc3_gadget_init(struct dwc3 *dwc)
        if (ret)
                goto err4;
 
-       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-
-       ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED,
-                       "dwc3", dwc);
-       if (ret) {
-               dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
-                               irq, ret);
-               goto err5;
-       }
-
        reg = dwc3_readl(dwc->regs, DWC3_DCFG);
        reg |= DWC3_DCFG_LPM_CAP;
        dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
-       /* Enable all but Start and End of Frame IRQs */
-       reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
-                       DWC3_DEVTEN_EVNTOVERFLOWEN |
-                       DWC3_DEVTEN_CMDCMPLTEN |
-                       DWC3_DEVTEN_ERRTICERREN |
-                       DWC3_DEVTEN_WKUPEVTEN |
-                       DWC3_DEVTEN_ULSTCNGEN |
-                       DWC3_DEVTEN_CONNECTDONEEN |
-                       DWC3_DEVTEN_USBRSTEN |
-                       DWC3_DEVTEN_DISCONNEVTEN);
-       dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
-
-       /* automatic phy suspend only on recent versions */
+       /* Enable USB2 LPM and automatic phy suspend only on recent versions */
        if (dwc->revision >= DWC3_REVISION_194A) {
                dwc3_gadget_usb2_phy_suspend(dwc, false);
                dwc3_gadget_usb3_phy_suspend(dwc, false);
@@ -2545,15 +2565,11 @@ int dwc3_gadget_init(struct dwc3 *dwc)
        ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
        if (ret) {
                dev_err(dwc->dev, "failed to register udc\n");
-               goto err6;
+               goto err5;
        }
 
        return 0;
 
-err6:
-       dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
-       free_irq(irq, dwc);
-
 err5:
        dwc3_gadget_free_endpoints(dwc);
 
@@ -2578,13 +2594,7 @@ err0:
 
 void dwc3_gadget_exit(struct dwc3 *dwc)
 {
-       int                     irq;
-
        usb_del_gadget_udc(&dwc->gadget);
-       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-
-       dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
-       free_irq(irq, dwc);
 
        dwc3_gadget_free_endpoints(dwc);
 
-- 
1.8.1.rc1.5.g7e0651a

--
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