diff options
author | Christopher Pascoe <pascoe@cvs.openbsd.org> | 2006-04-04 11:37:06 +0000 |
---|---|---|
committer | Christopher Pascoe <pascoe@cvs.openbsd.org> | 2006-04-04 11:37:06 +0000 |
commit | 778d9da530ef19c03089cc2e5d18e471b6d4bba8 (patch) | |
tree | 2f309122d60a618a8a38a53d12cf1a18bcfa95f2 /sys/arch/arm | |
parent | e77b25a2b49dfe084c2608b361eb34901bb430ba (diff) |
Add pxa2x0_dma_from_fifo to support DMA from internal peripheral FIFOs
to memory.
ok robert@
Diffstat (limited to 'sys/arch/arm')
-rw-r--r-- | sys/arch/arm/xscale/pxa2x0_dmac.c | 85 | ||||
-rw-r--r-- | sys/arch/arm/xscale/pxa2x0_dmac.h | 6 |
2 files changed, 89 insertions, 2 deletions
diff --git a/sys/arch/arm/xscale/pxa2x0_dmac.c b/sys/arch/arm/xscale/pxa2x0_dmac.c index 7b2c74087d1..2235d01b407 100644 --- a/sys/arch/arm/xscale/pxa2x0_dmac.c +++ b/sys/arch/arm/xscale/pxa2x0_dmac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pxa2x0_dmac.c,v 1.2 2006/04/04 11:33:40 pascoe Exp $ */ +/* $OpenBSD: pxa2x0_dmac.c,v 1.3 2006/04/04 11:37:05 pascoe Exp $ */ /* * Copyright (c) 2005 Christopher Pascoe <pascoe@openbsd.org> @@ -198,6 +198,89 @@ pxa2x0_dma_to_fifo(int periph, int chan, bus_addr_t fifo_addr, int width, return 0; } +/* Perform non-descriptor based DMA from a FIFO */ +int +pxa2x0_dma_from_fifo(int periph, int chan, bus_addr_t fifo_addr, int width, + int burstsize, bus_addr_t trg_addr, int length, void (*intr)(void *), + void *intrarg) +{ + struct pxadmac_softc *sc = pxadmac_softc; + uint32_t cmd; + + if (periph < 0 || periph > 63 || periph == 23) { + printf("pxa2x0_dma_from_fifo: bogus peripheral %d", periph); + return EINVAL; + } + + if (chan < 0 || chan >= sc->sc_nchan) { + printf("pxa2x0_dma_from_fifo: bogus dma channel %d", chan); + return EINVAL; + } + + if (length < 0 || length > DCMD_LENGTH_MASK) { + printf("pxa2x0_dma_from_fifo: bogus length %d", length); + return EINVAL; + } + + cmd = (length & DCMD_LENGTH_MASK) | DCMD_INCTRGADDR | DCMD_FLOWSRC + | DCMD_ENDIRQEN; + + switch (width) { + case 1: + cmd |= DCMD_WIDTH_1; + break; + case 4: + cmd |= DCMD_WIDTH_4; + break; + default: + printf("pxa2x0_dma_from_fifo: bogus width %d", width); + return EINVAL; + } + + switch (burstsize) { + case 8: + cmd |= DCMD_SIZE_8; + break; + case 16: + cmd |= DCMD_SIZE_16; + break; + case 32: + cmd |= DCMD_SIZE_32; + break; + default: + printf("pxa2x0_dma_from_fifo: bogus burstsize %d", burstsize); + return EINVAL; + } + + /* XXX: abort anything already in progress, hopefully nothing. */ + bus_space_write_4(sc->sc_bust, sc->sc_bush, DMAC_DCSR(chan), + DCSR_NODESCFETCH); + + /* Save handler for interrupt-on-completion. */ + sc->sc_intrhandlers[chan] = intr; + sc->sc_intrargs[chan] = intrarg; + + /* Map peripheral to channel for flow control setup. */ + bus_space_write_4(sc->sc_bust, sc->sc_bush, DMAC_DRCMR(periph), + chan | DRCMR_MAPVLD); + + /* Setup transfer addresses. */ + bus_space_write_4(sc->sc_bust, sc->sc_bush, DMAC_DDADR(chan), + DDADR_STOP); + bus_space_write_4(sc->sc_bust, sc->sc_bush, DMAC_DSADR(chan), + fifo_addr); + bus_space_write_4(sc->sc_bust, sc->sc_bush, DMAC_DTADR(chan), + trg_addr); + bus_space_write_4(sc->sc_bust, sc->sc_bush, DMAC_DCMD(chan), + cmd); + + /* Start the transfer. */ + bus_space_write_4(sc->sc_bust, sc->sc_bush, DMAC_DCSR(chan), + DCSR_RUN | DCSR_NODESCFETCH); + + return 0; +} + int pxadmac_intr(void *v) { diff --git a/sys/arch/arm/xscale/pxa2x0_dmac.h b/sys/arch/arm/xscale/pxa2x0_dmac.h index 48619e944e7..840965896b1 100644 --- a/sys/arch/arm/xscale/pxa2x0_dmac.h +++ b/sys/arch/arm/xscale/pxa2x0_dmac.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pxa2x0_dmac.h,v 1.1 2005/04/14 23:40:34 pascoe Exp $ */ +/* $OpenBSD: pxa2x0_dmac.h,v 1.2 2006/04/04 11:37:05 pascoe Exp $ */ /* * Copyright (c) 2005 Christopher Pascoe <pascoe@openbsd.org> @@ -23,4 +23,8 @@ int pxa2x0_dma_to_fifo(int periph, int chan, bus_addr_t fifo_addr, int width, int burstsize, bus_addr_t src_addr, int length, void (*intr)(void *), void *intrarg); +int pxa2x0_dma_from_fifo(int periph, int chan, bus_addr_t fifo_addr, int width, + int burstsize, bus_addr_t trg_addr, int length, void (*intr)(void *), + void *intrarg); + #endif /* _PXA2X0_DMAC_H */ |