DMA programming on DaVinci

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Sergei,

on DaVinci is extremely necessary to program EP CSR before
channel_program() ? I believe it's not a problem for the OMAP-based
board and I doubt it's a problem for Blackfin too.

I think it would be easy to drop all the DMA magic if we figure out a
way to program DMA that works for all engines. Possibly following what
MUSB docs say would be enough:

. Program EP CSR
. Program DMA ADDR and COUNT
. Program DMA Control

So it would be something like:

>From 586d9ea1b0417640877c201fdb88d2d555b8c174 Mon Sep 17 00:00:00 2001
From: Felipe Balbi <balbi@xxxxxx>
Date: Wed, 12 Jan 2011 12:50:24 +0200
Subject: [PATCH] usb: musb: gadget: drop DMA ifdeffery
Organization: Texas Instruments\n

MUSB DMA programming can be done in a simpler
way if we drop all the DMA magic.

NYET-Signed-off-by: Felipe Balbi <balbi@xxxxxx>
---

Completely untested, just looking at the code. Didn't even compile this
one.

 drivers/usb/musb/musb_gadget.c |  149 +++++++++------------------------------
 1 files changed, 35 insertions(+), 114 deletions(-)

diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 9b162df..d6aca24 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -347,87 +347,53 @@ static void txstate(struct musb *musb, struct musb_request *req)
 
 		/* MUSB_TXCSR_P_ISO is still set correctly */
 
-#ifdef CONFIG_USB_INVENTRA_DMA
-		{
-			if (request_size < musb_ep->packet_sz)
-				musb_ep->dma->desired_mode = 0;
-			else
-				musb_ep->dma->desired_mode = 1;
-
-			use_dma = use_dma && c->channel_program(
-					musb_ep->dma, musb_ep->packet_sz,
-					musb_ep->dma->desired_mode,
-					request->dma + request->actual, request_size);
-			if (use_dma) {
-				if (musb_ep->dma->desired_mode == 0) {
-					/*
-					 * We must not clear the DMAMODE bit
-					 * before the DMAENAB bit -- and the
-					 * latter doesn't always get cleared
-					 * before we get here...
-					 */
-					csr &= ~(MUSB_TXCSR_AUTOSET
-						| MUSB_TXCSR_DMAENAB);
-					musb_writew(epio, MUSB_TXCSR, csr
-						| MUSB_TXCSR_P_WZC_BITS);
-					csr &= ~MUSB_TXCSR_DMAMODE;
-					csr |= (MUSB_TXCSR_DMAENAB |
-							MUSB_TXCSR_MODE);
-					/* against programming guide */
-				} else {
-					csr |= (MUSB_TXCSR_DMAENAB
-							| MUSB_TXCSR_DMAMODE
-							| MUSB_TXCSR_MODE);
-					if (!musb_ep->hb_mult)
-						csr |= MUSB_TXCSR_AUTOSET;
-				}
-				csr &= ~MUSB_TXCSR_P_UNDERRUN;
+		if (request_size < musb_ep->packet_sz)
+			musb_ep->dma->desired_mode = 0;
+		else
+			musb_ep->dma->desired_mode = 1;
 
-				musb_writew(epio, MUSB_TXCSR, csr);
-			}
+		if (musb_ep->dma->desired_mode == 0) {
+			/*
+			 * We must not clear the DMAMODE bit
+			 * before the DMAENAB bit -- and the
+			 * latter doesn't always get cleared
+			 * before we get here...
+			 */
+			csr &= ~(MUSB_TXCSR_AUTOSET
+					| MUSB_TXCSR_DMAENAB);
+			musb_writew(epio, MUSB_TXCSR, csr
+					| MUSB_TXCSR_P_WZC_BITS);
+			csr &= ~MUSB_TXCSR_DMAMODE;
+			csr |= (MUSB_TXCSR_DMAENAB |
+					MUSB_TXCSR_MODE);
+			/* against programming guide */
+		} else {
+			csr |= (MUSB_TXCSR_DMAENAB
+					| MUSB_TXCSR_DMAMODE
+					| MUSB_TXCSR_MODE);
+			if (!musb_ep->hb_mult)
+				csr |= MUSB_TXCSR_AUTOSET;
 		}
+		csr &= ~MUSB_TXCSR_P_UNDERRUN;
 
-#elif defined(CONFIG_USB_TI_CPPI_DMA)
-		/* program endpoint CSR first, then setup DMA */
-		csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
-		csr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE |
-		       MUSB_TXCSR_MODE;
-		musb_writew(epio, MUSB_TXCSR,
-			(MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN)
-				| csr);
-
-		/* ensure writebuffer is empty */
-		csr = musb_readw(epio, MUSB_TXCSR);
-
-		/* NOTE host side sets DMAENAB later than this; both are
-		 * OK since the transfer dma glue (between CPPI and Mentor
-		 * fifos) just tells CPPI it could start.  Data only moves
-		 * to the USB TX fifo when both fifos are ready.
-		 */
+		musb_writew(epio, MUSB_TXCSR, csr);
 
-		/* "mode" is irrelevant here; handle terminating ZLPs like
-		 * PIO does, since the hardware RNDIS mode seems unreliable
-		 * except for the last-packet-is-already-short case.
-		 */
 		use_dma = use_dma && c->channel_program(
 				musb_ep->dma, musb_ep->packet_sz,
-				0,
-				request->dma + request->actual,
-				request_size);
+				musb_ep->dma->desired_mode,
+				request->dma + request->actual, request_size);
 		if (!use_dma) {
 			c->channel_release(musb_ep->dma);
 			musb_ep->dma = NULL;
 			csr &= ~MUSB_TXCSR_DMAENAB;
 			musb_writew(epio, MUSB_TXCSR, csr);
-			/* invariant: prequest->buf is non-null */
+
+			/* Case we enabled mode1 DMA, disable it */
+			if (musb_ep->dma->desired_mode) {
+				csr &= ~MUSB_TXCSR_DMAMODE;
+				musb_writew(epio, MUSB_TXCSR, csr);
+			}
 		}
-#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
-		use_dma = use_dma && c->channel_program(
-				musb_ep->dma, musb_ep->packet_sz,
-				request->zero,
-				request->dma + request->actual,
-				request_size);
-#endif
 	}
 #endif
 
@@ -627,37 +593,9 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 		return;
 	}
 
-	if (is_cppi_enabled() && musb_ep->dma) {
-		struct dma_controller	*c = musb->dma_controller;
-		struct dma_channel	*channel = musb_ep->dma;
-
-		/* NOTE:  CPPI won't actually stop advancing the DMA
-		 * queue after short packet transfers, so this is almost
-		 * always going to run as IRQ-per-packet DMA so that
-		 * faults will be handled correctly.
-		 */
-		if (c->channel_program(channel,
-				musb_ep->packet_sz,
-				!request->short_not_ok,
-				request->dma + request->actual,
-				request->length - request->actual)) {
-
-			/* make sure that if an rxpkt arrived after the irq,
-			 * the cppi engine will be ready to take it as soon
-			 * as DMA is enabled
-			 */
-			csr &= ~(MUSB_RXCSR_AUTOCLEAR
-					| MUSB_RXCSR_DMAMODE);
-			csr |= MUSB_RXCSR_DMAENAB | MUSB_RXCSR_P_WZC_BITS;
-			musb_writew(epio, MUSB_RXCSR, csr);
-			return;
-		}
-	}
-
 	if (csr & MUSB_RXCSR_RXPKTRDY) {
 		len = musb_readw(epio, MUSB_RXCOUNT);
 		if (request->actual < request->length) {
-#ifdef CONFIG_USB_INVENTRA_DMA
 			if (is_dma_capable() && musb_ep->dma) {
 				struct dma_controller	*c;
 				struct dma_channel	*channel;
@@ -731,7 +669,6 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 				if (use_dma)
 					return;
 			}
-#endif	/* Mentor's DMA */
 
 			fifo_count = request->length - request->actual;
 			DBG(3, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n",
@@ -741,22 +678,6 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 
 			fifo_count = min_t(unsigned, len, fifo_count);
 
-#ifdef	CONFIG_USB_TUSB_OMAP_DMA
-			if (tusb_dma_omap() && musb_ep->dma) {
-				struct dma_controller *c = musb->dma_controller;
-				struct dma_channel *channel = musb_ep->dma;
-				u32 dma_addr = request->dma + request->actual;
-				int ret;
-
-				ret = c->channel_program(channel,
-						musb_ep->packet_sz,
-						channel->desired_mode,
-						dma_addr,
-						fifo_count);
-				if (ret)
-					return;
-			}
-#endif
 			/*
 			 * Unmap the dma buffer back to cpu if dma channel
 			 * programming fails. This buffer is mapped if the
-- 
1.7.3.4.598.g85356

if something like this works for DaVinci, then we can easily drop all
ifdeffery and we drop quite some patches from Ming's series.

-- 
balbi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux