summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBin Liu <b-liu@ti.com>2015-01-26 16:22:07 -0600
committerBen Hutchings <ben@decadent.org.uk>2017-10-12 15:28:16 +0100
commit7dc5d81848092f2a7ceb252db83e1cf3e2f29bb7 (patch)
treebc8360cbd7c6d4012e1d9e7b92999e80f84f276c
parente8a4f7cbb13068b7aaf358e3754d249c7a0b70f8 (diff)
usb: musb: cppi41: improve rx channel abort routine
commit cb83df77f3ec151d68a1b6be957207e6fc7b7f50 upstream. 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> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rw-r--r--drivers/usb/musb/musb_cppi41.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c
index 1403a128b356..d8315638e825 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -570,10 +570,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;
@@ -587,13 +592,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;