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