Hello, NXP,
I want to use edma on the LS1012A board. I am using the LSDK1812 SDK, and I would appreciate it if you could share a memory copy example using a kernel module program. An example that can be applied to an application would also be helpful.
I am requesting this urgently, so I would appreciate your prompt response.
Thank you.
Gyosun,
解決済! 解決策の投稿を見る。
There is one patch realizing edma memcopy, you can apply it or use latest kernel which kernel version> 6.1.1.
Also there is some tiny errors in main.c file, we had modified it.
Attach the log for your reference.
For eDMA driver, please refer to drivers/dma/fsl-edma.c.
Use the slave device which deploys the eDMA functionality to verify the eDMA driver, below is a verification with the I2C
salve.
root@ls1021aqds:~# i2cdetect 0
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0.
I will probe address range 0x03-0x77.
Continue? [Y/n]
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- 69 -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
root@ls1021aqds:~# i2cdump 0 0x69 i
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 05 07 ff ff 5d 55 10 55 11 05 1e 00 e8 03 b5 ff ??..]U?U???.???.
10: ff e8 03 95 00 00 00 00 aa fe 9a 00 00 00 00 78 .???....???....x
20: 05 12 04 ff 00 7f 40 14 1d 60 3c 83 05 00 40 00 ???..?@??`<??.@.
30: fe 80 c6 29 00 00 00 7a 00 ff ff ff ff ff ff ff ???)...z........
40: 05 07 ff ff 5d 55 10 55 11 05 1e 00 e8 03 b5 ff ??..]U?U???.???.
50: ff e8 03 95 00 00 00 00 aa fe 9a 00 00 00 00 78 .???....???....x
60: 05 12 04 ff 00 7f 40 14 1d 60 3c 83 05 00 40 00 ???..?@??`<??.@.
70: fe 80 c6 29 00 00 00 7a 00 ff ff ff ff ff ff ff ???)...z........
80: 07 ff ff 5d 55 10 55 11 05 1e 00 e8 03 b5 ff ff ?..]U?U???.???..
90: e8 03 95 00 00 00 00 aa fe 9a 00 00 00 00 78 00 ???....???....x.
a0: 12 04 ff 00 7f 40 14 1d 60 3c 83 05 00 40 00 fe ??..?@??`<??.@.?
b0: 80 c6 29 00 00 00 7a 00 ff ff ff ff ff ff ff ff ??)...z.........
c0: 07 ff ff 5d 55 10 55 11 05 1e 00 e8 03 b5 ff ff ?..]U?U???.???..
d0: e8 03 95 00 00 00 00 aa fe 9a 00 00 00 00 78 00 ???....???....x.
e0: 12 04 ff 00 7f 40 14 1d 60 3c 83 05 00 40 00 fe ??..?@??`<??.@.?
f0: 80 c6 29 00 00 00 7a 00 ff ff ff ff ff ff ff ff ??)...z.........
root@ls1021aqds:~# cat /proc/interrupts
CPU0 CPU1
29: 0 0 GIC 29 arch_timer
30: 5563 5567 GIC 30 arch_timer
112: 260 0 GIC 112 fsl-lpuart
120: 32 0 GIC 120 2180000.i2c
121: 0 0 GIC 121 2190000.i2c
167: 8 0 GIC 167 eDMA
IPI0: 0 1 CPU wakeup interrupts
IPI1: 0 0 Timer broadcast interrupts
IPI2: 1388 1653 Rescheduling interrupts
IPI3: 0 0 Function call interrupts
IPI4: 2 4 Single function call interrupts
IPI5: 0 0 CPU stop interrupts
Err: 0
root@ls1021aqds:~#
Hi yipingwang,
Thank you for your response.
I apologize for the delay in getting back to you.
I'm looking for a memory-to-memory example using fsl-edma.c.
If you happen to have one, could you please share it with me?
Thanks,
Gyosun.
Additionally, we tested:
Looking at the fsl-edma.c code of the LSDK1812 I am using,
It seems to support device_prep_slave_sg and device_prep_dma_cyclic.
dma_cap_set(DMA_PRIVATE, fsl_edma->dma_dev.cap_mask);
dma_cap_set(DMA_SLAVE, fsl_edma->dma_dev.cap_mask);
dma_cap_set(DMA_CYCLIC, fsl_edma->dma_dev.cap_mask);
fsl_edma->dma_dev.device_prep_slave_sg = fsl_edma_prep_slave_sg;
fsl_edma->dma_dev.device_prep_dma_cyclic = fsl_edma_prep_dma_cyclic;
fsl_edma->dma_dev.device_config = fsl_edma_slave_config;
So, I have written as follows.
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE,mask);
dma_chan = dma_request_channel(mask,0,NULL);
if(dma_chan == 0) printk("failed to request DMA channel\n");
else printk("passed to request DMA channel %d\n", dma_chan->chan_id);
I have been assigned an ID without any issues.
static ssize_t dma_memcpy_sg(uint64_t paddr_dst, uint64_t paddr_src, size_t count)
{
struct dma_async_tx_descriptor *tx_desc = NULL;
struct dma_device *dma_dev = dma_chan->device;
dma_cookie_t cookie;
int ret, src_cnt = 1;
enum dma_transfer_direction dir = DMA_DEV_TO_MEM;
struct scatterlist sg;
struct dma_slave_config dma_config;
/* Configure the slave DMA */
memset(&dma_config, 0, sizeof(dma_config));
dma_config.direction = DMA_DEV_TO_MEM;
dma_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma_config.src_addr = dma_buf_handle_tx;
dma_config.src_maxburst = 1;
//ret = dmaengine_slave_config(dma_chan, &dma_config);
ret = dma_dev->device_config(dma_chan, &dma_config);
if (ret) {
pr_err("Failed to configure DMA slave\n");
}
sg_init_table(&sg, src_cnt);
sg_dma_address(&sg) = (uint64_t)paddr_dst;
sg_dma_len(&sg) = count;
//tx_desc = dmaengine_prep_slave_sg(dma_chan,
tx_desc = dma_dev->device_prep_slave_sg(dma_chan,
&sg,
src_cnt,
dir,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK, NULL);
if (!tx_desc) {
pr_err("[%d]Failed to prepare DMA memcpy\n", __LINE__);
return -1;
}
tx_desc->callback = complete_rx_dma;
//cookie = dmaengine_submit(tx_desc);
cookie = tx_desc->tx_submit(tx_desc);
if (dma_submit_error(cookie)) {
pr_err("[%d]Failed to do DMA tx_submit\n",__LINE__);
return -1;
}
dma_async_issue_pending(dma_chan);
}
When I execute the dma_memcpy_sg function, there are no pr_err messages, and there is no increase in the edma interrupt in /proc/interrupt. I'm not able to perform the copy, so I would appreciate some advice on what could be the problem.
Thanks,
Gyosun.
Please refer to the following update from the AE team.
Did customer try to transfer with single descriptor?
I saw customer use DMA_DEV_TO_MEM for tx, what's the direction of the transfer? Is it from device to memory?
We haven't example for scattergather transfer on hand, customer can refer to drivers/i2c/busses/i2c-imx.c for single transfer.
Hi yipingwang,
Thank you for your response.
I am currently experimenting with memory-to-memory transfers, but ultimately, I am aiming for memory-to-PCIe transfers.
Since I need to allocate the BAR (Base Address Register) and transfer data from memory to PCIe, I wanted to explore memory-to-memory transfers first.
If you have any relevant examples to share, please let me know.
Thanks,
Gyosun.
Please refer to the following update from the AE team.
I suggest customer to try single transfer first, then we can see if their DMA can work normally. And customer should use DMA_MEM_TO_MEM for copying between memory.
Hi yipingwang,
Is the approach you suggested applicable in the LSDK18.12 LS1012A environment?
If so, could you please provide the location of the relevant Linux source code for DMA_MEM_TO_MEM?
Thanks,
Gyosun.
Here is the definition of DMA direction, in include/linux/dmaengine.h
/**
* enum dma_transfer_direction - dma transfer mode and direction indicator
* @dma_MEM_TO_MEM: Async/Memcpy mode
* @dma_MEM_TO_DEV: Slave mode & From Memory to Device
* @dma_DEV_TO_MEM: Slave mode & From Device to Memory
* @dma_DEV_TO_DEV: Slave mode & From Device to Device
*/
enum dma_transfer_direction {
DMA_MEM_TO_MEM,
DMA_MEM_TO_DEV,
DMA_DEV_TO_MEM,
DMA_DEV_TO_DEV,
DMA_TRANS_NONE,
};
We haven't example code on hand. There is the usage of it can be searched in kernel code. Of can customer share their test file then we can try locally?
Hi yipingwang,
I have attached the test example that I have tested.
I have compiled it with LSDK18.12.
After the compilation, when the dev_pci_xdma_ls1012a.ko file is generated,
it should be copied to the board.
By performing the following three steps, the test results will be displayed easily.
insmod dev_pci_xdma_ls1012a.ko
echo 0 > /sys/kernel/kobject_example/test_mode
echo 1 > /sys/kernel/kobject_example/test_mode
Please analyze the reasons why it is not functioning when executed on the actual board.
Thanks,
Gyosun.
Hi yipingwang,
Oh my god!!
This aligns with what we desired.
I have confirmed that it works well with the LSDK 18.12 patch.
It would be great if the new LSDK version also includes DMA_MEMCPY and DMA_SG.
Thank you so much.
Gyosun.