diff options
Diffstat (limited to 'drivers/usb/musb/musb_host.c')
-rw-r--r-- | drivers/usb/musb/musb_host.c | 68 |
1 files changed, 66 insertions, 2 deletions
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 521fd83f5b9d..518abfca1243 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * Copyright 2005 Mentor Graphics Corporation | 4 | * Copyright 2005 Mentor Graphics Corporation |
5 | * Copyright (C) 2005-2006 by Texas Instruments | 5 | * Copyright (C) 2005-2006 by Texas Instruments |
6 | * Copyright (C) 2006-2007 Nokia Corporation | 6 | * Copyright (C) 2006-2007 Nokia Corporation |
7 | * Copyright (C) 2008-2009 MontaVista Software, Inc. <source@mvista.com> | ||
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License | 10 | * modify it under the terms of the GNU General Public License |
@@ -168,13 +169,15 @@ static inline void musb_h_tx_start(struct musb_hw_ep *ep) | |||
168 | 169 | ||
169 | } | 170 | } |
170 | 171 | ||
171 | static inline void cppi_host_txdma_start(struct musb_hw_ep *ep) | 172 | static inline void musb_h_tx_dma_start(struct musb_hw_ep *ep) |
172 | { | 173 | { |
173 | u16 txcsr; | 174 | u16 txcsr; |
174 | 175 | ||
175 | /* NOTE: no locks here; caller should lock and select EP */ | 176 | /* NOTE: no locks here; caller should lock and select EP */ |
176 | txcsr = musb_readw(ep->regs, MUSB_TXCSR); | 177 | txcsr = musb_readw(ep->regs, MUSB_TXCSR); |
177 | txcsr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_H_WZC_BITS; | 178 | txcsr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_H_WZC_BITS; |
179 | if (is_cppi_enabled()) | ||
180 | txcsr |= MUSB_TXCSR_DMAMODE; | ||
178 | musb_writew(ep->regs, MUSB_TXCSR, txcsr); | 181 | musb_writew(ep->regs, MUSB_TXCSR, txcsr); |
179 | } | 182 | } |
180 | 183 | ||
@@ -279,7 +282,7 @@ start: | |||
279 | if (!hw_ep->tx_channel) | 282 | if (!hw_ep->tx_channel) |
280 | musb_h_tx_start(hw_ep); | 283 | musb_h_tx_start(hw_ep); |
281 | else if (is_cppi_enabled() || tusb_dma_omap()) | 284 | else if (is_cppi_enabled() || tusb_dma_omap()) |
282 | cppi_host_txdma_start(hw_ep); | 285 | musb_h_tx_dma_start(hw_ep); |
283 | } | 286 | } |
284 | } | 287 | } |
285 | 288 | ||
@@ -1250,6 +1253,67 @@ void musb_host_tx(struct musb *musb, u8 epnum) | |||
1250 | 1253 | ||
1251 | } | 1254 | } |
1252 | 1255 | ||
1256 | if (is_dma_capable() && dma && !status) { | ||
1257 | /* | ||
1258 | * DMA has completed. But if we're using DMA mode 1 (multi | ||
1259 | * packet DMA), we need a terminal TXPKTRDY interrupt before | ||
1260 | * we can consider this transfer completed, lest we trash | ||
1261 | * its last packet when writing the next URB's data. So we | ||
1262 | * switch back to mode 0 to get that interrupt; we'll come | ||
1263 | * back here once it happens. | ||
1264 | */ | ||
1265 | if (tx_csr & MUSB_TXCSR_DMAMODE) { | ||
1266 | /* | ||
1267 | * We shouldn't clear DMAMODE with DMAENAB set; so | ||
1268 | * clear them in a safe order. That should be OK | ||
1269 | * once TXPKTRDY has been set (and I've never seen | ||
1270 | * it being 0 at this moment -- DMA interrupt latency | ||
1271 | * is significant) but if it hasn't been then we have | ||
1272 | * no choice but to stop being polite and ignore the | ||
1273 | * programmer's guide... :-) | ||
1274 | * | ||
1275 | * Note that we must write TXCSR with TXPKTRDY cleared | ||
1276 | * in order not to re-trigger the packet send (this bit | ||
1277 | * can't be cleared by CPU), and there's another caveat: | ||
1278 | * TXPKTRDY may be set shortly and then cleared in the | ||
1279 | * double-buffered FIFO mode, so we do an extra TXCSR | ||
1280 | * read for debouncing... | ||
1281 | */ | ||
1282 | tx_csr &= musb_readw(epio, MUSB_TXCSR); | ||
1283 | if (tx_csr & MUSB_TXCSR_TXPKTRDY) { | ||
1284 | tx_csr &= ~(MUSB_TXCSR_DMAENAB | | ||
1285 | MUSB_TXCSR_TXPKTRDY); | ||
1286 | musb_writew(epio, MUSB_TXCSR, | ||
1287 | tx_csr | MUSB_TXCSR_H_WZC_BITS); | ||
1288 | } | ||
1289 | tx_csr &= ~(MUSB_TXCSR_DMAMODE | | ||
1290 | MUSB_TXCSR_TXPKTRDY); | ||
1291 | musb_writew(epio, MUSB_TXCSR, | ||
1292 | tx_csr | MUSB_TXCSR_H_WZC_BITS); | ||
1293 | |||
1294 | /* | ||
1295 | * There is no guarantee that we'll get an interrupt | ||
1296 | * after clearing DMAMODE as we might have done this | ||
1297 | * too late (after TXPKTRDY was cleared by controller). | ||
1298 | * Re-read TXCSR as we have spoiled its previous value. | ||
1299 | */ | ||
1300 | tx_csr = musb_readw(epio, MUSB_TXCSR); | ||
1301 | } | ||
1302 | |||
1303 | /* | ||
1304 | * We may get here from a DMA completion or TXPKTRDY interrupt. | ||
1305 | * In any case, we must check the FIFO status here and bail out | ||
1306 | * only if the FIFO still has data -- that should prevent the | ||
1307 | * "missed" TXPKTRDY interrupts and deal with double-buffered | ||
1308 | * FIFO mode too... | ||
1309 | */ | ||
1310 | if (tx_csr & (MUSB_TXCSR_FIFONOTEMPTY | MUSB_TXCSR_TXPKTRDY)) { | ||
1311 | DBG(2, "DMA complete but packet still in FIFO, " | ||
1312 | "CSR %04x\n", tx_csr); | ||
1313 | return; | ||
1314 | } | ||
1315 | } | ||
1316 | |||
1253 | /* REVISIT this looks wrong... */ | 1317 | /* REVISIT this looks wrong... */ |
1254 | if (!status || dma || usb_pipeisoc(pipe)) { | 1318 | if (!status || dma || usb_pipeisoc(pipe)) { |
1255 | if (dma) | 1319 | if (dma) |