Hi,
I wrote a SDIO driver over the MMC 2 on OMAP l138 platform, which is not part of kernel (linux-03.20.00.12.) and it is working fine with non-DMA mode. I am facing issue for during the data transfer over EDMA. I am working on linux-03.20.00.12 os.
Please find the code, which i am using to transfer and configure the DMA.
I set the value as below:
acnt = 4 because SDIO controller transmit register is 4 byte
bcnt = 16 because FIFO controller is 64 byte (acnt*bcnt=64byte)
ccnt=uLen/(acnt*bcnt) uLen- totlan length of data to be transfer.
=================================================================================
static inline int sdioDrv_ConfigDma(int ch, struct edmacc_param *template)
{
u32 sync_dev;
const u16 acnt = 4;
/*
* Maximum size of FIFO is 64 Byte and TX and RX register can
* transmit 4 Byte at a time. Transmit/Receive 64 Byte with
* 16 iterations.
*/
const u16 bcnt = 16;
const u16 ccnt = 0;
u32 src_port = 0;
u32 dst_port = 0;
int src_bidx, dst_bidx;
int src_cidx, dst_cidx;
int iStatus = 0;
switch(ch)
{
case SDIO_TX_DMA:
/* DMA TX*/
sync_dev = g_drv.edma_tx_channel;
src_bidx = acnt;
src_cidx = acnt * bcnt;
dst_port = (u32)g_drv.regBase + OMAP_HSMMC_MMCDXR;
dst_bidx = 0;
dst_cidx = 0;
break;
case SDIO_RX_DMA:
/* DMA RX*/
sync_dev = g_drv.edma_rx_channel;
src_bidx = 0;
src_cidx = 0;
src_port = (u32)g_drv.regBase + OMAP_HSMMC_MMCDRR;
dst_bidx = acnt;
dst_cidx = acnt * bcnt;
break;
default:
printk("No DMA Channel Configuration!!!\n");
return -1;
}
edma_set_src(sync_dev, src_port, INCR, 0);
edma_set_dest(sync_dev, dst_port, INCR, 0);
edma_set_src_index(sync_dev, src_bidx, src_cidx);
edma_set_dest_index(sync_dev, dst_bidx, dst_cidx);
edma_set_transfer_params(sync_dev, acnt, bcnt, ccnt, 8, ABSYNC);
edma_read_slot(sync_dev, template);
template->opt |= EDMA_CHAN_SLOT(sync_dev) << 12;
return 0;
}
static inline int sdioDrv_IntializeMMCDMA(void)
{
/*
* Intialize DMA
*/
int rSatus;
g_drv.edma_tx_channel = OMAP_DMA_TX_CHANNEL;
g_drv.edma_rx_channel = OMAP_DMA_RX_CHANNEL;
/* Acquire master EDMA WRITE channel */
rSatus = edma_alloc_channel(g_drv.edma_tx_channel, sdiodrv_dma_cb, &g_drv, EVENTQ_DEFAULT);
if (rSatus < 0)
{
printk ("%s: EDMA TX channel allocation Failed\n", __FUNCTION__);
return rSatus;
}
/* TODO: Setup the DMA for TX*/
rSatus = sdioDrv_ConfigDma(SDIO_TX_DMA, &g_drv.tx_template);
if (rSatus != 0)
{
printk ("%s: EDMA TX channel Configuration Failed\n", __FUNCTION__);
return rSatus;
}
/* Acquire master EDMA READ channel */
rSatus = edma_alloc_channel(g_drv.edma_rx_channel, sdiodrv_dma_cb, &g_drv, EVENTQ_DEFAULT);
if (rSatus < 0)
{
printk ("$s: EDMA RX channel allocation Failed\n");
return rSatus;
}
/* TODO: Setup the DMA for RX*/
rSatus = sdioDrv_ConfigDma(SDIO_TX_DMA, &g_drv.rx_template);
if (rSatus != 0)
{
printk ("%s: EDMA RX channel Configuration Failed\n", __FUNCTION__);
return rSatus;
}
/* TODO: Allocate Slot for TX/RX*/
g_drv.slot = edma_alloc_slot(EDMA_CTLR(g_drv.edma_tx_channel), EDMA_SLOT_ANY);
return 0;
}
To transfer the data:
/* Set the FIFO for data write */
writel((MMCFIFOCTL_FIFOLEV | MMCFIFOCTL_FIFODIR_WR | MMCFIFOCTL_FIFORST),
g_drv.regBase + OMAP_HSMMC_MMCFIFOCTL);
writel((MMCFIFOCTL_FIFOLEV | MMCFIFOCTL_FIFODIR_WR),
g_drv.regBase + OMAP_HSMMC_MMCFIFOCTL);
template->src = g_drv.dma_write_addr; //Physical address of the buffer
template->ccnt = ccnt;
template->opt |= TCINTEN | EDMA_TCC(g_drv.edma_tx_channel);
template->link_bcntrld = EDMA_CHAN_SLOT(g_drv.slot) << 5;
edma_write_slot(g_drv.slot, template);
if(edma_start(g_drv.edma_tx_channel) == -EINVAL)
{
printk("Data Transfer failed\n");
}
=================================================================
I have done above code for data transfer over however it is not working and populating any error. Please let me know whether i am missing anything to configure the DMA.
Thanks in advance.
Best Regards
Sanjay