diff options
Diffstat (limited to 'drivers/usb/musb/musb_gadget.c')
-rw-r--r-- | drivers/usb/musb/musb_gadget.c | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index c7ebd0867fcc..f79440cdfe7e 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c | |||
@@ -165,9 +165,15 @@ static void nuke(struct musb_ep *ep, const int status) | |||
165 | if (is_dma_capable() && ep->dma) { | 165 | if (is_dma_capable() && ep->dma) { |
166 | struct dma_controller *c = ep->musb->dma_controller; | 166 | struct dma_controller *c = ep->musb->dma_controller; |
167 | int value; | 167 | int value; |
168 | |||
168 | if (ep->is_in) { | 169 | if (ep->is_in) { |
170 | /* | ||
171 | * The programming guide says that we must not clear | ||
172 | * the DMAMODE bit before DMAENAB, so we only | ||
173 | * clear it in the second write... | ||
174 | */ | ||
169 | musb_writew(epio, MUSB_TXCSR, | 175 | musb_writew(epio, MUSB_TXCSR, |
170 | 0 | MUSB_TXCSR_FLUSHFIFO); | 176 | MUSB_TXCSR_DMAMODE | MUSB_TXCSR_FLUSHFIFO); |
171 | musb_writew(epio, MUSB_TXCSR, | 177 | musb_writew(epio, MUSB_TXCSR, |
172 | 0 | MUSB_TXCSR_FLUSHFIFO); | 178 | 0 | MUSB_TXCSR_FLUSHFIFO); |
173 | } else { | 179 | } else { |
@@ -230,7 +236,7 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep) | |||
230 | | IN token(s) are recd from Host. | 236 | | IN token(s) are recd from Host. |
231 | | -> DMA interrupt on completion | 237 | | -> DMA interrupt on completion |
232 | | calls TxAvail. | 238 | | calls TxAvail. |
233 | | -> stop DMA, ~DmaEenab, | 239 | | -> stop DMA, ~DMAENAB, |
234 | | -> set TxPktRdy for last short pkt or zlp | 240 | | -> set TxPktRdy for last short pkt or zlp |
235 | | -> Complete Request | 241 | | -> Complete Request |
236 | | -> Continue next request (call txstate) | 242 | | -> Continue next request (call txstate) |
@@ -315,9 +321,17 @@ static void txstate(struct musb *musb, struct musb_request *req) | |||
315 | request->dma, request_size); | 321 | request->dma, request_size); |
316 | if (use_dma) { | 322 | if (use_dma) { |
317 | if (musb_ep->dma->desired_mode == 0) { | 323 | if (musb_ep->dma->desired_mode == 0) { |
318 | /* ASSERT: DMAENAB is clear */ | 324 | /* |
319 | csr &= ~(MUSB_TXCSR_AUTOSET | | 325 | * We must not clear the DMAMODE bit |
320 | MUSB_TXCSR_DMAMODE); | 326 | * before the DMAENAB bit -- and the |
327 | * latter doesn't always get cleared | ||
328 | * before we get here... | ||
329 | */ | ||
330 | csr &= ~(MUSB_TXCSR_AUTOSET | ||
331 | | MUSB_TXCSR_DMAENAB); | ||
332 | musb_writew(epio, MUSB_TXCSR, csr | ||
333 | | MUSB_TXCSR_P_WZC_BITS); | ||
334 | csr &= ~MUSB_TXCSR_DMAMODE; | ||
321 | csr |= (MUSB_TXCSR_DMAENAB | | 335 | csr |= (MUSB_TXCSR_DMAENAB | |
322 | MUSB_TXCSR_MODE); | 336 | MUSB_TXCSR_MODE); |
323 | /* against programming guide */ | 337 | /* against programming guide */ |
@@ -334,10 +348,7 @@ static void txstate(struct musb *musb, struct musb_request *req) | |||
334 | 348 | ||
335 | #elif defined(CONFIG_USB_TI_CPPI_DMA) | 349 | #elif defined(CONFIG_USB_TI_CPPI_DMA) |
336 | /* program endpoint CSR first, then setup DMA */ | 350 | /* program endpoint CSR first, then setup DMA */ |
337 | csr &= ~(MUSB_TXCSR_AUTOSET | 351 | csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY); |
338 | | MUSB_TXCSR_DMAMODE | ||
339 | | MUSB_TXCSR_P_UNDERRUN | ||
340 | | MUSB_TXCSR_TXPKTRDY); | ||
341 | csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB; | 352 | csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB; |
342 | musb_writew(epio, MUSB_TXCSR, | 353 | musb_writew(epio, MUSB_TXCSR, |
343 | (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN) | 354 | (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN) |
@@ -364,8 +375,8 @@ static void txstate(struct musb *musb, struct musb_request *req) | |||
364 | if (!use_dma) { | 375 | if (!use_dma) { |
365 | c->channel_release(musb_ep->dma); | 376 | c->channel_release(musb_ep->dma); |
366 | musb_ep->dma = NULL; | 377 | musb_ep->dma = NULL; |
367 | /* ASSERT: DMAENAB clear */ | 378 | csr &= ~MUSB_TXCSR_DMAENAB; |
368 | csr &= ~(MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE); | 379 | musb_writew(epio, MUSB_TXCSR, csr); |
369 | /* invariant: prequest->buf is non-null */ | 380 | /* invariant: prequest->buf is non-null */ |
370 | } | 381 | } |
371 | #elif defined(CONFIG_USB_TUSB_OMAP_DMA) | 382 | #elif defined(CONFIG_USB_TUSB_OMAP_DMA) |