I'm trying to do DMA to and from GPMC in linux. This will work if I use a MEM_TO_MEM transaction through device_prep_dma_memcpy(). The caveat is that the dma driver will set the transaction to 32-bit bursts, which limits the GPMC bursts to 2x16bit. I've been trying to use dmaengine_prep_slave_single(), but I can't figure out how to get the transfer working. The transfer never starts after I issue dma_async_issue_pending();
I've tried quite a number of combinations, but I just can't figure out what it is that I'm missing. How can I get this running properly?
Code looks something like:
static void dma_callback(void *param) { complete(&dma_comp); } int ch_num = 52; dma_buf = dma_alloc_coherent(NULL, MAX_DMA_TRANSFER_IN_BYTES, &dma_phys_addr, GFP_KERNEL); dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); dma_chan = dma_request_channel(mask, edma_filter_fn, &ch_num); int my_dma_copy(struct my_dev_class* my_dev, dma_addr_t dest_addr, dma_addr_t src_addr, int count, bool is_write) { unsigned int ch_num = 52; dir = is_write ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; dma_addr_t mem_dma_addr = is_write ? src_addr : dest_addr; struct dma_slave_config conf = { .src_addr = src_addr, .dst_addr = dest_addr, .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, .src_maxburst = 16, .dst_maxburst = 16, .device_fc = 0, .slave_id = 0, }; result = dmaengine_slave_config(chan, &conf); /* This works, but does not do GPMC bursts */ tx = dma_chan->device->device_prep_dma_memcpy(chan, trgt_addr, src_addr, count, DMA_CTRL_ACK | DMA_PREP_INTERRUPT); /* This doesn't trigger any data over GPMC */ //tx = dmaengine_prep_slave_single(dma_chan, mem_dma_addr, count, dir, // DMA_CTRL_ACK | DMA_PREP_INTERRUPT); reinit_competion(&dma_comp); tx->callback = dma_callback; cookie = dmaengine_submit(tx); dma_async_issue_pending(chan); wait_for_completion(&dma_comp); } dma_release_channel(dma_chan); dma_free_coherent(NULL, MAX_DMA_TRANSFER_IN_BYTES, dma_buf, dma_phys_addr);