diff options
Diffstat (limited to 'drivers/dma/mmp_tdma.c')
-rw-r--r-- | drivers/dma/mmp_tdma.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c index e7d1e12bf464..a262e0eb4cc9 100644 --- a/drivers/dma/mmp_tdma.c +++ b/drivers/dma/mmp_tdma.c @@ -235,7 +235,7 @@ static int mmp_tdma_config_chan(struct dma_chan *chan) tdcr |= TDCR_BURSTSZ_128B; break; default: - dev_err(tdmac->dev, "mmp_tdma: unknown burst size.\n"); + dev_err(tdmac->dev, "unknown burst size.\n"); return -EINVAL; } @@ -250,7 +250,7 @@ static int mmp_tdma_config_chan(struct dma_chan *chan) tdcr |= TDCR_SSZ_32_BITS; break; default: - dev_err(tdmac->dev, "mmp_tdma: unknown bus size.\n"); + dev_err(tdmac->dev, "unknown bus size.\n"); return -EINVAL; } } else if (tdmac->type == PXA910_SQU) { @@ -276,7 +276,7 @@ static int mmp_tdma_config_chan(struct dma_chan *chan) tdcr |= TDCR_BURSTSZ_SQU_32B; break; default: - dev_err(tdmac->dev, "mmp_tdma: unknown burst size.\n"); + dev_err(tdmac->dev, "unknown burst size.\n"); return -EINVAL; } } @@ -346,9 +346,9 @@ static irqreturn_t mmp_tdma_int_handler(int irq, void *dev_id) return IRQ_NONE; } -static void dma_do_tasklet(unsigned long data) +static void dma_do_tasklet(struct tasklet_struct *t) { - struct mmp_tdma_chan *tdmac = (struct mmp_tdma_chan *)data; + struct mmp_tdma_chan *tdmac = from_tasklet(tdmac, t, tasklet); dmaengine_desc_get_callback_invoke(&tdmac->desc, NULL); } @@ -363,6 +363,8 @@ static void mmp_tdma_free_descriptor(struct mmp_tdma_chan *tdmac) gen_pool_free(gpool, (unsigned long)tdmac->desc_arr, size); tdmac->desc_arr = NULL; + if (tdmac->status == DMA_ERROR) + tdmac->status = DMA_COMPLETE; return; } @@ -427,8 +429,15 @@ static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic( int num_periods = buf_len / period_len; int i = 0, buf = 0; - if (tdmac->status != DMA_COMPLETE) + if (!is_slave_direction(direction)) { + dev_err(tdmac->dev, "unsupported transfer direction\n"); return NULL; + } + + if (tdmac->status != DMA_COMPLETE) { + dev_err(tdmac->dev, "controller busy"); + return NULL; + } if (period_len > TDMA_MAX_XFER_BYTES) { dev_err(tdmac->dev, @@ -443,7 +452,8 @@ static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic( if (!desc) goto err_out; - mmp_tdma_config_write(chan, direction, &tdmac->slave_config); + if (mmp_tdma_config_write(chan, direction, &tdmac->slave_config)) + goto err_out; while (buf < buf_len) { desc = &tdmac->desc_arr[i]; @@ -544,6 +554,9 @@ static void mmp_tdma_issue_pending(struct dma_chan *chan) static int mmp_tdma_remove(struct platform_device *pdev) { + if (pdev->dev.of_node) + of_dma_controller_free(pdev->dev.of_node); + return 0; } @@ -573,7 +586,7 @@ static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev, tdmac->pool = pool; tdmac->status = DMA_COMPLETE; tdev->tdmac[tdmac->idx] = tdmac; - tasklet_init(&tdmac->tasklet, dma_do_tasklet, (unsigned long)tdmac); + tasklet_setup(&tdmac->tasklet, dma_do_tasklet); /* add the channel to tdma_chan list */ list_add_tail(&tdmac->chan.device_node, @@ -669,7 +682,7 @@ static int mmp_tdma_probe(struct platform_device *pdev) if (irq_num != chan_num) { irq = platform_get_irq(pdev, 0); ret = devm_request_irq(&pdev->dev, irq, - mmp_tdma_int_handler, 0, "tdma", tdev); + mmp_tdma_int_handler, IRQF_SHARED, "tdma", tdev); if (ret) return ret; } @@ -698,6 +711,17 @@ static int mmp_tdma_probe(struct platform_device *pdev) tdev->device.device_terminate_all = mmp_tdma_terminate_all; tdev->device.copy_align = DMAENGINE_ALIGN_8_BYTES; + tdev->device.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + if (type == MMP_AUD_TDMA) { + tdev->device.max_burst = SZ_128; + tdev->device.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + tdev->device.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + } else if (type == PXA910_SQU) { + tdev->device.max_burst = SZ_32; + } + tdev->device.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + tdev->device.descriptor_reuse = true; + dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); platform_set_drvdata(pdev, tdev); |