summary refs log tree commit diff
path: root/drivers/usb/musb/musbhsdma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/musb/musbhsdma.c')
-rw-r--r--drivers/usb/musb/musbhsdma.c66
1 files changed, 38 insertions, 28 deletions
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 8662e9e159c3..5e83f96d6b77 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -195,30 +195,32 @@ static int dma_channel_abort(struct dma_channel *channel)
 	void __iomem *mbase = musb_channel->controller->base;
 
 	u8 bchannel = musb_channel->idx;
+	int offset;
 	u16 csr;
 
 	if (channel->status == MUSB_DMA_STATUS_BUSY) {
 		if (musb_channel->transmit) {
-
-			csr = musb_readw(mbase,
-				MUSB_EP_OFFSET(musb_channel->epnum,
-						MUSB_TXCSR));
-			csr &= ~(MUSB_TXCSR_AUTOSET |
-				 MUSB_TXCSR_DMAENAB |
-				 MUSB_TXCSR_DMAMODE);
-			musb_writew(mbase,
-				MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR),
-				csr);
+			offset = MUSB_EP_OFFSET(musb_channel->epnum,
+						MUSB_TXCSR);
+
+			/*
+			 * The programming guide says that we must clear
+			 * the DMAENAB bit before the DMAMODE bit...
+			 */
+			csr = musb_readw(mbase, offset);
+			csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
+			musb_writew(mbase, offset, csr);
+			csr &= ~MUSB_TXCSR_DMAMODE;
+			musb_writew(mbase, offset, csr);
 		} else {
-			csr = musb_readw(mbase,
-				MUSB_EP_OFFSET(musb_channel->epnum,
-						MUSB_RXCSR));
+			offset = MUSB_EP_OFFSET(musb_channel->epnum,
+						MUSB_RXCSR);
+
+			csr = musb_readw(mbase, offset);
 			csr &= ~(MUSB_RXCSR_AUTOCLEAR |
 				 MUSB_RXCSR_DMAENAB |
 				 MUSB_RXCSR_DMAMODE);
-			musb_writew(mbase,
-				MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR),
-				csr);
+			musb_writew(mbase, offset, csr);
 		}
 
 		musb_writew(mbase,
@@ -296,20 +298,28 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
 					&& ((channel->desired_mode == 0)
 					    || (channel->actual_len &
 					    (musb_channel->max_packet_sz - 1)))
-					 ) {
+				    ) {
+					u8  epnum  = musb_channel->epnum;
+					int offset = MUSB_EP_OFFSET(epnum,
+								    MUSB_TXCSR);
+					u16 txcsr;
+
+					/*
+					 * The programming guide says that we
+					 * must clear DMAENAB before DMAMODE.
+					 */
+					musb_ep_select(mbase, epnum);
+					txcsr = musb_readw(mbase, offset);
+					txcsr &= ~(MUSB_TXCSR_DMAENAB
+							| MUSB_TXCSR_AUTOSET);
+					musb_writew(mbase, offset, txcsr);
 					/* Send out the packet */
-					musb_ep_select(mbase,
-						musb_channel->epnum);
-					musb_writew(mbase, MUSB_EP_OFFSET(
-							musb_channel->epnum,
-							MUSB_TXCSR),
-						MUSB_TXCSR_TXPKTRDY);
-				} else {
-					musb_dma_completion(
-						musb,
-						musb_channel->epnum,
-						musb_channel->transmit);
+					txcsr &= ~MUSB_TXCSR_DMAMODE;
+					txcsr |=  MUSB_TXCSR_TXPKTRDY;
+					musb_writew(mbase, offset, txcsr);
 				}
+				musb_dma_completion(musb, musb_channel->epnum,
+						    musb_channel->transmit);
 			}
 		}
 	}