Hi there,
We are using IMX8MP for one of our project, I am writing a linux kernel driver for an ADC which works on SPI interface. To achieve high-speed data read, We are planning to use the DMA for data transmission. But there is not enough documentation available on how to implement that,
Moreover, i have read below threads, which makes it more complex to implement.
So, What is the best approach to use dma transfer?
Do I need to use the "dma_coherent_alloc()" apis?
I would like to do the same with iMX8MP and I thought to change the spi-imx.c mocking the UART driver tty/serial/imx.c based on cyrcular RX buffer.
Look at imx_uart_start_rx_dma using dmaengine_prep_dma_cyclic
Then you can get status of your ring with dmaengine_tx_status, as you can find in imx_uart_dma_rx_callback, or, I guess, you can even have the status of your ring without calling the callback, if you want a continuous transfer.
Regarding dma-names. Yes, to enable ECSPI DMA, your DT should include dma-names. You may verify if you have them set on live system. Find your SPI controller, perhaps like this, results from iMX7D:
# find /sys/firmware/ -name "*spi*" /sys/firmware/devicetree/base/soc/bus@30800000/spi@30bb0000
/sys/firmware/devicetree/base/soc/bus@30800000/spba-bus@30800000/spi@30820000
/sys/firmware/devicetree/base/soc/bus@30800000/spba-bus@30800000/spi@30830000
/sys/firmware/devicetree/base/soc/bus@30800000/spba-bus@30800000/spi@30840000
...
then look in device folder
# ls /sys/firmware/devicetree/base/soc/bus@30800000/spba-bus@30800000/spi@30820000
#address-cells clocks dmas reg
#size-cells compatible interrupts status
clock-names dma-names name
DMA is enabled, just check what's in dma-names
hexdump -C /sys/firmware/devicetree/base/soc/bus@30800000/spba-bus@30800000/spi@30820000/dma-names
00000000 72 78 00 74 78 00 |rx.tx.|
00000006
Regarding "only carry out DMA transfer if the data size is more than 64 bytes"
Not 64 bytes but 64 (x 32bit) FIFO entries. So more than 64 bytes with 8-bit transfer units; 64 words or double words in 16- and 32-bit mode. If you are using spidev_test utility, -b / --bpw bits per word command line switch controls it. Your Linux SPI device as well specifies transfer bits per word. Most likely your driver uses 8-bits to simplify compatibility.
Shorter than 64x transfers simply don't need DMA at all, FIFO is enough.
Thank you for your response!
Actually, I want to continuously read the data from an ADC in the kernel thread, so when I don't use the DMA and go with the PIO method, the CPU usage just goes crazy (> 70%). For SPI transactions, I wish to offload that using DMA. I have made changes in the spi-imx.c to forcefully use the dma instead of 64-byte fifo limit.
While the standard regiser read/write APIs function well with DMA, the SPI transactions fail when reading the samples, and spi_sync returns an error code.
What could be the issue? Something I have overlooked?
PS: When I perform a register read/write transaction, I also receive the DMA debug prints, confirming that DMA is functioning with register read/write.
Here's my api to read the samples
int ad4134_sample_read(struct spi_device *spi)
{
int ret;
uint32_t pad[8] = {0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff};
struct spi_transfer tr =
{
.tx_buf = pad,
.rx_buf = st.sample,
.len = 32,
.bits_per_word = 32,
};
struct spi_message m;
spi_message_init(&m);
spi_message_add_tail(&tr, &m);
spi_sync(spi,&m);
return 0;
}
sorry for my delay, as I known imx8mp spi DMA has delay issue, I'm not sure if your case is caused by this issue I sent patch to you via mail, you can test it
I checked the spi driver, it seems it already enable DMA
https://github.com/nxp-imx/linux-imx/blob/lf-6.1.y/drivers/spi/spi-imx.c