musb: split out CPPI interrupt handler
Sergei Shtylyov [Fri, 27 Mar 2009 19:59:46 +0000 (12:59 -0700)]
As DaVinci DM646x has a dedicated CPPI DMA interrupt, replace
cppi_completion() (which has always been kind of layering
violation) by a complete CPPI interrupt handler.

[ dbrownell@users.sourceforge.net: only cppi_dma.c needs platform
device header, not cppi_dma.h ]

Signed-off-by: Dmitry Krivoschekov <dkrivoschekov@ru.mvista.com>
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

drivers/usb/musb/cppi_dma.c
drivers/usb/musb/cppi_dma.h
drivers/usb/musb/davinci.c

index 1976e9b..c3577bb 100644 (file)
@@ -6,6 +6,7 @@
  * The TUSB6020, using VLYNQ, has CPPI that looks much like DaVinci.
  */
 
+#include <linux/platform_device.h>
 #include <linux/usb.h>
 
 #include "musb_core.h"
@@ -1145,17 +1146,27 @@ static bool cppi_rx_scan(struct cppi *cppi, unsigned ch)
        return completed;
 }
 
-void cppi_completion(struct musb *musb, u32 rx, u32 tx)
+irqreturn_t cppi_interrupt(int irq, void *dev_id)
 {
-       void __iomem            *tibase;
-       int                     i, index;
+       struct musb             *musb = dev_id;
        struct cppi             *cppi;
+       void __iomem            *tibase;
        struct musb_hw_ep       *hw_ep = NULL;
+       u32                     rx, tx;
+       int                     i, index;
 
        cppi = container_of(musb->dma_controller, struct cppi, controller);
 
        tibase = musb->ctrl_base;
 
+       tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG);
+       rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG);
+
+       if (!tx && !rx)
+               return IRQ_NONE;
+
+       DBG(4, "CPPI IRQ Tx%x Rx%x\n", tx, rx);
+
        /* process TX channels */
        for (index = 0; tx; tx = tx >> 1, index++) {
                struct cppi_channel             *tx_ch;
@@ -1273,6 +1284,8 @@ void cppi_completion(struct musb *musb, u32 rx, u32 tx)
 
        /* write to CPPI EOI register to re-enable interrupts */
        musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0);
+
+       return IRQ_HANDLED;
 }
 
 /* Instantiate a software object representing a DMA controller. */
@@ -1280,6 +1293,9 @@ struct dma_controller *__init
 dma_controller_create(struct musb *musb, void __iomem *mregs)
 {
        struct cppi             *controller;
+       struct device           *dev = musb->controller;
+       struct platform_device  *pdev = to_platform_device(dev);
+       int                     irq = platform_get_irq(pdev, 1);
 
        controller = kzalloc(sizeof *controller, GFP_KERNEL);
        if (!controller)
@@ -1310,6 +1326,15 @@ dma_controller_create(struct musb *musb, void __iomem *mregs)
                return NULL;
        }
 
+       if (irq > 0) {
+               if (request_irq(irq, cppi_interrupt, 0, "cppi-dma", musb)) {
+                       dev_err(dev, "request_irq %d failed!\n", irq);
+                       dma_controller_destroy(&controller->controller);
+                       return NULL;
+               }
+               controller->irq = irq;
+       }
+
        return &controller->controller;
 }
 
@@ -1322,6 +1347,9 @@ void dma_controller_destroy(struct dma_controller *c)
 
        cppi = container_of(c, struct cppi, controller);
 
+       if (cppi->irq)
+               free_irq(cppi->irq, cppi->musb);
+
        /* assert:  caller stopped the controller first */
        dma_pool_destroy(cppi->pool);
 
index 729b407..8a39de3 100644 (file)
@@ -119,6 +119,8 @@ struct cppi {
        void __iomem                    *mregs;         /* Mentor regs */
        void __iomem                    *tibase;        /* TI/CPPI regs */
 
+       int                             irq;
+
        struct cppi_channel             tx[4];
        struct cppi_channel             rx[4];
 
@@ -127,7 +129,7 @@ struct cppi {
        struct list_head                tx_complete;
 };
 
-/* irq handling hook */
-extern void cppi_completion(struct musb *, u32 rx, u32 tx);
+/* CPPI IRQ handler */
+extern irqreturn_t cppi_interrupt(int, void *);
 
 #endif                         /* end of ifndef _CPPI_DMA_H_ */
index 898b52f..6e14e06 100644 (file)
@@ -265,6 +265,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
        irqreturn_t     retval = IRQ_NONE;
        struct musb     *musb = __hci;
        void __iomem    *tibase = musb->ctrl_base;
+       struct cppi     *cppi;
        u32             tmp;
 
        spin_lock_irqsave(&musb->lock, flags);
@@ -281,16 +282,9 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
        /* CPPI interrupts share the same IRQ line, but have their own
         * mask, state, "vector", and EOI registers.
         */
-       if (is_cppi_enabled()) {
-               u32 cppi_tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG);
-               u32 cppi_rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG);
-
-               if (cppi_tx || cppi_rx) {
-                       DBG(4, "CPPI IRQ t%x r%x\n", cppi_tx, cppi_rx);
-                       cppi_completion(musb, cppi_rx, cppi_tx);
-                       retval = IRQ_HANDLED;
-               }
-       }
+       cppi = container_of(musb->dma_controller, struct cppi, controller);
+       if (is_cppi_enabled() && musb->dma_controller && !cppi->irq)
+               retval = cppi_interrupt(irq, __hci);
 
        /* ack and handle non-CPPI interrupts */
        tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG);