usb: designware: cleanup irq handler

rockbox-gerrit-noreply--- via rockbox-cvs <[email protected]> Mon, 25 May 2026 07:39:07 -0400
Newsgroups gmane.comp.systems.archos.rockbox.cvs
Message-ID <[email protected]>
commit 64b1f09e06e074ce0f3c12f722e4259512d6fff9
Author: mojyack <[email protected]>
Date:   Fri Jan 23 10:31:00 2026 +0900

    usb: designware: cleanup irq handler
    
    Change-Id: Ic1926a8277d32721e3c736472dfc41a57ba0d433

diff --git a/firmware/drivers/usb-designware.c b/firmware/drivers/usb-designware.c
index 9968778dde..8f69815294 100644
--- a/firmware/drivers/usb-designware.c
+++ b/firmware/drivers/usb-designware.c
@@ -1133,29 +1133,106 @@ static void usb_dw_handle_token_mismatch(void)
 }
 #endif /* USB_DW_SHARED_FIFO */
 
+static void usb_dw_iepint(int ep)
+{
+    uint32_t epints = DWC_DIEPINT(ep);
+    DWC_DIEPINT(ep) = epints;
+
+    if (epints & TOC)
+    {
+        usb_dw_abort_endpoint(ep, USB_DW_EPDIR_IN);
+    }
+
+#ifdef USB_DW_SHARED_FIFO
+    if (epints & ITTXFE)
+    {
+        if (epmis_msk & (1 << ep))
+        {
+            DWC_DIEPCTL(ep) |= EPENA;
+            epmis_msk &= ~(1 << ep);
+            if (!epmis_msk)
+                DWC_DIEPMSK &= ~ITTXFE;
+        }
+    }
+
+#elif defined(USB_DW_ARCH_SLAVE)
+    if (epints & TXFE)
+    {
+        usb_dw_handle_dtxfifo(ep);
+    }
+#endif
+
+    if (epints & XFRC)
+    {
+        usb_dw_handle_xfer_complete(ep, USB_DW_EPDIR_IN);
+    }
+}
+
+static void usb_dw_oepint(int ep)
+{
+    uint32_t epints = DWC_DOEPINT(ep);
+    DWC_DOEPINT(ep) = epints;
+
+    if (!ep)
+    {
+        if (epints & STUP)
+        {
+            usb_dw_handle_setup_received();
+        }
+
+        if (epints & XFRC)
+        {
+            if(epints & STATUSRECVD)
+            {
+                /* At the end of a control write's data phase, the
+                 * controller writes a spurious OUTDONE token to the
+                 * FIFO and raises StatusRecvd | XferCompl.
+                 *
+                 * We do not need or want this -- we've already handled
+                 * the data phase by this point -- but EP0 is stopped
+                 * as a side effect of XferCompl, so we need to restart
+                 * it to keep receiving packets. */
+                usb_dw_ep0_recv();
+            }
+            else if(!(epints & SETUPRECVD))
+            {
+                /* Only call this for normal data packets. Setup
+                 * packets use the STUP interrupt handler instead. */
+                usb_dw_handle_xfer_complete(0, USB_DW_EPDIR_OUT);
+            }
+        }
+    }
+    else
+    {
+        if (epints & XFRC)
+        {
+            usb_dw_handle_xfer_complete(ep, USB_DW_EPDIR_OUT);
+        }
+    }
+}
+
 static void usb_dw_irq(void)
 {
     int ep;
-    uint32_t daint;
+    uint32_t gintsts = DWC_GINTSTS & DWC_GINTMSK;
 
 #ifdef USB_DW_ARCH_SLAVE
     /* Handle one packet at a time, the IRQ will re-trigger if there's
        something left. */
-    if (DWC_GINTSTS & RXFLVL)
+    if (gintsts & RXFLVL)
     {
         usb_dw_handle_rxfifo();
     }
 #endif
 
 #ifdef USB_DW_SHARED_FIFO
-    if (DWC_GINTSTS & EPMIS)
+    if (gintsts & EPMIS)
     {
         usb_dw_handle_token_mismatch();
         DWC_GINTSTS = EPMIS;
     }
 
 #ifdef USB_DW_ARCH_SLAVE
-    uint32_t gintsts = DWC_GINTSTS & DWC_GINTMSK;
     if (gintsts & PTXFE)
     {
         /* First disable the IRQ, it will be re-enabled later if there
@@ -1180,99 +1257,29 @@ static void usb_dw_irq(void)
 #endif /* USB_DW_ARCH_SLAVE */
 #endif /* USB_DW_SHARED_FIFO */
 
-    daint = DWC_DAINT;
-
-    /* IN */
-    for (ep = 0; ep < USB_NUM_ENDPOINTS; ep++)
+    if (gintsts & (OEPINT | IEPINT))
     {
-        if (daint & (1 << ep))
+        uint32_t daint = DWC_DAINT & DWC_DAINTMSK;
+        uint32_t daint_out = daint >> 16;
+        uint32_t daint_in = daint & 0xffff;
+        for (ep = 0; ep < USB_NUM_ENDPOINTS && daint_in; ep++, daint_in >>= 1)
         {
-            uint32_t epints = DWC_DIEPINT(ep);
-
-            if (epints & TOC)
-            {
-                usb_dw_abort_endpoint(ep, USB_DW_EPDIR_IN);
-            }
-
-#ifdef USB_DW_SHARED_FIFO
-            if (epints & ITTXFE)
-            {
-                if (epmis_msk & (1 << ep))
-                {
-                    DWC_DIEPCTL(ep) |= EPENA;
-                    epmis_msk &= ~(1 << ep);
-                    if (!epmis_msk)
-                        DWC_DIEPMSK &= ~ITTXFE;
-                }
-            }
-
-#elif defined(USB_DW_ARCH_SLAVE)
-            if (epints & TXFE)
+            if (daint_in & 1)
             {
-                usb_dw_handle_dtxfifo(ep);
-            }
-#endif
-
-            /* Clear XFRC here, if this is a 'multi-transfer' request then
-               a new transfer is going to be launched, this ensures it will
-               not miss a single interrupt. */
-            DWC_DIEPINT(ep) = epints;
-
-            if (epints & XFRC)
-            {
-                usb_dw_handle_xfer_complete(ep, USB_DW_EPDIR_IN);
+                usb_dw_iepint(ep);
             }
         }
-    }
 
-    /* OUT */
-    for (ep = 0; ep < USB_NUM_ENDPOINTS; ep++)
-    {
-        if (daint & (1 << (ep + 16)))
+        for (ep = 0; ep < USB_NUM_ENDPOINTS && daint_out; ep++, daint_out >>= 1)
         {
-            uint32_t epints = DWC_DOEPINT(ep);
-            DWC_DOEPINT(ep) = epints;
-
-            if (!ep)
-            {
-                if (epints & STUP)
-                {
-                    usb_dw_handle_setup_received();
-                }
-
-                if (epints & XFRC)
-                {
-                    if(epints & STATUSRECVD)
-                    {
-                        /* At the end of a control write's data phase, the
-                         * controller writes a spurious OUTDONE token to the
-                         * FIFO and raises StatusRecvd | XferCompl.
-                         *
-                         * We do not need or want this -- we've already handled
-                         * the data phase by this point -- but EP0 is stopped
-                         * as a side effect of XferCompl, so we need to restart
-                         * it to keep receiving packets. */
-                        usb_dw_ep0_recv();
-                    }
-                    else if(!(epints & SETUPRECVD))
-                    {
-                        /* Only call this for normal data packets. Setup
-                         * packets use the STUP interrupt handler instead. */
-                        usb_dw_handle_xfer_complete(0, USB_DW_EPDIR_OUT);
-                    }
-                }
-            }
-            else
+            if (daint_out & 1)
             {
-                if (epints & XFRC)
-                {
-                    usb_dw_handle_xfer_complete(ep, USB_DW_EPDIR_OUT);
-                }
+                usb_dw_oepint(ep);
             }
         }
     }
 
-    if (DWC_GINTSTS & USBRST)
+    if (gintsts & USBRST)
     {
         DWC_GINTSTS = USBRST;
         usb_dw_set_address(0);
@@ -1280,7 +1287,7 @@ static void usb_dw_irq(void)
         usb_core_bus_reset();
     }
 
-    if (DWC_GINTSTS & ENUMDNE)
+    if (gintsts & ENUMDNE)
     {
         DWC_GINTSTS = ENUMDNE;
         ep0.state = EP0_SETUP;
-- 
rockbox-cvs mailing list
[email protected]
https://lists.haxx.se/mailman/listinfo/rockbox-cvs