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. Signed-off-by: Dmitry Krivoschekov <dkrivoschekov@xxxxxxxxxxxxx> Signed-off-by: Sergei Shtylyov <sshtylyov@xxxxxxxxxxxxx> --- The patch is against the recent DaVinci tree; untested... drivers/usb/musb/cppi_dma.c | 33 ++++++++++++++++++++++++++++++--- drivers/usb/musb/cppi_dma.h | 7 +++++-- drivers/usb/musb/davinci.c | 14 ++++---------- 3 files changed, 39 insertions(+), 15 deletions(-) Index: linux-davinci/drivers/usb/musb/cppi_dma.c =================================================================== --- linux-davinci.orig/drivers/usb/musb/cppi_dma.c +++ linux-davinci/drivers/usb/musb/cppi_dma.c @@ -1144,17 +1144,27 @@ static bool cppi_rx_scan(struct cppi *cp 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; @@ -1292,6 +1302,8 @@ void cppi_completion(struct musb *musb, /* 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. */ @@ -1299,6 +1311,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) @@ -1329,6 +1344,15 @@ dma_controller_create(struct musb *musb, 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; } @@ -1341,6 +1365,9 @@ void dma_controller_destroy(struct dma_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: linux-davinci/drivers/usb/musb/cppi_dma.h =================================================================== --- linux-davinci.orig/drivers/usb/musb/cppi_dma.h +++ linux-davinci/drivers/usb/musb/cppi_dma.h @@ -8,6 +8,7 @@ #include <linux/smp_lock.h> #include <linux/errno.h> #include <linux/dmapool.h> +#include <linux/platform_device.h> #include "musb_dma.h" #include "musb_core.h" @@ -119,6 +120,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 +130,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: linux-davinci/drivers/usb/musb/davinci.c =================================================================== --- linux-davinci.orig/drivers/usb/musb/davinci.c +++ linux-davinci/drivers/usb/musb/davinci.c @@ -266,6 +266,7 @@ static irqreturn_t davinci_interrupt(int 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); @@ -282,16 +283,9 @@ static irqreturn_t davinci_interrupt(int /* 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); -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html