Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Jul 2010 10:23:12 GMT
From:      Jakub Wojciech Klama <jceel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 181303 for review
Message-ID:  <201007221023.o6MANC2n033365@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@181303?ac=10

Change 181303 by jceel@jceel on 2010/07/22 10:22:43

	EDMA3 driver improvements and refactoring.

Affected files ...

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

Differences ...

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

@@ -66,9 +66,9 @@
 
 #include <arm/davinci/davincireg.h>
 #include <arm/davinci/davinci_edmareg.h>
-#include <dev/dmae/dmae.h>
+#include <dev/gpdma/gpdma.h>
 
-#include "dmae_if.h"
+#include "gpdma_if.h"
 
 #define	DEBUG
 //#undef	DEBUG
@@ -87,10 +87,11 @@
 	int				dc_status;
 #define	CHANNEL_ACTIVE			1
 #define	CHANNEL_ACTIVE_LINKED		2
+#define	CHANNEL_STOPPED			3
 #define	CHANNEL_IDLE			0
 	int				dc_laststatus;
-	struct dmae_transfer *		dc_xfer;
-	struct dmae_transfer *		dc_linkxfer;
+	struct gpdma_transfer *		dc_xfer;
+	struct gpdma_transfer *		dc_linkxfer;
 };
 
 struct davinci_edma_softc {
@@ -113,16 +114,16 @@
 	{ -1, 0 }
 };
 
-static const struct dmae_capabilities davinci_edma_caps = {
+static const struct gpdma_capabilities davinci_edma_caps = {
 	.dc_nchannels	= DAVINCI_EDMA_NCHANNELS,
-	.dc_ops		= DMAE_COPY,
-	.dc_buffers	= DMAEBUF_BLOCK | DMAEBUF_FRAME | DMAEBUF_FIFO,
-	.dc_flags	= DMAECAP_REPEAT | DMAECAP_LINK,
+	.dc_ops		= GPDMA_COPY,
+	.dc_buffers	= GPDMABUF_BLOCK | GPDMABUF_FRAME | GPDMABUF_FIFO,
+	.dc_flags	= GPDMACAP_REPEAT | GPDMACAP_LINK,
 };
 
 static int davinci_edma_probe(device_t);
 static int davinci_edma_attach(device_t);
-static int davinci_edma_setup_channel(device_t, int, struct dmae_transfer *);
+static int davinci_edma_setup_channel(device_t, int, struct gpdma_transfer *);
 static int davinci_edma_clear_channel(device_t, int);
 static int davinci_edma_start_channel(device_t, int);
 static int davinci_edma_stop_channel(device_t, int);
@@ -134,8 +135,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 *,
+static int davinci_edma_setupdesc(struct gpdma_transfer *,
     struct davinci_edma_desc *);
+static void davinci_edma_printdesc(struct davinci_edma_softc *, int);
 static uint64_t ffs64(uint64_t);
 
 #define	davinci_edma_lock(sc)			\
@@ -153,12 +155,11 @@
 	bus_space_write_4((_sc)->ds_bst, (_sc)->ds_bsh, DAVINCI_EDMACC_BASE + (_reg), (_data))
 #define	davinci_read_edmatc_4(_sc, _tc, _reg)		\
 	bus_space_read_4((_sc)->ds_bst, (_sc)->ds_bsh, DAVINCI_EDMATC ## _tc ## _BASE + (_reg))
-#define	davinci_write_edmatc_4(_sc, _tc, _reg)		\
+#define	davinci_write_edmatc_4(_sc, _tc, _reg, _data)		\
 	bus_space_write_4((_sc)->ds_bst, (_sc)->ds_bsh, DAVINCI_EDMATC ## _tc ## _BASE + (_reg), (_data))
 #define	davinci_edma_copydesc(_sc, _desc, _idx)		\
 	memcpy((uint8_t *)(DAVINCI_EDMA_BASE + DAVINCI_EDMA_PARAM(_idx)), (_desc), sizeof(param_desc))
 
-
 static int
 davinci_edma_probe(device_t dev)
 {
@@ -231,7 +232,11 @@
 	davinci_write_edmacc_4(sc, DAVINCI_EDMACC_DRAE0, 0xffffffff);
 	davinci_write_edmacc_4(sc, DAVINCI_EDMACC_DRAEH0, 0xffffffff);
 
-	dmae_register_driver(dev, &davinci_edma_caps, sc->ds_dmatag);
+	/* Enable TC error interrupts */
+	davinci_write_edmatc_4(sc, 0, DAVINCI_EDMATC_ERREN, 0xffff);
+	davinci_write_edmatc_4(sc, 1, DAVINCI_EDMATC_ERREN, 0xffff);
+
+	gpdma_register_driver(dev, &davinci_edma_caps, sc->ds_dmatag);
 
 	return (0);
 
@@ -248,7 +253,7 @@
 }
 
 static int
-davinci_edma_setup_channel(device_t dev, int chno, struct dmae_transfer *xfer)
+davinci_edma_setup_channel(device_t dev, int chno, struct gpdma_transfer *xfer)
 {
 	struct davinci_edma_softc *sc = device_get_softc(dev);
 	struct davinci_edma_channel *ch;
@@ -261,6 +266,10 @@
 	ch = &sc->ds_channels[chno];
 	ch->dc_xfer = xfer;
 
+	/* Zero param_desc and link_desc */
+	memset(&param_desc, 0, sizeof(struct davinci_edma_desc));
+	memset(&link_desc, 0, sizeof(struct davinci_edma_desc));
+
 	/* Allow at most one linked transfer */
 	if (xfer->dt_next != NULL && xfer->dt_next->dt_next != NULL)
 		return (EINVAL);
@@ -278,21 +287,29 @@
 		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);
+		debugf("calling davinci_edma_copydesc(&link_desc=%p, chno=%d)\n", &link_desc, chno + 64);
 		davinci_edma_copydesc(sc, &link_desc, chno + 64);
 	}
 
 	/* Enable channel interrupts */
-//	if ((xfer->dt_flags & DMAE_TRANSFER_EXTTRIG) == 0)
+//	if ((xfer->dt_flags & GPDMA_TRANSFER_EXTTRIG) == 0)
 //		davinci_edma_enable_channel(sc, chno);
 
 	if (chno > 31) {
 		chno -= 32;
 		davinci_write_edmacc_4(sc, DAVINCI_EDMACC_IESRH, (1 << chno));
+		davinci_write_edmacc_4(sc, DAVINCI_EDMACC_EESRH, (1 << chno));
 	} else {
 		davinci_write_edmacc_4(sc, DAVINCI_EDMACC_IESR, (1 << chno));
+		davinci_write_edmacc_4(sc, DAVINCI_EDMACC_EESR, (1 << chno));
 	}
 
+
+	bus_dmamap_sync(xfer->dt_src.db_dmatag, xfer->dt_src.db_dmamap,
+	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+	bus_dmamap_sync(xfer->dt_dst.db_dmatag, xfer->dt_dst.db_dmamap,
+	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
 	debugf("channel setup done.");
 
 	return (0);
@@ -345,7 +362,13 @@
 static int
 davinci_edma_stop_channel(device_t dev, int chno)
 {
-	return (ENOTSUP);
+	struct davinci_edma_softc *sc = device_get_softc(dev);
+	struct davinci_edma_channel *ch;
+
+	ch = &sc->ds_channels[chno];
+	ch->dc_status = CHANNEL_STOPPED;
+
+	return (0);
 }
 
 static int
@@ -369,7 +392,7 @@
 	}
 
 	if (active)
-		return (DMAE_TRANSFER_INPROGRESS);
+		return (GPDMA_TRANSFER_INPROGRESS);
 	else
 		return (ch->dc_laststatus);
 }
@@ -379,7 +402,7 @@
 {
 	struct davinci_edma_softc *sc = (struct davinci_edma_softc *)arg;
 	struct davinci_edma_channel *ch;
-	struct dmae_transfer *xfer = NULL;
+	struct gpdma_transfer *xfer = NULL;
 	uint64_t ipr;
 	uint32_t iprl, iprh;
 	int chno;
@@ -402,23 +425,38 @@
 
 			KASSERT(ch->dc_status != CHANNEL_IDLE, ("invalid channel state"));
 
+	printf("src dmatag=%p dst dmatag=%p src dmamap=%p dst dmamap=%p\n", xfer->dt_src.db_dmatag, xfer->dt_dst.db_dmatag, xfer->dt_src.db_dmamap, xfer->dt_dst.db_dmamap);
+	bus_dmamap_sync(xfer->dt_src.db_dmatag, xfer->dt_src.db_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+	bus_dmamap_sync(xfer->dt_dst.db_dmatag, xfer->dt_dst.db_dmamap, BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTWRITE);
+
+
+
 			if (xfer->dt_callback != NULL) {
-				xfer->dt_callback(DMAE_TRANSFER_COMPLETED,
+				xfer->dt_callback(GPDMA_TRANSFER_COMPLETED,
 				    xfer->dt_callback_arg);
 			}
 		
-			if (chno > 32)
+			if (chno > 32) { 
 				davinci_write_edmacc_4(sc, DAVINCI_EDMACC_ICRH, (1 << (chno - 32)));
-			else 
+		//		davinci_write_edmacc_4(sc, DAVINCI_EDMACC_ECRH, (1 << (chno - 32)));
+			} else {
 				davinci_write_edmacc_4(sc, DAVINCI_EDMACC_ICR, (1 << chno));
+		//		davinci_write_edmacc_4(sc, DAVINCI_EDMACC_ECR, (1 << chno));
+			}
 
 			ipr &= ~(1ULL << chno);
+
+			if (ch->dc_status == CHANNEL_STOPPED)
+				continue;
+
 			ch->dc_status = CHANNEL_IDLE;
 
+			if (xfer->dt_flags & GPDMA_TRANSFER_REPEAT)
+				davinci_edma_start_channel(sc->ds_dev, chno);
+
 			if (xfer->dt_next != NULL) {
 				ch->dc_xfer = xfer->dt_next;
 				davinci_edma_start_channel(sc->ds_dev, chno);
-				return;
 			}
 		}
 	}
@@ -429,7 +467,7 @@
 {
 	struct davinci_edma_softc *sc = (struct davinci_edma_softc *)arg;
 	struct davinci_edma_channel *ch;
-	struct dmae_transfer *xfer = NULL;
+	struct gpdma_transfer *xfer = NULL;
 	uint64_t emr;
 	uint32_t emrl, emrh;
 	int chno;
@@ -450,7 +488,7 @@
 		KASSERT(ch->dc_status != CHANNEL_IDLE, ("invalid channel state"));
 
 		if (xfer->dt_callback != NULL) {
-			xfer->dt_callback(DMAE_TRANSFER_ERROR,
+			xfer->dt_callback(GPDMA_TRANSFER_ERROR,
 			    xfer->dt_callback_arg);
 		}
 		
@@ -484,8 +522,8 @@
 static void
 davinci_edma_tcerr(struct davinci_edma_softc *sc, int tc)
 {
-	struct davinci_edma_channel *ch;
-	struct dmae_transfer *xfer;
+//	struct davinci_edma_channel *ch;
+//	struct gpdma_transfer *xfer;
 	uint32_t errstat, errdet;
 	int chno;
 
@@ -497,24 +535,28 @@
 		errdet = davinci_read_edmatc_4(sc, 1, DAVINCI_EDMATC_ERRDET);
 	}
 
-	chno = (errstat >> DAVINCI_EDMATC_ERRDET_TCCSHIFT) & 
-	    DAVINCI_EDMATC_ERRDET_TCCMASK;
+	chno = ((errdet >> DAVINCI_EDMATC_ERRDET_TCCSHIFT) & 
+	    DAVINCI_EDMATC_ERRDET_TCCMASK);
+
+	device_printf(sc->ds_dev, "TC error: tc=%d, chno=%d, errstat=%08x, "
+	    "errdet=%08x\n", tc, chno, errstat, errdet);
+
+	device_printf(sc->ds_dev, "Transfer descriptor that has failed:\n");
+	davinci_edma_printdesc(sc, chno);
 
-	ch = &sc->ds_channels[chno];
-	xfer = ch->dc_xfer;
+//	ch = &sc->ds_channels[chno];
+//	xfer = ch->dc_xfer;
 
-	if (xfer->dt_callback != NULL) {
-		xfer->dt_callback(DMAE_TRANSFER_ERROR,
-		    xfer->dt_callback_arg);
-	}	
+	panic("DMA transfer controller error");
 }
 
 static int
-davinci_edma_setupdesc(struct dmae_transfer *xfer,
+davinci_edma_setupdesc(struct gpdma_transfer *xfer,
     struct davinci_edma_desc *desc)
 {
 	int chno;
-	uint32_t acnt, bcnt, srcbidx, dstbidx;
+	uint32_t acnt = 0, bcnt = 0, ccnt = 0;
+	uint32_t srcbidx, dstbidx, srccidx, dstcidx;
 
 	chno = rman_get_start(xfer->dt_res);
 
@@ -526,56 +568,115 @@
 	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)
+	srccidx = 0;
+	dstcidx = 0;
+
+	/* block-to-block transfer */
+	if (xfer->dt_src.db_type == GPDMABUF_BLOCK && xfer->dt_dst.db_type == GPDMABUF_BLOCK)
+	{
+		if (xfer->dt_src.db_length != xfer->dt_dst.db_length)
 			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;
+		acnt = xfer->dt_src.db_length;
+		bcnt = 1;
+		ccnt = 1;
+		srcbidx = dstbidx = srccidx = dstcidx = 1;
+	}
+
+	/* block-to-frame transfer */
+	if (xfer->dt_src.db_type == GPDMABUF_BLOCK && xfer->dt_dst.db_type == GPDMABUF_FRAME)
+	{
+		acnt = xfer->dt_dst.db_stride_width;
+		bcnt = xfer->dt_dst.db_length / xfer->dt_dst.db_stride_width; //xfer->dt_dst.db_nstrides;
+		ccnt = 1;
+		srcbidx = acnt;
+		dstbidx = acnt + xfer->dt_dst.db_stride_spacing;
+		srccidx = dstcidx = 0;
+	}
+
+	/* frame-to-block transfer */
+	if (xfer->dt_src.db_type == GPDMABUF_FRAME && xfer->dt_dst.db_type == GPDMABUF_BLOCK)
+	{
+		acnt = xfer->dt_src.db_stride_width;
+		bcnt = xfer->dt_src.db_length / xfer->dt_src.db_stride_width; //xfer->dt_src.db_nstrides;
+		ccnt = 1;
+		srcbidx = acnt + xfer->dt_src.db_stride_spacing;
+		dstbidx = acnt;
+		srccidx = dstcidx = 0;
+	}
+
+	/* frame-to-frame transfer */
+	if (xfer->dt_src.db_type == GPDMABUF_FRAME && xfer->dt_dst.db_type == GPDMABUF_FRAME)
+	{
+		if (xfer->dt_src.db_stride_width != xfer->dt_dst.db_stride_width)
+			return (EINVAL);
 
-		if (xfer->dt_src.db_type == DMAEBUF_FRAME)
-			srcbidx += xfer->dt_src.db_stride_spacing;
+		acnt = xfer->dt_src.db_stride_width;
+		bcnt = xfer->dt_dst.db_length / xfer->dt_dst.db_stride_width; //xfer->dt_src.db_nstrides;
+		ccnt = 1;
+		srcbidx = acnt + xfer->dt_src.db_stride_spacing;
+		dstbidx = acnt + xfer->dt_dst.db_stride_spacing;
+		srccidx = dstcidx = 0;
+	}
 
-		if (xfer->dt_dst.db_type == DMAEBUF_FRAME)
-			dstbidx += xfer->dt_dst.db_stride_spacing;
-	} else {
-		acnt = xfer->dt_dst.db_length;
+	if (bcnt <= 0)
 		bcnt = 1;
+
+	if (xfer->dt_src.db_flags & GPDMA_BUFFER_FIFO) { 
+		ccnt = bcnt;
+		bcnt = acnt / xfer->dt_src.db_fifo_width;
+		acnt = xfer->dt_src.db_fifo_width;
+		srccidx = 0;
 		srcbidx = 0;
+		dstcidx = acnt * bcnt;
+		dstbidx = acnt;
+	}
+
+	if (xfer->dt_dst.db_flags & GPDMA_BUFFER_FIFO) {
+		ccnt = bcnt;
+		bcnt = acnt / xfer->dt_dst.db_fifo_width;
+		acnt = xfer->dt_dst.db_fifo_width;
+		dstcidx = 0;
 		dstbidx = 0;
+		srccidx = acnt * bcnt;
+		srcbidx = acnt;
 	}
 
+	//if ((xfer->dt_flags & GPDMA_TRANSFER_STRIDE_SYNC) == 0)
+		desc->edma_opt |= DAVINCI_EDMA_OPT_SYNCDIM;
+
 	/* Set up DMA descriptor */
 	desc->edma_src = xfer->dt_src.db_addr;
 	desc->edma_dst = xfer->dt_dst.db_addr;
-	desc->edma_opt = 
+	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_cidx = (dstcidx << 16) | srccidx;
+	desc->edma_ccnt = ccnt;
 	desc->edma_link = (xfer->dt_next != NULL)
-	    ? ((chno + 64) * sizeof(*desc)) + 0x4000
+	    ? DAVINCI_EDMA_PARAM(chno + 64)
 	    : 0xffff;
 
+	if (xfer->dt_flags & GPDMA_TRANSFER_REPEAT)
+		desc->edma_link = DAVINCI_EDMA_PARAM(chno);
+
 	return (0);
 }
 
+static void
+davinci_edma_printdesc(struct davinci_edma_softc *sc, int chno)
+{
+	struct davinci_edma_desc *desc = (struct davinci_edma_desc *)
+	    (sc->ds_bsh + DAVINCI_EDMA_PARAM(chno));
+
+	printf("src=%08x\tdst=%08x\n", desc->edma_src, desc->edma_dst);
+	printf("acnt=%d\tbcnt=%d\tccnt=%d\n", 0, 0, 0);
+	printf("srcbidx=%d dstbidx=%d srccidx=%d dstcidx=%d\n", 0, 0, 0, 0);
+	printf("link=%08x (set %d) opt=%d\n", 0, 0, 0);
+}
+
 static __inline uint64_t
 ffs64(uint64_t mask)
 {
@@ -595,12 +696,12 @@
 	DEVMETHOD(device_probe,		davinci_edma_probe),
 	DEVMETHOD(device_attach,	davinci_edma_attach),
 
-	/* DMAE methods */
-	DEVMETHOD(dmae_setup_channel,	davinci_edma_setup_channel),
-	DEVMETHOD(dmae_clear_channel,	davinci_edma_clear_channel),
-	DEVMETHOD(dmae_start_channel,	davinci_edma_start_channel),
-	DEVMETHOD(dmae_start_channel,	davinci_edma_stop_channel),
-	DEVMETHOD(dmae_poll_channel,	davinci_edma_poll_channel),
+	/* GPDMA methods */
+	DEVMETHOD(gpdma_setup_channel,	davinci_edma_setup_channel),
+	DEVMETHOD(gpdma_clear_channel,	davinci_edma_clear_channel),
+	DEVMETHOD(gpdma_start_channel,	davinci_edma_start_channel),
+	DEVMETHOD(gpdma_start_channel,	davinci_edma_stop_channel),
+	DEVMETHOD(gpdma_poll_channel,	davinci_edma_poll_channel),
 	{ 0, 0 }
 };
 

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

@@ -74,7 +74,7 @@
 #define	DAVINCI_EDMACC_CER		0x1018
 #define	DAVINCI_EDMACC_CERH		0x101C
 #define	DAVINCI_EDMACC_EER		0x1020
-#define	DAVINCI_EDMACC_CEERH		0x1024
+#define	DAVINCI_EDMACC_EERH		0x1024
 #define	DAVINCI_EDMACC_EECR		0x1028
 #define	DAVINCI_EDMACC_EECRH		0x102C
 #define	DAVINCI_EDMACC_EESR		0x1030



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007221023.o6MANC2n033365>