From owner-p4-projects@FreeBSD.ORG Thu Jul 22 10:23:13 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 49E97106567B; Thu, 22 Jul 2010 10:23:13 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0E4111065679 for ; Thu, 22 Jul 2010 10:23:13 +0000 (UTC) (envelope-from jceel@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id EE2578FC1D for ; Thu, 22 Jul 2010 10:23:12 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id o6MANCO0033367 for ; Thu, 22 Jul 2010 10:23:12 GMT (envelope-from jceel@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o6MANC2n033365 for perforce@freebsd.org; Thu, 22 Jul 2010 10:23:12 GMT (envelope-from jceel@freebsd.org) Date: Thu, 22 Jul 2010 10:23:12 GMT Message-Id: <201007221023.o6MANC2n033365@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jceel@freebsd.org using -f From: Jakub Wojciech Klama To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 181303 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Jul 2010 10:23:13 -0000 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 #include -#include +#include -#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(¶m_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