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.

Netra: DMA for GPMC

Hi all,

We are using GPMC with HPI based DSP. In CPU memory transfer mode, the mechanism works fine.

When we use DMA with GPMC (Driver from arch/arm/plat-omap/sdma2edma.c) and read request comes, the console hangs after a moment and probably DMA xfer doesn't get completed. I have taken reference from NAND driver (drivers/mtd/nand/omap2.c).

Can someone please review whether below implementation is correct or anything is missing ?

Please note that, I need to read from a source, which is a register directly mapped to GPMC bus, bus width = 16 bits. Thus source is a fixed address location.

Destination is DDR memory of Netra, which is incremental.

Code

host_dma_init() : omap_request_dma() call is successful.

{    int err = 0;
        info = kzalloc(sizeof(struct omap_qhal_info), GFP_KERNEL);
        if (!info)
              return -ENOMEM;

    err = omap_request_dma(OMAP24XX_DMA_GPMC, "QHALDMA", omap_qhal_dma_cb, &info->comp, &info->dma_ch);
    if(err < 0)
    {
        info->dma_ch = -1;
        printk("Fail: omap_request_dma()\n");
        return -ENOMEM;

    }    else

      printk("SUCCESS: omap_request_dma()\n");

}

host_dma_read()

{

    dma_src = addr; //Physical add in DDR

    dma_dest = dma_map_single(NULL, src_buffer, nBytes, DMA_FROM_DEVICE);
        if (dma_mapping_error(NULL, dma_dest)) {
                printk("Couldn't DMA map a %d byte buffer\n", nBytes);
        return -1;

    omap_set_dma_src_params(info->dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, dma_src, 0, 0);
    omap_set_dma_dest_params(info->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, dma_dest, 0, 0);
    omap_set_dma_transfer_params(info->dma_ch, OMAP_DMA_DATA_TYPE_S16,
            0x10, nBytes, OMAP_DMA_SYNC_FRAME,
            OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);


    ret = gpmc_prefetch_enable(GPMC_CS,
            PREFETCH_FIFOTHRESHOLD_MAX, 0x1, nBytes, 0 /*for read*/);

    if (ret)
        printk("\nPREFETCH ENGINE IS BUSY... >>>\n");

    init_completion(&info->comp);

   omap_start_dma(info->dma_ch); }

   wait_for_completion(&info->comp); //Code always wait here and then console hangs, no message on log..... After this point, I am not able to access telnet too. ping works fine.

    tim = 0;
    limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_QHAL_TIMEOUT_MS));

     while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
        cpu_relax();

    gpmc_prefetch_reset(GPMC_CS);
   dma_unmap_single(NULL, dma_dest, nBytes, DMA_FROM_DEVICE);
}

Any idea what goes wrong ? Any help on this will be highly appreciated.

Thanks in advance,
Sweta