Use DMA transaction in SPI device driver

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Use DMA transaction in SPI device driver

2,028 Views
pratham_malaviya
Contributor III

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.

  1. They say in this thread that we may need to add "dma-names" and modify dts for the dma support, with the spi-imx.c and dma subsystem handling everything else. and we only need to use standard spi APIs.
  2. According to this thread, the controller will only carry out DMA transfer if the data size is more than 64 bytes. Also they are changing the spi-imx.c file to force the dma transfer.

So, What is the best approach to use dma transfer?

Do I need to use the "dma_coherent_alloc()" apis?

Labels (1)
Tags (4)
0 Kudos
Reply
5 Replies

1,570 Views
atessadri
Contributor I

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.

 

0 Kudos
Reply

1,976 Views
kef2
Senior Contributor V

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. 

 

0 Kudos
Reply

1,966 Views
pratham_malaviya
Contributor III

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;

}

Tags (3)
0 Kudos
Reply

1,872 Views
joanxie
NXP TechSupport
NXP TechSupport

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

0 Kudos
Reply

1,980 Views
joanxie
NXP TechSupport
NXP TechSupport

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

0 Kudos
Reply