summaryrefslogtreecommitdiff
path: root/sys/arch/arm
diff options
context:
space:
mode:
authorChristopher Pascoe <pascoe@cvs.openbsd.org>2006-04-04 11:37:06 +0000
committerChristopher Pascoe <pascoe@cvs.openbsd.org>2006-04-04 11:37:06 +0000
commit778d9da530ef19c03089cc2e5d18e471b6d4bba8 (patch)
tree2f309122d60a618a8a38a53d12cf1a18bcfa95f2 /sys/arch/arm
parente77b25a2b49dfe084c2608b361eb34901bb430ba (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.c85
-rw-r--r--sys/arch/arm/xscale/pxa2x0_dmac.h6
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 */