DMA to EIM CS1 on i.mx6sololite

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

DMA to EIM CS1 on i.mx6sololite

1,942 Views
jayakumar2
Contributor V

Hi friends,

I have a i.mx6sololite based board, running yocto with linux kernel 3.0.35. I am happy to say that I am able to use the EIM interface on CS1 (EIM_CS1*) to do memory transactions with an fpga. So I can do memory mapped (on the host) register read/write successfully to/from the FPGA.

However, the performance is, as is expected, not good. So I'd like to improve it by using DMA instead. My thinking is the following:

- add character device driver which will support allocating DMAable memory (dma_alloc_coherent) and support triggering the DMA and managing the completion interrupt

- userspace application will use ioctl to talk to the character device driver to copy its userspace buffer into the DMAable memory and trigger the DMA to transfer the data to the fpga

I took a look at the following driver : Linux/drivers/dma/imx-dma.c - Linux Cross Reference - Free Electrons

But I'm unsure if that's a good starting point. Searching for EIM DMA example shows this link : working SDMA with EIM on iMX6

I would be grateful for any advice/suggestions on EIM DMA drivers.

Thanks,

jayakumar

Labels (2)
Tags (1)
0 Kudos
4 Replies

915 Views
Yuri
NXP Employee
NXP Employee

  The SDMA controller helps to optimize system performance by offloading

the CPU in dynamic data routing with relatively slow channels, such as UART,

SSI, SPI. The SDMA is not the best solution to achieve maximal throughput.

The ARM architecture provides more effective tools for it, such as special

block transfer instructions LDM / STM. Perhaps it makes sense to apply NEON

VLD / VST instructions for burst transfers.

 

  Also please pay attention of the CSREC bit field of EIM_CSnGCR1 register :

“CS Recovery. This bit field, according to the settings shown below, determines the

minimum pulse width of CS, OE, and WE control signals before executing a new back

to back access to the same chip select.”

   The most quick accesses are expected between so-called back-to-back ones,

when there are no gaps between transfers. For LDM / STM instructions this

means only two 32-bit accesses will be performed in such back-to-back manner.

Regards,

Yuri

915 Views
jayakumar2
Contributor V

Hi Yuri, Igor,

Thanks for your replies. They are helpful.

In my setup, I am currently using 16-bit wide EIM datapath so it is better than SPI. I think it makes sense to use SDMA because in my use case, we have image data generated on the host and then we want to transfer that to the FPGA for further processing while the host continues to do other tasks. So SDMA in the background makes sense.

I was able to get the mxc_sdma_memcopy_test.c which uses the dmaengine API on 3.0.35 to work on my setup. So I can see:

root@imx6slevk:/var/volatile/tmp# dd if=/dev/zero of=/dev/sdma_test bs=1 count=1

in dma_m2m_callback

root@imx6slevk:/var/volatile/tmp# cat /dev/sdma_test

buffer 1 copy passed!

buffer 2 copy passed!

buffer 3 copy passed!

But I am having some trouble converting that to target the EIM address space rather than memory to memory transfer.

The change I made was:

        {

        int FPGA_ADDR_BASE = 0x0C000000;

        rbuf = ioremap(FPGA_ADDR_BASE, 1024*1024);

        if(!rbuf) {

                printk("error rbuf !!!!!!!!!!!\n");

                return -1;

        }

        printk(KERN_ERR "got rbuf=0x%x\n", rbuf);

        }

and then change the dmaengine setup code to do:

        dma_m2m_config.direction = DMA_MEM_TO_DEV;

        dma_m2m_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;

        dmaengine_slave_config(dma_m2m_chan, &dma_m2m_config);

But when I test using this approach, I get:

root@imx6slevk:~# echo > /dev/sdma_test

got rbuf=0xc0c00000

sdma_write:215

sdma_write:224

sdma_write:227

sdma_write:236

sdma_write:239 m2m_desc=  (null)

[<7f04f210>] (sdma_write+0x208/0x2a4 [mxc_sdma_memcopy_test]) from [<800dd14c>] (vfs_write+0xa8/0x138)

So it seems the line:

        dma_m2m_desc = dma_m2m_chan->device->device_prep_slave_sg(dma_m2m_chan,sg2, 1, dma_m2m_config.direction, 0);

is failing because the device_prep_slave_sg is failing out. This function seems to be implemented within the mxc dma driver , drivers/dma/imx-dma.c.

I haven't figured out what the root cause of the failure is yet. I wanted to check with you if what I'm doing makes sense or if I've made an incorrect assumption.

I've attached the test source code. http://pastebin.com/1Ems9Qsa

Thanks,

jaya

0 Kudos

915 Views
rclongyunteng
Contributor I

Hi jaya,

I want to  transfer data from EIM to mx6q internal memory.  But i found a question like yours.
I have test mxc_sdma_memcopy_test.c example. It is useful for transfer between internal memory and internal memory. 
But I want it work as copy data from EIM to Memory. I think the mode is the same as transfer between external memory and internal memory. 
I have mapped eim address like below: 
        s_armaddr = ioremap_nocache(WEIM_ARB_BASE_ADDR, SDMA_BUF_SIZE ); 
And then i set the source buf like below: 
        sg_set_buf(&sg[0], s_armaddr + 0x16, SDMA_BUF_SIZE ); 

But the data i read form eim is not what i want. 
Any suggestions please? Thank you very much. 
Best Regards

0 Kudos

915 Views
igorpadykov
NXP Employee
NXP Employee

Hi Jaya

one can look at sdma patches and blog below

i.MX6 SDMA

Freescale i.MX SDMA tutorial (part I)

Best regards

igor

-----------------------------------------------------------------------------------------------------------------------

Note: If this post answers your question, please click the Correct Answer button. Thank you!

-----------------------------------------------------------------------------------------------------------------------