168 lines
5.2 KiB
Diff
168 lines
5.2 KiB
Diff
From b91b067c531c9322f3719951b07303e790b13475 Mon Sep 17 00:00:00 2001
|
|
From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
|
|
Date: Fri, 27 Mar 2009 12:59:46 -0700
|
|
Subject: [PATCH] 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-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: only cppi_dma.c needs platform
|
|
device header, not cppi_dma.h ]
|
|
|
|
Signed-off-by: Dmitry Krivoschekov <dkrivoschekov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
|
|
Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
|
|
Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
|
|
---
|
|
drivers/usb/musb/cppi_dma.c | 34 +++++++++++++++++++++++++++++++---
|
|
drivers/usb/musb/cppi_dma.h | 6 ++++--
|
|
drivers/usb/musb/davinci.c | 14 ++++----------
|
|
3 files changed, 39 insertions(+), 15 deletions(-)
|
|
|
|
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
|
|
index ac7227c..6ff3c67 100644
|
|
--- a/drivers/usb/musb/cppi_dma.c
|
|
+++ b/drivers/usb/musb/cppi_dma.c
|
|
@@ -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;
|
|
@@ -1293,6 +1304,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. */
|
|
@@ -1300,6 +1313,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)
|
|
@@ -1330,6 +1346,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;
|
|
}
|
|
|
|
@@ -1342,6 +1367,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);
|
|
|
|
diff --git a/drivers/usb/musb/cppi_dma.h b/drivers/usb/musb/cppi_dma.h
|
|
index 729b407..8a39de3 100644
|
|
--- a/drivers/usb/musb/cppi_dma.h
|
|
+++ b/drivers/usb/musb/cppi_dma.h
|
|
@@ -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_ */
|
|
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
|
|
index 399c435..9fd74bf 100644
|
|
--- a/drivers/usb/musb/davinci.c
|
|
+++ b/drivers/usb/musb/davinci.c
|
|
@@ -250,6 +250,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);
|
|
@@ -266,16 +267,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);
|
|
--
|
|
1.6.0.4
|
|
|