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.

OMAP L138 MMC 2 issue to tansfer data over EDMA

Other Parts Discussed in Thread: OMAPL138

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