usb: musb: cppi41: improve rx channel abort routine
authorBin Liu <b-liu@ti.com>
Mon, 26 Jan 2015 22:22:07 +0000 (16:22 -0600)
committerFelipe Balbi <balbi@ti.com>
Tue, 27 Jan 2015 15:34:58 +0000 (09:34 -0600)
1. set AUTOREQ to NONE at the beginning of teardown;

2. add delay for dma pipeline to drain;

3. Do not set USB_TDOWN bit for RX teardown.

  The CPPI hw has an issue that when tearing down a RX channel, if
  another RX channel is receiving data, the CPPI will lockup.

  To workaround the issue, do not set the CPPI TD bit. The steps before
  this point ensures the CPPI channel will be torn down properly.

Signed-off-by: Bin Liu <b-liu@ti.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/musb/musb_cppi41.c

index 6af10e7e66a79e4d0aaa6cf041c870e2847c61bf..be84562d021b8c401f981c7f7a5a7c4551cd16bc 100644 (file)
@@ -549,10 +549,15 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel)
                csr &= ~MUSB_TXCSR_DMAENAB;
                musb_writew(epio, MUSB_TXCSR, csr);
        } else {
+               cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREQ_NONE);
+
                csr = musb_readw(epio, MUSB_RXCSR);
                csr &= ~(MUSB_RXCSR_H_REQPKT | MUSB_RXCSR_DMAENAB);
                musb_writew(epio, MUSB_RXCSR, csr);
 
+               /* wait to drain cppi dma pipe line */
+               udelay(50);
+
                csr = musb_readw(epio, MUSB_RXCSR);
                if (csr & MUSB_RXCSR_RXPKTRDY) {
                        csr |= MUSB_RXCSR_FLUSHFIFO;
@@ -566,13 +571,14 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel)
                tdbit <<= 16;
 
        do {
-               musb_writel(musb->ctrl_base, USB_TDOWN, tdbit);
+               if (is_tx)
+                       musb_writel(musb->ctrl_base, USB_TDOWN, tdbit);
                ret = dmaengine_terminate_all(cppi41_channel->dc);
        } while (ret == -EAGAIN);
 
-       musb_writel(musb->ctrl_base, USB_TDOWN, tdbit);
-
        if (is_tx) {
+               musb_writel(musb->ctrl_base, USB_TDOWN, tdbit);
+
                csr = musb_readw(epio, MUSB_TXCSR);
                if (csr & MUSB_TXCSR_TXPKTRDY) {
                        csr |= MUSB_TXCSR_FLUSHFIFO;