This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

OMAP4 GPMC DMA transfer issues

Other Parts Discussed in Thread: 4460, SYSCONFIG

Hi,

I am trying to do DMA write and read over GPMC between OMAP4460 and Ethernet device. The read and write gpmc data transfer (without DMA) are working. But I am finding DMA transfers issues after the DMA is configured and started, data transfer is not happening.

A similar configration (code reference) is working between AM35xx and FPGA over GPMC in DMA mode on custom board.

From E2E forum topic (http://e2e.ti.com/support/omap/f/849/p/161654/658397.aspx#658397) its mentioned that there is difference between OMAP3 and OMAP4 DMA. But it did not throw any light on solving this issue.


I tried OMAP24XX_DMA_GPMC trigger in omap_request_dma() for requesting the channel ( channel 0 assigned for the transfer) and in omap_set_dma_transfer_params() for setting DMA transfer. Then I don't see the DMA callback getting called and and its unable to finish the DMA transfer.

I also tried DMA_NO_DEVICE trigger. But it crashes on OMAP4.

I tried a simple mem->mem transfer using the OMAP24XX_DMA_GPMC trigger. That also had the same issue.

Let me know, If I am missing anything on OMAP4 DMA setup.

My configurations look like these:


ret = omap_request_dma(OMAP24XX_DMA_GPMC, "xxxx", callback_fn, &info->comp, &info->dma_ch);

dma_transfer_func()
{
dma_addr = dma_map_single(&info->pdev->dev, info->dma_buf, len,dir);
if (dma_mapping_error(&global_info->pdev->dev, dma_addr)) {
printk("Couldn't DMA map a %d byte buffer\n", len);
goto out_copy;
}


if (is_write) {
omap_set_dma_dest_params(info->dma_ch, 0, OMAP_DMA_AMODE_CONSTANT,
buf, 0, 0);
omap_set_dma_src_params(info->dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
dma_addr, 0, 0);
omap_set_dma_transfer_params(info->dma_ch, OMAP_DMA_DATA_TYPE_S16,
0x10, buf_len, OMAP_DMA_SYNC_FRAME,
OMAP24XX_DMA_GPMC, OMAP_DMA_DST_SYNC);
} else {
omap_set_dma_src_params(info->dma_ch, 0, OMAP_DMA_AMODE_CONSTANT,
buf, 0, 0);
omap_set_dma_dest_params(info->dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
dma_addr, 0, 0);
omap_set_dma_transfer_params(info->dma_ch, OMAP_DMA_DATA_TYPE_S16,
0x10, buf_len, OMAP_DMA_SYNC_FRAME,
OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);
}

init_completion(&info->comp);

omap_start_dma(info->dma_ch);

/* setup and start DMA using dma_addr */
wait_for_completion(&info->comp);
}

My callback fn:

callback_fn(int lch, u16 ch_status, void *data)
{
struct completion *comp = data;
complete (comp);
dma_unmap_single(&info->pdev->dev, info->dma_addr, len, info->dma_dir);
omap_stop_dma(info->dma_ch);
}


I have also tried BURST_MODE but that also didnt work. The configurations i used were:

omap_set_dma_src_burst_mode(info->dma_ch, OMAP_DMA_DATA_BURST_8);
omap_set_dma_dest_burst_mode(info->dma_ch, OMAP_DMA_DATA_BURST_8);
omap_set_dma_write_mode (info->dma_ch, OMAP_DMA_WRITE_NON_POSTED);
omap_set_dma_src_data_pack(info->dma_ch, 1);
omap_set_dma_dest_data_pack(info->dma_ch, 1);
omap_dma_set_prio_lch(info->dma_ch, DMA_CH_PRIO_HIGH, DMA_CH_PRIO_HIGH);

I'm using kernel version 3.0.8

Any help is appreciated. Thanks in advance.

  • Umesh,

    Which platform are you using (ie, Blaze, Panda, custom) and which software release are you using (for example, 4AI.1.6)?  How are you using the Ethernet device?  ie, Is it a USB-Ethernet adaptor?  

    I noticed in your code that you are performing the dma_unmap_single() in the callback function, as opposed to in the transfer function.  This is different from the OMAP4 NAND driver, which uses GPMC/DMA.  See the code in /drivers/mtd/nand/omap2.c.  Also, I noticed that you are not enabling the GPMC pre-fetch (may not be needed if you are not using NAND). 

    Other than this, I would suggest using print statements or a JTAG to find out specifically why the callback function is not being called.

    Regards,
    Gina

  • Gina,

    Thanks for the response.

    We are using a custom board based on OMAP4460. The release version we used as base was L27.IS.2.P2_OMAP4(January 2012) for Blaze. We have the ethernet device connected on the GPMC port.

    We tried the dma_unmap_single() in the transfer function but the code never reaches there. It gets stuck in omap_start_dma().

    Yes, we figured we dont need to enable the GPMC pre-fetch since we are not using NAND.

    Apart from callback function not getting called, we dont see the dma transfer getting completed too.

    Is there any other reference board based on OMAP4460 where GPMC DMA is used?

    Appreciate the help.

    Umesh.

  • Umesh,

    You may want to look at the Device Driver Tests for DMA on OMAP, located here: https://gitorious.org/omap-ddt/omap-ddt/trees/master/dma/test_code/utils/dma

    Here are instructions for downloading and compiling the test cases, if you want to try them out: http://omappedia.org/wiki/OMAP_Kernel_driver_tests

    Regards,
    Gina 

  • Sorry for my englisch, but I have the same problem. We have the PandaBoard this the 4460 CPU. The memory on GPMC ist the CYDC128B161 Dual Port memory.

    We can already read and write to, the mode is "NOR", and the address lines and data lines are multiplexed.

    The "chip select" is 0, and the size is 16 bit times 0x4000

    I have the example "Scenario:    L_DD_DMA_0003_0001" of the "test_code" adjusted so that it actually
    should write to DP-Ram. I had to change it slightly, all functions are now running without error.

    But the DMA does not start.

    I have all registers, read with "omapconf" after the DMA start:

    GPMC_REVISION:          00000060
    GPMC_SYSCONFIG:         00000011
    GPMC_SYSSTATUS:         00000001
    GPMC_IRQSTATUS:         00000000
    GPMC_IRQENABLE:         00000000
    GPMC_TIMEOUT_CONTROL:   00000000
    GPMC_ERR_ADDRESS:       00000000
    GPMC_ERR_TYPE:          00000000
    GPMC_CONFIG:            00000A00
    GPMC_STATUS:            00000901
    GPMC_CONFIG1_0:         00001210
    GPMC_CONFIG2_0:         00101001
    GPMC_CONFIG3_0:         221F1F14
    GPMC_CONFIG4_0:         10057016
    GPMC_CONFIG5_0:         010F1111
    GPMC_CONFIG6_0:         8F070000
    GPMC_CONFIG7_0:         00000F41
    GPMC_NAND_DATA_0:       00006D4F
    GPMC_PREFETCH_CONFIG_1: 00004000
    GPMC_PREFETCH_CONFIG_2: 00000000
    GPMC_PREFETCH_CONTROL:  00000000
    GPMC_PREFETCH_STATUS:   00000000
    GPMC_ECC_CONFIG:        00001030
    GPMC_ECC_CONTROL:       00000000
    GPMC_ECC_SIZE_CONFIG:   FFFFF000
    GPMC_ECC0_RESULT:       00000000
    GPMC_BCH_RESULT0_0:     00000000
    GPMC_BCH_RESULT1_0:     00000000
    GPMC_BCH_RESULT2_0:     00000000
    GPMC_BCH_RESULT3_0:     00000000
    GPMC_BCH_RESULT4_0:     00000000
    GPMC_BCH_RESULT5_0:     00000000
    GPMC_BCH_RESULT6_0:     00000000
    GPMC_BCH_SWDATA:        00000000

    DMA4_REVISION:     00010900
    DMA4_IRQSTATUS_L3: 00000003
    DMA4_IRQENABLE_L3: 00000000
    DMA4_SYSSTATUS:    00000001
    DMA4_CAPS_0:       001C0000
    DMA4_CAPS_2:       000001FF
    DMA4_CAPS_3:       000000F3
    DMA4_CAPS_4:       00007FFE
    DMA4_GCR:          00030010
    DMA4_CCR0:         040050C4
    DMA4_CLNK_CTRL0:   00000000
    DMA4_CICR0:        00000922
    DMA4_CSR0:         00000000
    DMA4_CSDP0:        00020001
    DMA4_CEN0:         00000401
    DMA4_CFN0:         00000001
    DMA4_CSSA0:        AA005000
    DMA4_CDSA0:        010037FC
    DMA4_CSEI0:        00000000
    DMA4_CSFI0:        00000000
    DMA4_CDEI0:        00000000
    DMA4_CDFI0:        00000000
    DMA4_CSAC0:        A9649000
    DMA4_CDAC0:        00000000
    DMA4_CCEN0:        00000000
    DMA4_CCFN0:        00000000
    DMA4_COLOR0:       00000000
    DMA4_CDP0:         00000000
    DMA4_CNDP0:        00000000
    DMA4_CCCDN0:       00000000

    PS.: One example read  DMA4_REVISION on command line:

    echo "DMA4_REVISION:     $(omapconf read 0x4A056000)"

    Please Help

    Sincerely Hubert




  • I had to write forget that in asynchronous mode on the memory is being accessed.

    Sincerely Hubert

  • Hubert,

    Have you followed carefully the required DMA sequencing, as described in chapter 16.5.2 of the OMAP4 TRM?

    Regards,
    Gina 

  • Thank you Gina,
    I actually think I'll do it that way. Maybe I'm wrong,
    because I used the kernel functions.
    I've written a short test code executed when the driver,
    but the only thing I see is:
    [ 1788.611907] DMA SRC  ADDR: 0xAA03E3C0
    [ 1788.611907] DMA DEST ADDR: 0x1000200

    Here is the code:
    #define START_INDEX_DMA_W (512)
    static struct completion comp;
    void _dma_callback(int transfer_id, u16 transfer_status, void *data)
    {
       printk(KERN_INFO "DMA is running :-)!!\n");
       complete((struct completion *) &comp);
    }
    void dma_test(unsigned int dpmemadrr)
    {
        unsigned int src_buf; /* virtual source buffer address */
        unsigned int src_buf_phys; /* physycal source buffer address */
        unsigned int dest_buf_phys_w; /* physycal destination buffer address */
        unsigned int buf_size; /* buffer size in bytes */
        int  transfer_id;
        int success;
        dest_buf_phys_w=dpmemadrr+ START_INDEX_DMA_W;
        success=omap_request_dma(OMAP44XX_DMA_GPMC,"dma",dma_callback,NULL,&transfer_id);
        if (success) {
          printk(" Request failed\n");
          return;
        }
        buf_size=256;
        src_buf=(unsigned int)kmalloc(256,GFP_DMA);
        src_buf_phys=dma_map_single(NULL,(void *)src_buf
                     ,buf_size, DMA_BIDIRECTIONAL);
        if (src_buf_phys == 0 ) {
          printk(KERN_ERR "SRC DMA Mapping failed\n");
            return;
        }
        printk("DMA SRC  ADDR: 0x%X\n",src_buf_phys);
        printk("DMA DEST ADDR: 0x%X\n",dest_buf_phys_w);
        omap_set_dma_transfer_params(
                    transfer_id,
                    OMAP_DMA_DATA_TYPE_S16,
                    buf_size/2,//OMAP_DMA_DATA_TYPE_S16,
                    1,
                    OMAP_DMA_SYNC_ELEMENT,
                    OMAP44XX_DMA_GPMC,
                    0);
         omap_set_dma_src_params(
                    transfer_id,0,OMAP_DMA_AMODE_POST_INC,
                    src_buf_phys,0,0);
         omap_set_dma_src_burst_mode(
                    transfer_id,OMAP_DMA_DATA_BURST_DIS);
         omap_set_dma_dest_params(
                    transfer_id,0,OMAP_DMA_AMODE_POST_INC,
                    dest_buf_phys_w,0,0);
         omap_set_dma_dest_burst_mode(
                    transfer_id,OMAP_DMA_DATA_BURST_DIS);
         omap_dma_set_global_params(
                    0x3, DMA_DEFAULT_FIFO_DEPTH,0);
         omap_dma_set_prio_lch(
                    transfer_id,DMA_CH_PRIO_HIGH,DMA_CH_PRIO_HIGH);
         omap_set_dma_write_mode(
                    transfer_id,OMAP_DMA_WRITE_LAST_NON_POSTED);
         init_completion(&comp);
         omap_start_dma(transfer_id);
         wait_for_completion(&comp);
         printk("DMA Completion message came :-)\n");
    }

    And here the Resgister frrom 16.5.2 of the OMAP4 TRM,after start the driver and wait for the irq:
    DMA4_CSDP0:        0x00020001
    DMA4_CEN0:         0x00000080
    DMA4_CFN0:         0x00000001
    DMA4_CSSA0:        0xAA03E3C0
    DMA4_CDSA0:        0x01000200
    DMA4_CCR0:         0x040050C4
    DMA4_CSEI0:        0x00000000
    DMA4_CSFI0:        0x00000000
    DMA4_CDEI0:        0x00000000
    DMA4_CDFI0:        0x00000000
    The only thing that strikes me:
    DMA4_CCR0[4:0] = 4 ??
    This comes from the parameter OMAP44XX_DMA_GPMC,but if I write a 0 pure, there is an error.

    Sincerely Hubert

  • Hubert,

    Especially since DMA4_CCR0[20:19] is 0, DMA4_CCR0[4:0] should be 0 for a nonsynchronized transfer.  What kind of error do you get when you write a 0?  I believe you should just pass 0 as the 6th parameter to  omap_set_dma_transfer_params(), rather than passing OMAP44XX_DMA_GPMC.  OMAP44XX_DMA_GPMC should only be used in the omap_request_dma() function.

    Regards,
    Gina 

  • Thank you Gina,
    that was it, the logic analyzer showed the data were written.
    It comb only a NULL pointer message from the IRQ that is also achieved.

    Regards,
    Hubert

  • Hello there

    I have a very basic question regarding the omap dma api.

    I try to read from the gpmc of an omap4 device using the DMA. when I start the transfer using the function omap_start_dma(transfer_id); , I can observe the gpmc signal on the scope which works fine. Also the dma interrupt is call as expected. But now my question is where can I access the transferred data.

     src_buf_phys=dma_map_single(NULL,(void *)src_buf ,buf_size,  DMA_FROM_DEVICE);

    When I plot the content of src_buf which is in my case the destination buffer I get lots of values with are unequal to zero (noting connected to the gpmc), When i try to plot the content of the src_buf_phys I get an segmentation error.

    Cold anybody tell me please how to access the transferred data in kernel space?

    my dma callback function look like this

    void dma_callback(int transfer_id, u16 transfer_status, void *data)
    {
       complete((struct completion *) &comp);
    }

    Thanks for your help!!

    BR,

    Arnold

  • I try to interface an FPGA with the OMAP4 using the GPMC in synchronous burst mode.
    The FPGA acts like an FIFO which triggers just on the GPMC_CLK and GPMC_CS signals and outputs the data on the 16Bit GPMC_AD bus.
    The GPMC is configured in non-multiplexed 16Bit NOR Flash mode. To enable the burst mode of the GPMC a DMA is used. The kernel code below shows the DMA configuration.


        ret=omap_request_dma(OMAP44XX_DMA_GPMC,"dma",dma_callback,NULL,&spartan_dma.transfer_id);

        omap_set_dma_transfer_params(spartan_dma.transfer_id,
                      OMAP_DMA_DATA_TYPE_S16,
                      spartan_dma.buffers.buf_size / 2,
                      1,
                      OMAP_DMA_SYNC_ELEMENT,
                      0,
                      0);

           omap_set_dma_src_params(
                      spartan_dma.transfer_id,0,OMAP_DMA_AMODE_POST_INC,
                      cs_mem_base,1,1);

        omap_set_dma_dest_params(
                       spartan_dma.transfer_id,0,OMAP_DMA_AMODE_POST_INC,
                       spartan_dma.buffers.ping_buf_phys,1,1);

           omap_set_dma_src_burst_mode(
                      spartan_dma.transfer_id,OMAP_DMA_DATA_BURST_16 );


           omap_set_dma_dest_burst_mode(
                      spartan_dma.transfer_id,OMAP_DMA_DATA_BURST_16  );

          omap_set_dma_dest_data_pack(spartan_dma.transfer_id,1);
          omap_set_dma_src_data_pack(spartan_dma.transfer_id,1);

           omap_dma_set_global_params(
                      0x1, 0x20,DMA_THREAD_RESERVE_THREET);
           omap_dma_set_prio_lch(
                      spartan_dma.transfer_id,DMA_CH_PRIO_HIGH,DMA_CH_PRIO_HIGH);

            omap_start_dma(spartan_dma.transfer_id);


    DMA Register content:

    [159908.133087] REVISION:10900
    [159908.137329] IRQSTATUS_L3:f
    [159908.140319] IRQENABLE_L3:0
    [159908.145416] SYSSTATUS:1
    [159908.148132] CAPS_0:1c0000
    [159908.153076] CAPS_1:10900
    [159908.155883] CAPS_2:1ff
    [159908.160461] CAPS_3:f3
    [159908.163024] CAPS_4:7ffe
    [159908.167663] GCR:10020
    [159908.170196] CCR:4005040
    [159908.174865] CLNK_CTRL:0
    [159908.177612] CICR:922
    [159908.180053] CSR:0
    [159908.184844] CSDP:e1c1
    [159908.187377] CEN:200
    [159908.191589] CFN:1
    [159908.193756] CSSA:1000000
    [159908.198455] CDSA:aaa2c800
    [159908.201354] CSEI:1
    [159908.203613] CSFI:1
    [159908.208557] CDEI:1
    [159908.210815] CDFI:1
    [159908.214874] CSAC:1000400
    [159908.217681] CDAC:aaa2ac00
    [159908.222778] CCEN:200
    [159908.225219] CCFN:0
    [159908.229309] COLOR:0
    [159908.231689] CDP:0
    [159908.233825] CNDP:0
    [159908.238616] CCDN:0

    The GPMC is configured as following

    159782.092132] GPMC_SYSCONFIG :0
    [159782.096313] GPMC_REVISION   :60
    [159782.099792] GPMC_SYSSTATUS  :1
    [159782.104827] GPMC_IRQSTATUS  :0
    [159782.108184] GPMC_IRQENABLE:0
    [159782.113128] GPMC_TIMEOUT_CONTROL:0
    [159782.116882] GPMC_ERR_ADDRESS:0
    [159782.121948] GPMC_ERR_TYPE:0
    [159782.125061] GPMC_CONFIG:2
    [159782.129364] GPMC_STATUS:901
    [159782.132446] GPMC_CS_CONFIG1:79001013
    [159782.138061] GPMC_CS_CONFIG2:a0a00
    [159782.142700] GPMC_CS_CONFIG3:0
    [159782.145965] GPMC_CS_CONFIG4:10056a12
    [159782.151611] GPMC_CS_CONFIG5:808110b
    [159782.155426] GPMC_CS_CONFIG6:8f070f8f
    [159782.161224] GPMC_CS_CONFIG7:f41


    The OMAP mux is configured the following:

    cd /sys/kernel/debug/omap_mux
    sudo echo 0x100 > gpmc_ad0
    sudo echo 0x100 > gpmc_ad1
    sudo echo 0x100 > gpmc_ad2
    sudo echo 0x100 > gpmc_ad3
    sudo echo 0x100 > gpmc_ad4
    sudo echo 0x100 > gpmc_ad5
    sudo echo 0x100 > gpmc_ad6
    sudo echo 0x100 > gpmc_ad7
    sudo echo 0x100 > gpmc_ad8
    sudo echo 0x100 > gpmc_ad9
    sudo echo 0x100 > gpmc_ad10
    sudo echo 0x100 > gpmc_ad11
    sudo echo 0x100 > gpmc_ad12
    sudo echo 0x100 > gpmc_ad13
    sudo echo 0x100 > gpmc_ad14
    sudo echo 0x100 > gpmc_ad15
    sudo echo 0x100 > gpmc_clk
    sudo echo 0x100 > gpmc_nadv_ale
    sudo echo 0x100 > gpmc_nbe0_cle
    sudo echo 0x000 > gpmc_ncs0
    sudo echo 0x000 > gpmc_ncs1
    sudo echo 0x100 > gpmc_nwp
    sudo echo 0x100 > gpmc_wait0
    sudo echo 0x100 > gpmc_nwe
    sudo echo 0x100 > gpmc_noe

    But unfortunately sometimes the GPMC_CLK and GPMC_CS signals stops working during individual bursts (see figure below)
    (the internal GPMC clock is 200 Mhz, using an prescaller of 4 , GPMC_CLK is 50Mhz)



    Zoom in:


    For me this failure looks like it has random occurrence because the bust number on which the failure occurred is always different.

    Using the scope, the GPMC_CLK looks like this if no failure happens (1.8Vpp)



    and like this if the failure happens


    Can anybody help me to solve this issue?
    For me it looks like the GPMC_CLK pin is somehow wrong configured, but I tried many different configuration without solving the issue.


    Best Regards