We have module_test\mxc_sdma_memcopy_test.c in the uni_test
test\mxc_sdma_test\mxc_sdma_test.c in the uni_test is the user space application to do the test.
If you read the code carefully, the driver is written by Linux DMA API and the BSP just mapping the Linux DMA API to sdma of the i.MX6.
If you check the Linux header file, the DMA_BIDIRECTIONAL, DMA_TO_DEVICE, DMA_FROM_DEVICE, DMA_NONE is listed.
include\linux\dma-direction.h
#define _LINUX_DMA_DIRECTION_H
/*
* These definitions mirror those in pci.h, so they can be used
* interchangeably with their PCI_ counterparts.
*/
enum dma_data_direction {
DMA_BIDIRECTIONAL = 0,
DMA_TO_DEVICE = 1,
DMA_FROM_DEVICE = 2,
DMA_NONE = 3,
};
#endif
please note the following line in the driver.
dma_m2m_desc = dma_m2m_chan->device->device_prep_dma_memcpy(dma_m2m_chan, dma_dst, dma_src, SDMA_BUF_SIZE,0);
ssize_t sdma_write(struct file * filp, const char __user * buf, size_t count,
loff_t * offset)
{
u32 *index1, *index2, *index3, i, ret;
struct dma_slave_config dma_m2m_config = {0};
struct dma_async_tx_descriptor *dma_m2m_desc;
u32 *index4 = wbuf4;
dma_addr_t dma_src, dma_dst;
index1 = wbuf;
index2 = wbuf2;
index3 = wbuf3;
for (i=0; i<SDMA_BUF_SIZE/4; i++) {
*(index1 + i) = 0x12121212;
}
for (i=0; i<SDMA_BUF_SIZE/2/4; i++) {
*(index2 + i) = 0x34343434;
}
for (i=0; i<SDMA_BUF_SIZE/4; i++) {
*(index3 + i) = 0x56565656;
}
for (i=0; i<SDMA_BUF_SIZE/4; i++) {
*(index4 + i) = 0x56565656;
}
#if 0
for (i=0; i<SDMA_BUF_SIZE/4; i++) {
printk("input data_%d : %x\n", i, *(wbuf+i));
}
for (i=0; i<SDMA_BUF_SIZE/2/4; i++) {
printk("input data2_%d : %x\n", i, *(wbuf2+i));
}
for (i=0; i<SDMA_BUF_SIZE/4; i++) {
printk("input data3_%d : %x\n", i, *(wbuf3+i));
}
#endif
dma_m2m_config.direction = DMA_MEM_TO_MEM;
dma_m2m_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
dmaengine_slave_config(dma_m2m_chan, &dma_m2m_config);
sg_init_table(sg, 3);
sg_set_buf(&sg[0], wbuf, SDMA_BUF_SIZE);
sg_set_buf(&sg[1], wbuf2, SDMA_BUF_SIZE/2);
sg_set_buf(&sg[2], wbuf3, SDMA_BUF_SIZE);
ret = dma_map_sg(NULL, sg, 3, dma_m2m_config.direction);
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,0,35))
dma_m2m_desc = dma_m2m_chan->device->device_prep_slave_sg(dma_m2m_chan,sg, 3, dma_m2m_config.direction, 1);
#endif
sg_init_table(sg2, 3);
sg_set_buf(&sg2[0], rbuf, SDMA_BUF_SIZE);
sg_set_buf(&sg2[1], rbuf2, SDMA_BUF_SIZE/2);
sg_set_buf(&sg2[2], rbuf3, SDMA_BUF_SIZE);
ret = dma_map_sg(NULL, sg2, 3, dma_m2m_config.direction);
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,0,35))
dma_m2m_desc = dma_m2m_chan->device->device_prep_slave_sg(dma_m2m_chan,sg2, 3, dma_m2m_config.direction, 0);
#else
dma_m2m_desc = dma_m2m_chan->device->device_prep_dma_sg(dma_m2m_chan,sg2, 3, sg, 3, 0);
#endif
dma_m2m_desc->callback = dma_m2m_callback;
dmaengine_submit(dma_m2m_desc);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,35))
dma_async_issue_pending(dma_m2m_chan);
#endif
wait_for_completion(&dma_m2m_ok);
dma_unmap_sg(NULL, sg, 3, dma_m2m_config.direction);
dma_unmap_sg(NULL, sg2, 3, dma_m2m_config.direction);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,35))
dma_src = dma_map_single(NULL, wbuf4, SDMA_BUF_SIZE, DMA_TO_DEVICE);
dma_dst = dma_map_single(NULL, rbuf4, SDMA_BUF_SIZE, DMA_FROM_DEVICE);
dma_m2m_desc = dma_m2m_chan->device->device_prep_dma_memcpy(dma_m2m_chan, dma_dst, dma_src, SDMA_BUF_SIZE,0);
if (!dma_m2m_desc)
printk("prep error!!\n");
dma_m2m_desc->callback = dma_m2m_callback;
dmaengine_submit(dma_m2m_desc);
dma_async_issue_pending(dma_m2m_chan);
wait_for_completion(&dma_m2m_ok);
dma_unmap_single(NULL, dma_src, SDMA_BUF_SIZE, DMA_TO_DEVICE);
dma_unmap_single(NULL, dma_dst, SDMA_BUF_SIZE, DMA_FROM_DEVICE);
#endif
return 0;
}
struct file_operations dma_fops = {
open: sdma_open,
release: sdma_release,
read: sdma_read,
write: sdma_write,
};