summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBin Liu <b-liu@ti.com>2015-01-26 16:22:07 -0600
committerJiri Slaby <jslaby@suse.cz>2015-10-28 16:38:26 +0100
commitc387e4dad5ccd015a5185cfcfb103a20f9624321 (patch)
tree2ceb121c98982d4d58eed44a59ed57f11e746b67
parentec62e3efc3bd0fb0e464db4a0463e519d0737241 (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> Cc: Oliver Neukum <ONeukum@suse.com> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
-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 77b475a43dad..1c9c626248fd 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -507,10 +507,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;
@@ -524,13 +529,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;