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);