diff options
Diffstat (limited to 'drivers/usb/musb/cppi_dma.c')
-rw-r--r-- | drivers/usb/musb/cppi_dma.c | 40 |
1 files changed, 17 insertions, 23 deletions
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index ef2332a9941d..59dc3d351b60 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c | |||
@@ -7,6 +7,7 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/platform_device.h> | 9 | #include <linux/platform_device.h> |
10 | #include <linux/slab.h> | ||
10 | #include <linux/usb.h> | 11 | #include <linux/usb.h> |
11 | 12 | ||
12 | #include "musb_core.h" | 13 | #include "musb_core.h" |
@@ -1154,8 +1155,11 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id) | |||
1154 | struct musb_hw_ep *hw_ep = NULL; | 1155 | struct musb_hw_ep *hw_ep = NULL; |
1155 | u32 rx, tx; | 1156 | u32 rx, tx; |
1156 | int i, index; | 1157 | int i, index; |
1158 | unsigned long flags; | ||
1157 | 1159 | ||
1158 | cppi = container_of(musb->dma_controller, struct cppi, controller); | 1160 | cppi = container_of(musb->dma_controller, struct cppi, controller); |
1161 | if (cppi->irq) | ||
1162 | spin_lock_irqsave(&musb->lock, flags); | ||
1159 | 1163 | ||
1160 | tibase = musb->ctrl_base; | 1164 | tibase = musb->ctrl_base; |
1161 | 1165 | ||
@@ -1188,8 +1192,13 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id) | |||
1188 | 1192 | ||
1189 | bd = tx_ch->head; | 1193 | bd = tx_ch->head; |
1190 | 1194 | ||
1195 | /* | ||
1196 | * If Head is null then this could mean that a abort interrupt | ||
1197 | * that needs to be acknowledged. | ||
1198 | */ | ||
1191 | if (NULL == bd) { | 1199 | if (NULL == bd) { |
1192 | DBG(1, "null BD\n"); | 1200 | DBG(1, "null BD\n"); |
1201 | tx_ram->tx_complete = 0; | ||
1193 | continue; | 1202 | continue; |
1194 | } | 1203 | } |
1195 | 1204 | ||
@@ -1285,6 +1294,9 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id) | |||
1285 | /* write to CPPI EOI register to re-enable interrupts */ | 1294 | /* write to CPPI EOI register to re-enable interrupts */ |
1286 | musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0); | 1295 | musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0); |
1287 | 1296 | ||
1297 | if (cppi->irq) | ||
1298 | spin_unlock_irqrestore(&musb->lock, flags); | ||
1299 | |||
1288 | return IRQ_HANDLED; | 1300 | return IRQ_HANDLED; |
1289 | } | 1301 | } |
1290 | 1302 | ||
@@ -1406,15 +1418,6 @@ static int cppi_channel_abort(struct dma_channel *channel) | |||
1406 | 1418 | ||
1407 | if (cppi_ch->transmit) { | 1419 | if (cppi_ch->transmit) { |
1408 | struct cppi_tx_stateram __iomem *tx_ram; | 1420 | struct cppi_tx_stateram __iomem *tx_ram; |
1409 | int enabled; | ||
1410 | |||
1411 | /* mask interrupts raised to signal teardown complete. */ | ||
1412 | enabled = musb_readl(tibase, DAVINCI_TXCPPI_INTENAB_REG) | ||
1413 | & (1 << cppi_ch->index); | ||
1414 | if (enabled) | ||
1415 | musb_writel(tibase, DAVINCI_TXCPPI_INTCLR_REG, | ||
1416 | (1 << cppi_ch->index)); | ||
1417 | |||
1418 | /* REVISIT put timeouts on these controller handshakes */ | 1421 | /* REVISIT put timeouts on these controller handshakes */ |
1419 | 1422 | ||
1420 | cppi_dump_tx(6, cppi_ch, " (teardown)"); | 1423 | cppi_dump_tx(6, cppi_ch, " (teardown)"); |
@@ -1429,7 +1432,6 @@ static int cppi_channel_abort(struct dma_channel *channel) | |||
1429 | do { | 1432 | do { |
1430 | value = musb_readl(&tx_ram->tx_complete, 0); | 1433 | value = musb_readl(&tx_ram->tx_complete, 0); |
1431 | } while (0xFFFFFFFC != value); | 1434 | } while (0xFFFFFFFC != value); |
1432 | musb_writel(&tx_ram->tx_complete, 0, 0xFFFFFFFC); | ||
1433 | 1435 | ||
1434 | /* FIXME clean up the transfer state ... here? | 1436 | /* FIXME clean up the transfer state ... here? |
1435 | * the completion routine should get called with | 1437 | * the completion routine should get called with |
@@ -1442,23 +1444,15 @@ static int cppi_channel_abort(struct dma_channel *channel) | |||
1442 | musb_writew(regs, MUSB_TXCSR, value); | 1444 | musb_writew(regs, MUSB_TXCSR, value); |
1443 | musb_writew(regs, MUSB_TXCSR, value); | 1445 | musb_writew(regs, MUSB_TXCSR, value); |
1444 | 1446 | ||
1445 | /* While we scrub the TX state RAM, ensure that we clean | 1447 | /* |
1446 | * up any interrupt that's currently asserted: | ||
1447 | * 1. Write to completion Ptr value 0x1(bit 0 set) | 1448 | * 1. Write to completion Ptr value 0x1(bit 0 set) |
1448 | * (write back mode) | 1449 | * (write back mode) |
1449 | * 2. Write to completion Ptr value 0x0(bit 0 cleared) | 1450 | * 2. Wait for abort interrupt and then put the channel in |
1450 | * (compare mode) | 1451 | * compare mode by writing 1 to the tx_complete register. |
1451 | * Value written is compared(for bits 31:2) and when | ||
1452 | * equal, interrupt is deasserted. | ||
1453 | */ | 1452 | */ |
1454 | cppi_reset_tx(tx_ram, 1); | 1453 | cppi_reset_tx(tx_ram, 1); |
1455 | musb_writel(&tx_ram->tx_complete, 0, 0); | 1454 | cppi_ch->head = 0; |
1456 | 1455 | musb_writel(&tx_ram->tx_complete, 0, 1); | |
1457 | /* re-enable interrupt */ | ||
1458 | if (enabled) | ||
1459 | musb_writel(tibase, DAVINCI_TXCPPI_INTENAB_REG, | ||
1460 | (1 << cppi_ch->index)); | ||
1461 | |||
1462 | cppi_dump_tx(5, cppi_ch, " (done teardown)"); | 1456 | cppi_dump_tx(5, cppi_ch, " (done teardown)"); |
1463 | 1457 | ||
1464 | /* REVISIT tx side _should_ clean up the same way | 1458 | /* REVISIT tx side _should_ clean up the same way |