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: 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>
This commit is contained in:
parent
c9cd06b3d6
commit
91e9c4fec7
|
@ -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);
|
||||
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue