summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBin Liu <b-liu@ti.com>2015-01-26 16:22:07 -0600
committerFelipe Balbi <balbi@ti.com>2015-01-27 09:34:58 -0600
commitcb83df77f3ec151d68a1b6be957207e6fc7b7f50 (patch)
treed764ade173dcac614583c1ad6742b1a208601117
parent0149b07a9e28b0d8bd2fc1c238ffe7d530c2673f (diff)
downloadblackbird-op-linux-cb83df77f3ec151d68a1b6be957207e6fc7b7f50.tar.gz
blackbird-op-linux-cb83df77f3ec151d68a1b6be957207e6fc7b7f50.zip
usb: musb: cppi41: improve rx channel abort routine
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>
-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 6af10e7e66a7..be84562d021b 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -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;
OpenPOWER on IntegriCloud