diff options
Diffstat (limited to 'drivers/dma/mvf_edma.c')
-rw-r--r-- | drivers/dma/mvf_edma.c | 141 |
1 files changed, 62 insertions, 79 deletions
diff --git a/drivers/dma/mvf_edma.c b/drivers/dma/mvf_edma.c index e04e45af74c1..cf934174b558 100644 --- a/drivers/dma/mvf_edma.c +++ b/drivers/dma/mvf_edma.c @@ -29,6 +29,8 @@ #include <asm/mvf_edma.h> #include <asm/mvf_edma_regs.h> +//#define SCATTER_TEST + #define MVF_MODE_MEMCPY 0x01 #define MVF_MODE_CYCLIC 0x02 #define MVF_MODE_SC 0x03 @@ -68,6 +70,20 @@ struct mvf_dma_engine { int err_irq[MVF_MAX_DMA_ENGINE]; }; +void mvf_dma_regdump( void __iomem *base, int channel) +{ + printk("REG ADDR=%x REG%x\n", (unsigned int)&MVF_EDMA_TCD_SADDR(base, channel), (unsigned int)MVF_EDMA_TCD_SADDR(base, channel)); + printk("REG ADDR=%x REG%x\n", (unsigned int)&MVF_EDMA_TCD_DADDR(base, channel), (unsigned int)MVF_EDMA_TCD_DADDR(base, channel)); + printk("REG ADDR=%x REG%x\n", (unsigned int)&MVF_EDMA_TCD_ATTR(base, channel), (unsigned int)MVF_EDMA_TCD_ATTR(base, channel)); + printk("REG ADDR=%x REG%x\n", (unsigned int)&MVF_EDMA_TCD_SOFF(base, channel), (unsigned int)MVF_EDMA_TCD_SOFF(base, channel)); + printk("REG ADDR=%x REG%x\n", (unsigned int)&MVF_EDMA_TCD_NBYTES(base, channel), (unsigned int)MVF_EDMA_TCD_NBYTES(base, channel)); + printk("REG ADDR=%x REG%x\n", (unsigned int)&MVF_EDMA_TCD_SLAST(base, channel), (unsigned int)MVF_EDMA_TCD_SLAST(base, channel)); + printk("REG ADDR=%x REG%x\n", (unsigned int)&MVF_EDMA_TCD_CITER(base, channel), (unsigned int)MVF_EDMA_TCD_CITER(base, channel)); + printk("REG ADDR=%x REG%x\n", (unsigned int)&MVF_EDMA_TCD_BITER(base, channel), (unsigned int)MVF_EDMA_TCD_BITER(base, channel)); + printk("REG ADDR=%x REG%x\n", (unsigned int)&MVF_EDMA_TCD_DOFF(base, channel), (unsigned int)MVF_EDMA_TCD_DOFF(base, channel)); + printk("REG ADDR=%x REG%x\n", (unsigned int)&MVF_EDMA_TCD_DLAST_SGA(base, channel),(unsigned int)MVF_EDMA_TCD_DLAST_SGA(base, channel)); + printk("REG ADDR=%x REG%x\n", (unsigned int)&MVF_EDMA_TCD_CSR(base, channel), (unsigned int)MVF_EDMA_TCD_CSR(base, channel)); +} static void mvf_dma_reset_chan(struct mvf_dma_chan *mvf_chan) { @@ -169,18 +185,18 @@ static int mvf_dma_sg_next(struct mvf_dma_chan *mvf_chan, struct scatterlist *sg if ( mvf_chan->word_size == DMA_SLAVE_BUSWIDTH_1_BYTE){ srcflag = MVF_EDMA_TCD_ATTR_SSIZE_8BIT; dstflag = MVF_EDMA_TCD_ATTR_DSIZE_8BIT; - srcdelta = 0; + srcdelta = 1; dstdelta = 1; }else if ( mvf_chan->word_size == DMA_SLAVE_BUSWIDTH_2_BYTES){ srcflag = MVF_EDMA_TCD_ATTR_SSIZE_16BIT; dstflag = MVF_EDMA_TCD_ATTR_DSIZE_16BIT; - srcdelta = 0; + srcdelta = 2; dstdelta = 2; }else{ srcflag = MVF_EDMA_TCD_ATTR_SSIZE_32BIT; dstflag = MVF_EDMA_TCD_ATTR_DSIZE_32BIT; - srcdelta = 0; + srcdelta = 4; dstdelta = 4; } @@ -217,6 +233,12 @@ static int mvf_dma_sg_next(struct mvf_dma_chan *mvf_chan, struct scatterlist *sg MVF_EDMA_TCD_BITER(base, channel) = MVF_EDMA_TCD_BITER_BITER(1); MVF_EDMA_TCD_DLAST_SGA(base, channel) = MVF_EDMA_TCD_DLAST_SGA_DLAST_SGA(0); +// mvf_dma_regdump(base, channel); + + MVF_EDMA_TCD_CSR(base,channel) |= MVF_EDMA_TCD_CSR_INT_MAJOR; + MVF_EDMA_TCD_CSR(base,channel) &= ~MVF_EDMA_TCD_CSR_D_REQ; + MVF_EDMA_SEEI(base) = MVF_EDMA_SEEI_SEEI(channel); + return now; } @@ -253,14 +275,19 @@ static int mvf_dma_handle(struct mvf_dma_chan *mvf_chan) if (mvf_chan->sg_list) { current_sg = mvf_chan->sg_list; mvf_chan->sg_list = sg_next(mvf_chan->sg_list); - // prepare next transfer if (mvf_chan->sg_list) { +#ifdef SCATTER_TEST + if ( mvf_chan->sg_list->length != 0){ +#endif // re-fill tx parameter mvf_dma_sg_next(mvf_chan, mvf_chan->sg_list); // start tx mvf_dma_enable_chan(mvf_chan); ret = 1; +#ifdef SCATTER_TEST + } +#endif } } } @@ -290,10 +317,10 @@ static irqreturn_t mvf_dma_int_handler(int irq, void *dev_id) printk("error irq\n"); return IRQ_HANDLED; } + //printk("DMA irq occured = CR:%x ES:%x SRC:%x \n", MVF_EDMA_CR(base), MVF_EDMA_ES(base),MVF_EDMA_INT(base)); // read int source and clear soon int_src = MVF_EDMA_INT(base); - MVF_EDMA_CINT(base) = MVF_EDMA_CINT_CAIR; // deliver int source and re-enable (if scatter gather is configured) for (i = 0; i < MVF_EACH_DMA_CHANNEL; i++) { @@ -310,6 +337,7 @@ static irqreturn_t mvf_dma_int_handler(int irq, void *dev_id) tasklet_schedule(&mvf_chan->tasklet); } } + MVF_EDMA_CINT(base) = i; } } @@ -331,10 +359,11 @@ static irqreturn_t mvf_dma_err_handler(int irq, void *dev_id) engine = i; } } + printk(KERN_INFO"DMA error irq occured = CR:%x ES:%x\n", (unsigned int)MVF_EDMA_CR(base), (unsigned int)MVF_EDMA_ES(base)); // fail safe if (!base){ - printk("error irq\n"); + printk(KERN_INFO"error irq\n"); return IRQ_HANDLED; } @@ -343,6 +372,7 @@ static irqreturn_t mvf_dma_err_handler(int irq, void *dev_id) if ( err & (1 << i)){ mvf_chan = mvf_find_chan(mvf_dma, engine, i); if (mvf_chan){ + mvf_chan->last_completed = mvf_chan->desc.cookie; mvf_chan->status = DMA_ERROR; tasklet_schedule(&mvf_chan->tasklet); } @@ -357,14 +387,13 @@ static irqreturn_t mvf_dma_err_handler(int irq, void *dev_id) static int mvf_dma_alloc_chan_resources(struct dma_chan *chan) { struct mvf_dma_chan *mvf_chan = to_mvf_dma_chan(chan); -// struct mvf_dma_engine *mvf_dma = mvf_chan->mvf_dma; mvf_dma_reset_chan(mvf_chan); dma_async_tx_descriptor_init(&mvf_chan->desc, chan); mvf_chan->desc.tx_submit = mvf_dma_tx_submit; - /* the descriptor is ready */ + // the descriptor is ready async_tx_ack(&mvf_chan->desc); return 0; @@ -373,11 +402,8 @@ static int mvf_dma_alloc_chan_resources(struct dma_chan *chan) static void mvf_dma_free_chan_resources(struct dma_chan *chan) { struct mvf_dma_chan *mvf_chan = to_mvf_dma_chan(chan); -// struct mvf_dma_engine *mvf_dma = mvf_chan->mvf_dma; mvf_dma_disable_chan(mvf_chan); - -// free_irq(mvf_chan->chan_irq, mvf_dma); } @@ -387,12 +413,9 @@ mvf_edma_set_tcd_params(struct mvf_dma_chan *mvf_chan, u32 source, u32 dest, u32 citer, u32 biter, u32 doff, u32 dlast_sga, int major_int, int disable_req) { -// struct mvf_dma_chan *mvf_chan = to_mvf_dma_chan(chan); -// struct mvf_dma_engine *mvf_dma = mvf_chan->mvf_dma; - int channel = mvf_chan->chan.chan_id % MVF_EACH_DMA_CHANNEL; void __iomem *base = mvf_chan->chan_mem_base; - + MVF_EDMA_TCD_SADDR(base, channel) = source; MVF_EDMA_TCD_DADDR(base, channel) = dest; MVF_EDMA_TCD_ATTR(base, channel) = attr; @@ -404,6 +427,21 @@ mvf_edma_set_tcd_params(struct mvf_dma_chan *mvf_chan, u32 source, u32 dest, MVF_EDMA_TCD_DOFF(base, channel) = MVF_EDMA_TCD_DOFF_DOFF(doff); MVF_EDMA_TCD_DLAST_SGA(base, channel) = MVF_EDMA_TCD_DLAST_SGA_DLAST_SGA(dlast_sga); +#if 0 + printk("Channel:%d Top reg:%x\n TX descriptor src : %x / dest : %x / attr : %x\n",channel, &MVF_EDMA_TCD_SADDR(base, channel), source,dest,attr); + MVF_EDMA_TCD_SADDR(base, channel) = source&0xfffffff0; + MVF_EDMA_TCD_DADDR(base, channel) = dest&0xffffff00; + MVF_EDMA_TCD_ATTR(base, channel) = (0 | MVF_EDMA_TCD_ATTR_SSIZE_32BIT | MVF_EDMA_TCD_ATTR_DSIZE_32BIT); + MVF_EDMA_TCD_SOFF(base, channel) = 0x4; + MVF_EDMA_TCD_NBYTES(base, channel) = 16; + MVF_EDMA_TCD_SLAST(base, channel) = 0; + MVF_EDMA_TCD_CITER(base, channel) = 1; + MVF_EDMA_TCD_BITER(base, channel) = 1; + MVF_EDMA_TCD_DOFF(base, channel) = 4; + MVF_EDMA_TCD_DLAST_SGA(base, channel) = 0; + MVF_EDMA_TCD_CSR(base, channel) = 0x0000; +#endif + /* interrupt at the end of major loop */ if (major_int) MVF_EDMA_TCD_CSR(base,channel) |= MVF_EDMA_TCD_CSR_INT_MAJOR; @@ -487,12 +525,8 @@ static struct dma_async_tx_descriptor *mvf_prep_slave_sg( } mvf_chan->sg_list = sgl; -#if 1 ret = mvf_dma_setup_sg(mvf_chan, sg_len, dma_length, dmamode); -#else - ret = imx_dma_setup_sg(imxdmac->imxdma_channel, sgl, sg_len, - dma_length, imxdmac->per_address, dmamode); -#endif + if (ret) return NULL; @@ -514,20 +548,12 @@ static struct dma_async_tx_descriptor *mvf_dma_prep_dma_cyclic( mvf_chan->status = DMA_IN_PROGRESS; mvf_chan->flags = MVF_MODE_CYCLIC; -#if 0 - ret = imx_dma_setup_progression_handler(imxdmac->imxdma_channel, - imxdma_progression); - if (ret) { - dev_err(imxdma->dev, "Failed to setup the DMA handler\n"); - return NULL; - } -#endif - if (mvf_chan->sg_list) kfree(mvf_chan->sg_list); mvf_chan->sg_list = kcalloc(periods + 1, sizeof(struct scatterlist), GFP_KERNEL); + if (!mvf_chan->sg_list) return NULL; @@ -542,10 +568,12 @@ static struct dma_async_tx_descriptor *mvf_dma_prep_dma_cyclic( } /* close the loop */ +#ifndef SCATTER_TEST mvf_chan->sg_list[periods].offset = 0; mvf_chan->sg_list[periods].length = 0; mvf_chan->sg_list[periods].page_link = ((unsigned long)mvf_chan->sg_list | 0x01) & ~0x02; +#endif if (direction == DMA_DEV_TO_MEM) dmamode = DMA_MODE_READ; @@ -573,33 +601,14 @@ static struct dma_async_tx_descriptor *mvf_dma_prep_memcpy mvf_chan->flags = MVF_MODE_MEMCPY; mvf_chan->status = DMA_IN_PROGRESS; - // chan_id -#if 1 mvf_edma_set_tcd_params( mvf_chan, src, dst, - (0 | MVF_EDMA_TCD_ATTR_SSIZE_32BIT | MVF_EDMA_TCD_ATTR_DSIZE_32BIT), - 0x04, - len, 0x0, 1, 1, - 0x04, 0x0, 0x1,0x0); - -#else - // channel control - if ( channel == 10){ - mvf_edma_set_tcd_params( - channel, - src, - dst, - (0 | MVF_EDMA_TCD_ATTR_SSIZE_32BIT | MVF_EDMA_TCD_ATTR_DSIZE_32BIT), - 0x04, + (0 | MVF_EDMA_TCD_ATTR_SSIZE_8BIT | MVF_EDMA_TCD_ATTR_DSIZE_8BIT), + 0x01, len, 0x0, 1, 1, - 0x04, 0x0, 0x1,0x0); - }else{ - } -#endif - - + 0x01, 0x0, 0x1,0x0); mvf_chan->desc_count = 0; return &mvf_chan->desc; @@ -689,22 +698,6 @@ static int __init mvf_dma_init(struct mvf_dma_engine *mvf_dma) } return 0; - - -#if 0 - int ret; - - ret = clk_prepare_enable(mvf_dma->clk); - if (ret) - return ret; - - ret = mxs_reset_block(mvf_dma->base); - if (ret) - goto err_out; - -err_out: - return ret; -#endif } static int __init mvf_dma_probe(struct platform_device *pdev) @@ -727,7 +720,7 @@ static int __init mvf_dma_probe(struct platform_device *pdev) } mvf_dma->base[i] = ioremap(iores->start, resource_size(iores)); - if (!mvf_dma->base) { + if (!mvf_dma->base[i]) { ret = -ENOMEM; goto err_ioremap; } @@ -744,14 +737,6 @@ static int __init mvf_dma_probe(struct platform_device *pdev) mvf_dma->err_irq[i]=errirq_res->start; } -#if 0 - mvf_dma->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(mvf_dma->clk)) { - ret = PTR_ERR(mvf_dma->clk); - goto err_clk; - } -#endif - dma_cap_set(DMA_MEMCPY, mvf_dma->dma_device.cap_mask); dma_cap_set(DMA_SLAVE, mvf_dma->dma_device.cap_mask); dma_cap_set(DMA_CYCLIC, mvf_dma->dma_device.cap_mask); @@ -761,7 +746,6 @@ static int __init mvf_dma_probe(struct platform_device *pdev) /* Initialize channel parameters */ for (i = 0; i < MVF_EDMA_CHANNELS; i++) { struct mvf_dma_chan *mvf_chan = &mvf_dma->mvf_chans[i]; - index = i / MVF_EACH_DMA_CHANNEL; mvf_chan->mvf_dma = mvf_dma; @@ -771,7 +755,6 @@ static int __init mvf_dma_probe(struct platform_device *pdev) tasklet_init(&mvf_chan->tasklet, mvf_dma_tasklet, (unsigned long) mvf_chan); - /* Add the channel to mvf_chan list */ list_add_tail(&mvf_chan->chan.device_node, &mvf_dma->dma_device.channels); @@ -802,7 +785,7 @@ static int __init mvf_dma_probe(struct platform_device *pdev) goto err_init; } - dev_info(mvf_dma->dma_device.dev, "initialized\n"); + printk(KERN_INFO "eDMA driver Installed.\n"); return 0; |