|
@@ -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)
|
|
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;
|
|
|
|
- int i, index;
|
|
|
|
|
|
+ struct musb *musb = dev_id;
|
|
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)
|
|
|
|
|
|
/* 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
|
|
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)
|
|
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)
|
|
|
|
|
|
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);
|
|
|
|
|