PERFORCE change 180502 for review

Jakub Wojciech Klama jceel at FreeBSD.org
Mon Jul 5 21:17:32 UTC 2010


http://p4web.freebsd.org/@@180502?ac=10

Change 180502 by jceel at jceel on 2010/07/05 21:17:11

	* Add support for linked transfers in EDMA3 driver
	* Some cosmeting and style(9) changes

Affected files ...

.. //depot/projects/soc2010/jceel_dma/sys/arm/davinci/davinci_edma.c#4 edit
.. //depot/projects/soc2010/jceel_dma/sys/arm/davinci/davinci_edmareg.h#4 edit

Differences ...

==== //depot/projects/soc2010/jceel_dma/sys/arm/davinci/davinci_edma.c#4 (text+ko) ====

@@ -86,8 +86,11 @@
 	int				dc_chno;
 	int				dc_status;
 #define	CHANNEL_ACTIVE			1
+#define	CHANNEL_ACTIVE_LINKED		2
 #define	CHANNEL_IDLE			0
+	int				dc_laststatus;
 	struct dmae_transfer *		dc_xfer;
+	struct dmae_transfer *		dc_linkxfer;
 };
 
 struct davinci_edma_softc {
@@ -131,6 +134,9 @@
 static void davinci_edma_intr_tcerr1(void *);
 
 static void davinci_edma_tcerr(struct davinci_edma_softc *, int);
+static int davinci_edma_setupdesc(struct dmae_transfer *,
+    struct davinci_edma_desc *);
+static uint64_t ffs64(uint64_t);
 
 #define	davinci_edma_lock(sc)			\
 	mtx_lock(&sc->ds_mtx)
@@ -246,66 +252,36 @@
 {
 	struct davinci_edma_softc *sc = device_get_softc(dev);
 	struct davinci_edma_channel *ch;
-	struct davinci_edma_desc param_desc;
-	uint32_t acnt, bcnt, srcbidx, dstbidx;
-
-	debugf("setup channel: chno=%d, xfer=%p", chno, xfer);
-	debugf("srcbuf=0x%08lx, dstbuf=0x%08lx length=%ld", 
-	    xfer->dt_src.db_addr, xfer->dt_dst.db_addr, 
-	    xfer->dt_dst.db_length);
+	struct davinci_edma_desc param_desc, link_desc;
+	int ret;
 
 	if (chno < 0 || chno > DAVINCI_EDMA_NCHANNELS)
 		return (EINVAL);
+	
+	ch = &sc->ds_channels[chno];
+	ch->dc_xfer = xfer;
 
-	if (xfer->dt_src.db_type == DMAEBUF_FRAME ||
-	    xfer->dt_dst.db_type == DMAEBUF_FRAME) {
-		if (xfer->dt_src.db_type == DMAEBUF_FRAME && 
-		    xfer->dt_dst.db_type == DMAEBUF_FRAME &&
-		    xfer->dt_src.db_stride_width != 
-		    xfer->dt_dst.db_stride_width)
-			return (EINVAL);
+	/* Allow at most one linked transfer */
+	if (xfer->dt_next != NULL && xfer->dt_next->dt_next != NULL)
+		return (EINVAL);
 
-		acnt = (xfer->dt_src.db_type == DMAEBUF_FRAME 
-		    ? xfer->dt_src.db_stride_width 
-		    : xfer->dt_dst.db_stride_width);
-		bcnt = (xfer->dt_src.db_type == DMAEBUF_FRAME
-		    ? xfer->dt_src.db_length / 
-		      (acnt + xfer->dt_src.db_stride_spacing)
-		    : xfer->dt_dst.db_length / 
-		      (acnt + xfer->dt_dst.db_stride_spacing));
-		
-		srcbidx = dstbidx = acnt;
+	/* Setup transfer descriptor */
+	ret = davinci_edma_setupdesc(xfer, &param_desc);
+	if (ret)
+		return (ret);
 
-		if (xfer->dt_src.db_type == DMAEBUF_FRAME)
-			srcbidx += xfer->dt_src.db_stride_spacing;
+	davinci_edma_copydesc(sc, &param_desc, chno);
 
-		if (xfer->dt_dst.db_type == DMAEBUF_FRAME)
-			dstbidx += xfer->dt_dst.db_stride_spacing;
-	} else {
-		acnt = xfer->dt_dst.db_length;
-		bcnt = 1;
-		srcbidx = 0;
-		dstbidx = 0;
+	/* Setup linked descriptor (if present) */
+	if (xfer->dt_next != NULL) {
+		ch->dc_linkxfer = xfer->dt_next;
+		ret = davinci_edma_setupdesc(xfer->dt_next, &link_desc);
+		if (ret)
+			return (ret);
+		printf("calling davinci_edma_copydesc(&link_desc=%p, chno=%d)\n", &link_desc, chno + 64);
+		davinci_edma_copydesc(sc, &link_desc, chno + 64);
 	}
 
-	ch = &sc->ds_channels[chno];
-	ch->dc_xfer = xfer;
-
-	/* Set up DMA descriptor */
-	param_desc.edma_src = xfer->dt_src.db_addr;
-	param_desc.edma_dst = xfer->dt_dst.db_addr;
-	param_desc.edma_opt = 
-	    DAVINCI_EDMA_OPT_TCINTEN | 
-	    DAVINCI_EDMA_OPT_ITCINTEN | 
-	    DAVINCI_EDMA_OPT_SYNCDIM | 
-	    (chno << DAVINCI_EDMA_OPT_TCCSHIFT);
-	param_desc.edma_abcnt = (bcnt << 16) | acnt;
-	param_desc.edma_bidx = (dstbidx << 16) | srcbidx;
-	param_desc.edma_cidx = 0;
-	param_desc.edma_ccnt = 1;
-
-	davinci_edma_copydesc(sc, &param_desc, chno);
-
 	/* Enable channel interrupts */
 //	if ((xfer->dt_flags & DMAE_TRANSFER_EXTTRIG) == 0)
 //		davinci_edma_enable_channel(sc, chno);
@@ -375,7 +351,27 @@
 static int
 davinci_edma_poll_channel(device_t dev, int chno, int *status)
 {
-	return (0);
+	struct davinci_edma_softc *sc = device_get_softc(dev);
+	struct davinci_edma_channel *ch;
+	uint32_t ipr;
+	int active = 0;
+
+	ch = &sc->ds_channels[chno];
+
+	if (chno < 32) {
+		ipr = davinci_read_edmacc_4(sc, DAVINCI_EDMACC_IPR);
+		if (ipr & (1 << chno))
+			active = 1;
+	} else {
+		ipr = davinci_read_edmacc_4(sc, DAVINCI_EDMACC_IPRH);
+		if (ipr & (1 << (chno-32)))
+			active = 1;
+	}
+
+	if (active)
+		return (DMAE_TRANSFER_INPROGRESS);
+	else
+		return (ch->dc_laststatus);
 }
 
 static void
@@ -384,54 +380,46 @@
 	struct davinci_edma_softc *sc = (struct davinci_edma_softc *)arg;
 	struct davinci_edma_channel *ch;
 	struct dmae_transfer *xfer = NULL;
-	uint32_t ipr, iprh;
+	uint64_t ipr;
+	uint32_t iprl, iprh;
 	int chno;
 
 	debugf("transfer completion interrupt");
 
 	while (1) {
-		ipr = davinci_read_edmacc_4(sc, DAVINCI_EDMACC_IPR);
+		iprl = davinci_read_edmacc_4(sc, DAVINCI_EDMACC_IPR);
 		iprh = davinci_read_edmacc_4(sc, DAVINCI_EDMACC_IPRH);
+		ipr = (uint64_t)iprh << 32 | iprl;
 
-		if (ipr == 0 && iprh == 0)
+		if (ipr == 0)
 			return;
 
-		while ((chno = (ffs(ipr) - 1)) != -1) {
+		while ((chno = (ffs64(ipr) - 1)) != -1) {
 			ch = &sc->ds_channels[chno];
 			xfer = ch->dc_xfer;
 
 			debugf("interrupt on channel %d", chno);
 
-			KASSERT(ch->dc_status == CHANNEL_ACTIVE, "edma spurious interrupt");
+			KASSERT(ch->dc_status != CHANNEL_IDLE, ("invalid channel state"));
 
 			if (xfer->dt_callback != NULL) {
-				xfer->dt_callback(DMAE_TRANSFER_COMPLETED, 
-				   xfer->dt_callback_arg);
+				xfer->dt_callback(DMAE_TRANSFER_COMPLETED,
+				    xfer->dt_callback_arg);
 			}
+		
+			if (chno > 32)
+				davinci_write_edmacc_4(sc, DAVINCI_EDMACC_ICRH, (1 << (chno - 32)));
+			else 
+				davinci_write_edmacc_4(sc, DAVINCI_EDMACC_ICR, (1 << chno));
 
-			ch->dc_status = 0;
-			
-			davinci_write_edmacc_4(sc, DAVINCI_EDMACC_ICR, (1 << chno));
-			ipr &= ~(1 << chno);
-		}
+			ipr &= ~(1ULL << chno);
+			ch->dc_status = CHANNEL_IDLE;
 
-		while ((chno = (ffs(iprh) + 31)) != 31) {
-			ch = &sc->ds_channels[chno];
-			xfer = ch->dc_xfer;
-
-			KASSERT(ch->dc_status == CHANNEL_ACTIVE, "edma spurious interrupt");
-			
-			debugf("interrupt on channel %d", chno);
-
-			if (xfer->dt_callback != NULL) {
-				xfer->dt_callback(DMAE_TRANSFER_COMPLETED,
-
-				    xfer->dt_callback_arg);
+			if (xfer->dt_next != NULL) {
+				ch->dc_xfer = xfer->dt_next;
+				davinci_edma_start_channel(sc->ds_dev, chno);
+				return;
 			}
-			
-			ch->dc_status = 0;
-			davinci_write_edmacc_4(sc, DAVINCI_EDMACC_ICRH, (1 << (chno-32)));
-			iprh &= ~(1 << (chno - 32));
 		}
 	}
 }
@@ -442,48 +430,38 @@
 	struct davinci_edma_softc *sc = (struct davinci_edma_softc *)arg;
 	struct davinci_edma_channel *ch;
 	struct dmae_transfer *xfer = NULL;
-	uint32_t emr, emrh;
+	uint64_t emr;
+	uint32_t emrl, emrh;
 	int chno;
 
-	emr = davinci_read_edmacc_4(sc, DAVINCI_EDMACC_EMR);
+	emrl = davinci_read_edmacc_4(sc, DAVINCI_EDMACC_EMR);
 	emrh = davinci_read_edmacc_4(sc, DAVINCI_EDMACC_EMRH);
+	emr = (uint64_t)emrh << 32 | emrl;
 
-	if (emr == 0 && emrh == 0)
+	if (emr == 0)
 		return;
 
-	while ((chno = (ffs(emr) - 1)) != -1) {
+	while ((chno = (ffs64(emr) - 1)) != -1) {
 		ch = &sc->ds_channels[chno];
 		xfer = ch->dc_xfer;
 
 		debugf("error interrupt on channel %d", chno);
 
-		KASSERT(ch->dc_status == CHANNEL_ACTIVE, "edma spurious interrupt");
+		KASSERT(ch->dc_status != CHANNEL_IDLE, ("invalid channel state"));
 
 		if (xfer->dt_callback != NULL) {
 			xfer->dt_callback(DMAE_TRANSFER_ERROR,
 			    xfer->dt_callback_arg);
 		}
 		
-		ch->dc_status = 0;
-			
-		davinci_write_edmacc_4(sc, DAVINCI_EDMACC_EMR, (1 << chno));
-		emr &= ~(1 << chno);
-	}
+		ch->dc_status = CHANNEL_IDLE;
+	
+		if (chno >= 32) 		
+			davinci_write_edmacc_4(sc, DAVINCI_EDMACC_EMRH, (1 << (chno - 32)));
+		else
+			davinci_write_edmacc_4(sc, DAVINCI_EDMACC_EMR, (1 << chno));
 
-	while ((chno = (ffs(emrh) + 31)) != 31) {
-		ch = &sc->ds_channels[chno];
-		KASSERT(ch->dc_status == CHANNEL_ACTIVE, "edma spurious interrupt");
-			
-		debugf("error interrupt on channel %d", chno);
-
-		if (xfer->dt_callback != NULL) {
-			xfer->dt_callback(DMAE_TRANSFER_ERROR,
-			    xfer->dt_callback_arg);
-		}
-			
-		ch->dc_status = 0;
-		davinci_write_edmacc_4(sc, DAVINCI_EDMACC_EMRH, (1 << (chno-32)));
-		emr &= ~(1 << (chno - 32));
+		emr &= ~(1ULL << chno);
 	}
 }
 
@@ -523,7 +501,7 @@
 	    DAVINCI_EDMATC_ERRDET_TCCMASK;
 
 	ch = &sc->ds_channels[chno];
-	xfer = dc->dc_xfer;
+	xfer = ch->dc_xfer;
 
 	if (xfer->dt_callback != NULL) {
 		xfer->dt_callback(DMAE_TRANSFER_ERROR,
@@ -531,6 +509,87 @@
 	}	
 }
 
+static int
+davinci_edma_setupdesc(struct dmae_transfer *xfer,
+    struct davinci_edma_desc *desc)
+{
+	int chno;
+	uint32_t acnt, bcnt, srcbidx, dstbidx;
+
+	chno = rman_get_start(xfer->dt_res);
+
+	debugf("setup desc: chno=%d, xfer=%p", chno, xfer);
+	debugf("srcbuf=0x%08lx, dstbuf=0x%08lx length=%ld", 
+	    xfer->dt_src.db_addr, xfer->dt_dst.db_addr, 
+	    xfer->dt_dst.db_length);
+
+	if (xfer->dt_src.db_length == 0 || xfer->dt_dst.db_length == 0)
+		return (EINVAL);
+
+	if (xfer->dt_src.db_type == DMAEBUF_FRAME ||
+	    xfer->dt_dst.db_type == DMAEBUF_FRAME) {
+		if (xfer->dt_src.db_type == DMAEBUF_FRAME && 
+		    xfer->dt_dst.db_type == DMAEBUF_FRAME &&
+		    xfer->dt_src.db_stride_width != 
+		    xfer->dt_dst.db_stride_width)
+			return (EINVAL);
+
+		acnt = (xfer->dt_src.db_type == DMAEBUF_FRAME 
+		    ? xfer->dt_src.db_stride_width 
+		    : xfer->dt_dst.db_stride_width);
+		bcnt = (xfer->dt_src.db_type == DMAEBUF_FRAME
+		    ? xfer->dt_src.db_length / 
+		      (acnt + xfer->dt_src.db_stride_spacing)
+		    : xfer->dt_dst.db_length / 
+		      (acnt + xfer->dt_dst.db_stride_spacing));
+		
+		srcbidx = dstbidx = acnt;
+
+		if (xfer->dt_src.db_type == DMAEBUF_FRAME)
+			srcbidx += xfer->dt_src.db_stride_spacing;
+
+		if (xfer->dt_dst.db_type == DMAEBUF_FRAME)
+			dstbidx += xfer->dt_dst.db_stride_spacing;
+	} else {
+		acnt = xfer->dt_dst.db_length;
+		bcnt = 1;
+		srcbidx = 0;
+		dstbidx = 0;
+	}
+
+	/* Set up DMA descriptor */
+	desc->edma_src = xfer->dt_src.db_addr;
+	desc->edma_dst = xfer->dt_dst.db_addr;
+	desc->edma_opt = 
+	    DAVINCI_EDMA_OPT_TCINTEN | 
+	 /*   DAVINCI_EDMA_OPT_ITCINTEN | */
+	    DAVINCI_EDMA_OPT_SYNCDIM |
+	    (chno << DAVINCI_EDMA_OPT_TCCSHIFT);
+	desc->edma_abcnt = (bcnt << 16) | acnt;
+	desc->edma_bidx = (dstbidx << 16) | srcbidx;
+	desc->edma_cidx = 0;
+	desc->edma_ccnt = 1;
+	desc->edma_link = (xfer->dt_next != NULL)
+	    ? ((chno + 64) * sizeof(*desc)) + 0x4000
+	    : 0xffff;
+
+	return (0);
+}
+
+static __inline uint64_t
+ffs64(uint64_t mask)
+{
+	uint64_t bit;
+
+	if (mask == 0)
+		return (0);
+
+	for (bit = 1; (mask & 1UL) == 0; bit++)
+		mask >>= 1UL;
+
+	return (bit);
+}
+
 static device_method_t davinci_edma_methods[] = {
 	/* Device methods */
 	DEVMETHOD(device_probe,		davinci_edma_probe),

==== //depot/projects/soc2010/jceel_dma/sys/arm/davinci/davinci_edmareg.h#4 (text+ko) ====

@@ -143,6 +143,6 @@
 } __packed;
 
 #define DAVINCI_EDMA_PARAM_BASE		0x4000
-#define	DAVINCI_EDMA_PARAM(_n)		(DAVINCI_EDMA_PARAM_BASE + (_n * sizeof(struct davinci_edma_desc)))
+#define	DAVINCI_EDMA_PARAM(_n)		(DAVINCI_EDMA_PARAM_BASE + ((_n) * sizeof(struct davinci_edma_desc)))
 
 #endif	/* _ARM_DAVINCI_DAVINCI_EDMAREG_H */


More information about the p4-projects mailing list