1*cf10107dSdyoung /* $Id: at91pdc.c,v 1.3 2011/07/01 19:31:17 dyoung Exp $ */
2c62a0ac4Smatt
3c62a0ac4Smatt #include <sys/types.h>
4*cf10107dSdyoung #include <sys/bus.h>
5c62a0ac4Smatt #include <arm/at91/at91pdcvar.h>
6c62a0ac4Smatt
at91pdc_alloc_fifo(bus_dma_tag_t dmat,at91pdc_fifo_t * fifo,int size,int flags)7c62a0ac4Smatt int at91pdc_alloc_fifo(bus_dma_tag_t dmat, at91pdc_fifo_t *fifo, int size,
8c62a0ac4Smatt int flags)
9c62a0ac4Smatt {
10c62a0ac4Smatt bus_dma_segment_t segs;
11c62a0ac4Smatt int rsegs;
12c62a0ac4Smatt int err;
13c62a0ac4Smatt int f;
14c62a0ac4Smatt
15c62a0ac4Smatt memset(fifo, 0, sizeof(*fifo));
16c62a0ac4Smatt
17c62a0ac4Smatt /* allocate map: */
18c62a0ac4Smatt f = flags & (BUS_DMA_BUS1 | BUS_DMA_BUS2 | BUS_DMA_BUS3 | BUS_DMA_BUS4);
19c62a0ac4Smatt err = bus_dmamap_create(dmat, size, 1, size, 0,
20c62a0ac4Smatt BUS_DMA_WAITOK | f,
21c62a0ac4Smatt &fifo->f_dmamap);
22c62a0ac4Smatt if (err)
23c62a0ac4Smatt goto fail_0;
24c62a0ac4Smatt
25c62a0ac4Smatt /* allocate DMA safe memory: */
26c62a0ac4Smatt f |= flags & BUS_DMA_STREAMING;
27c62a0ac4Smatt err = bus_dmamem_alloc(dmat, size, 0, size, &segs, 1, &rsegs,
28c62a0ac4Smatt BUS_DMA_WAITOK | f);
29c62a0ac4Smatt if (err)
30c62a0ac4Smatt goto fail_1;
31c62a0ac4Smatt
32c62a0ac4Smatt /* allocate virtual memory: */
33c62a0ac4Smatt f |= flags & (BUS_DMA_COHERENT | BUS_DMA_NOCACHE);
34c62a0ac4Smatt err = bus_dmamem_map(dmat, &segs, 1, size, &fifo->f_buf,
35c62a0ac4Smatt BUS_DMA_WAITOK | f);
36c62a0ac4Smatt if (err)
37c62a0ac4Smatt goto fail_2;
38c62a0ac4Smatt
39c62a0ac4Smatt /* connect physical to virtual memory: */
40c62a0ac4Smatt f |= flags & (BUS_DMA_READ | BUS_DMA_WRITE);
41c62a0ac4Smatt f &= ~(BUS_DMA_COHERENT | BUS_DMA_NOCACHE);
42c62a0ac4Smatt err = bus_dmamap_load(dmat, fifo->f_dmamap, fifo->f_buf, size, NULL,
43c62a0ac4Smatt BUS_DMA_NOWAIT | f);
44c62a0ac4Smatt if (err)
45c62a0ac4Smatt goto fail_3;
46c62a0ac4Smatt
47c62a0ac4Smatt /* initialize rest of the structure: */
48c62a0ac4Smatt fifo->f_buf_size = size;
49c62a0ac4Smatt fifo->f_ndx = fifo->f_length = 0;
50c62a0ac4Smatt
51c62a0ac4Smatt fifo->f_buf_addr = fifo->f_dmamap->dm_segs[0].ds_addr;
52c62a0ac4Smatt fifo->f_pdc_rd_ndx = fifo->f_pdc_wr_ndx = 0;
53c62a0ac4Smatt fifo->f_pdc_space = fifo->f_buf_size;
54c62a0ac4Smatt
55c62a0ac4Smatt return 0;
56c62a0ac4Smatt fail_3:
57c62a0ac4Smatt bus_dmamem_unmap(dmat, fifo->f_buf, size);
58c62a0ac4Smatt fail_2:
59c62a0ac4Smatt bus_dmamem_free(dmat, &segs, rsegs);
60c62a0ac4Smatt fail_1:
61c62a0ac4Smatt bus_dmamap_destroy(dmat, fifo->f_dmamap);
62c62a0ac4Smatt fail_0:
63c62a0ac4Smatt return err;
64c62a0ac4Smatt }
65