diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/musb/cppi_dma.c | 22 | ||||
-rw-r--r-- | drivers/usb/musb/musb_host.c | 68 | ||||
-rw-r--r-- | drivers/usb/musb/musbhsdma.c | 7 |
3 files changed, 69 insertions, 28 deletions
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 569ef0fed0f6..30e24891ed62 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c | |||
@@ -1228,27 +1228,7 @@ void cppi_completion(struct musb *musb, u32 rx, u32 tx) | |||
1228 | 1228 | ||
1229 | hw_ep = tx_ch->hw_ep; | 1229 | hw_ep = tx_ch->hw_ep; |
1230 | 1230 | ||
1231 | /* Peripheral role never repurposes the | 1231 | musb_dma_completion(musb, index + 1, 1); |
1232 | * endpoint, so immediate completion is | ||
1233 | * safe. Host role waits for the fifo | ||
1234 | * to empty (TXPKTRDY irq) before going | ||
1235 | * to the next queued bulk transfer. | ||
1236 | */ | ||
1237 | if (is_host_active(cppi->musb)) { | ||
1238 | #if 0 | ||
1239 | /* WORKAROUND because we may | ||
1240 | * not always get TXKPTRDY ... | ||
1241 | */ | ||
1242 | int csr; | ||
1243 | |||
1244 | csr = musb_readw(hw_ep->regs, | ||
1245 | MUSB_TXCSR); | ||
1246 | if (csr & MUSB_TXCSR_TXPKTRDY) | ||
1247 | #endif | ||
1248 | completed = false; | ||
1249 | } | ||
1250 | if (completed) | ||
1251 | musb_dma_completion(musb, index + 1, 1); | ||
1252 | 1232 | ||
1253 | } else { | 1233 | } else { |
1254 | /* Bigger transfer than we could fit in | 1234 | /* Bigger transfer than we could fit in |
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) |
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 8662e9e159c3..de0e24203673 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c | |||
@@ -304,12 +304,9 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) | |||
304 | musb_channel->epnum, | 304 | musb_channel->epnum, |
305 | MUSB_TXCSR), | 305 | MUSB_TXCSR), |
306 | MUSB_TXCSR_TXPKTRDY); | 306 | MUSB_TXCSR_TXPKTRDY); |
307 | } else { | ||
308 | musb_dma_completion( | ||
309 | musb, | ||
310 | musb_channel->epnum, | ||
311 | musb_channel->transmit); | ||
312 | } | 307 | } |
308 | musb_dma_completion(musb, musb_channel->epnum, | ||
309 | musb_channel->transmit); | ||
313 | } | 310 | } |
314 | } | 311 | } |
315 | } | 312 | } |