Commit 91e9c4fe authored by Sergei Shtylyov's avatar Sergei Shtylyov Committed by Greg Kroah-Hartman

musb: split out CPPI interrupt handler

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: default avatarDmitry Krivoschekov <dkrivoschekov@ru.mvista.com>
Signed-off-by: default avatarSergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c9cd06b3
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* The TUSB6020, using VLYNQ, has CPPI that looks much like DaVinci. * The TUSB6020, using VLYNQ, has CPPI that looks much like DaVinci.
*/ */
#include <linux/platform_device.h>
#include <linux/usb.h> #include <linux/usb.h>
#include "musb_core.h" #include "musb_core.h"
...@@ -1145,17 +1146,27 @@ static bool cppi_rx_scan(struct cppi *cppi, unsigned ch) ...@@ -1145,17 +1146,27 @@ static bool cppi_rx_scan(struct cppi *cppi, unsigned ch)
return completed; return completed;
} }
void cppi_completion(struct musb *musb, u32 rx, u32 tx) irqreturn_t cppi_interrupt(int irq, void *dev_id)
{ {
void __iomem *tibase; struct musb *musb = dev_id;
int i, index;
struct cppi *cppi; struct cppi *cppi;
void __iomem *tibase;
struct musb_hw_ep *hw_ep = NULL; struct musb_hw_ep *hw_ep = NULL;
u32 rx, tx;
int i, index;
cppi = container_of(musb->dma_controller, struct cppi, controller); cppi = container_of(musb->dma_controller, struct cppi, controller);
tibase = musb->ctrl_base; 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 */ /* process TX channels */
for (index = 0; tx; tx = tx >> 1, index++) { for (index = 0; tx; tx = tx >> 1, index++) {
struct cppi_channel *tx_ch; struct cppi_channel *tx_ch;
...@@ -1273,6 +1284,8 @@ void cppi_completion(struct musb *musb, u32 rx, u32 tx) ...@@ -1273,6 +1284,8 @@ void cppi_completion(struct musb *musb, u32 rx, u32 tx)
/* write to CPPI EOI register to re-enable interrupts */ /* write to CPPI EOI register to re-enable interrupts */
musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0); musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0);
return IRQ_HANDLED;
} }
/* Instantiate a software object representing a DMA controller. */ /* Instantiate a software object representing a DMA controller. */
...@@ -1280,6 +1293,9 @@ struct dma_controller *__init ...@@ -1280,6 +1293,9 @@ struct dma_controller *__init
dma_controller_create(struct musb *musb, void __iomem *mregs) dma_controller_create(struct musb *musb, void __iomem *mregs)
{ {
struct cppi *controller; 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); controller = kzalloc(sizeof *controller, GFP_KERNEL);
if (!controller) if (!controller)
...@@ -1310,6 +1326,15 @@ dma_controller_create(struct musb *musb, void __iomem *mregs) ...@@ -1310,6 +1326,15 @@ dma_controller_create(struct musb *musb, void __iomem *mregs)
return NULL; 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; return &controller->controller;
} }
...@@ -1322,6 +1347,9 @@ void dma_controller_destroy(struct dma_controller *c) ...@@ -1322,6 +1347,9 @@ void dma_controller_destroy(struct dma_controller *c)
cppi = container_of(c, struct cppi, controller); cppi = container_of(c, struct cppi, controller);
if (cppi->irq)
free_irq(cppi->irq, cppi->musb);
/* assert: caller stopped the controller first */ /* assert: caller stopped the controller first */
dma_pool_destroy(cppi->pool); dma_pool_destroy(cppi->pool);
......
...@@ -119,6 +119,8 @@ struct cppi { ...@@ -119,6 +119,8 @@ struct cppi {
void __iomem *mregs; /* Mentor regs */ void __iomem *mregs; /* Mentor regs */
void __iomem *tibase; /* TI/CPPI regs */ void __iomem *tibase; /* TI/CPPI regs */
int irq;
struct cppi_channel tx[4]; struct cppi_channel tx[4];
struct cppi_channel rx[4]; struct cppi_channel rx[4];
...@@ -127,7 +129,7 @@ struct cppi { ...@@ -127,7 +129,7 @@ struct cppi {
struct list_head tx_complete; struct list_head tx_complete;
}; };
/* irq handling hook */ /* CPPI IRQ handler */
extern void cppi_completion(struct musb *, u32 rx, u32 tx); extern irqreturn_t cppi_interrupt(int, void *);
#endif /* end of ifndef _CPPI_DMA_H_ */ #endif /* end of ifndef _CPPI_DMA_H_ */
...@@ -265,6 +265,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) ...@@ -265,6 +265,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
irqreturn_t retval = IRQ_NONE; irqreturn_t retval = IRQ_NONE;
struct musb *musb = __hci; struct musb *musb = __hci;
void __iomem *tibase = musb->ctrl_base; void __iomem *tibase = musb->ctrl_base;
struct cppi *cppi;
u32 tmp; u32 tmp;
spin_lock_irqsave(&musb->lock, flags); spin_lock_irqsave(&musb->lock, flags);
...@@ -281,16 +282,9 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) ...@@ -281,16 +282,9 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
/* CPPI interrupts share the same IRQ line, but have their own /* CPPI interrupts share the same IRQ line, but have their own
* mask, state, "vector", and EOI registers. * mask, state, "vector", and EOI registers.
*/ */
if (is_cppi_enabled()) { cppi = container_of(musb->dma_controller, struct cppi, controller);
u32 cppi_tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG); if (is_cppi_enabled() && musb->dma_controller && !cppi->irq)
u32 cppi_rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG); retval = cppi_interrupt(irq, __hci);
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;
}
}
/* ack and handle non-CPPI interrupts */ /* ack and handle non-CPPI interrupts */
tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG); tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment