]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/dma/fsl-edma.c
drm/i915: Fixup preempt-to-busy vs resubmission of a virtual request
[linux.git] / drivers / dma / fsl-edma.c
index fcbad6ae954a820774f994fbaf1c99d7130df005..b626c06ac2e0bb3d502c5e9625caa9b26e11f9c1 100644 (file)
 
 #include "fsl-edma-common.h"
 
+static void fsl_edma_synchronize(struct dma_chan *chan)
+{
+       struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
+
+       vchan_synchronize(&fsl_chan->vchan);
+}
+
 static irqreturn_t fsl_edma_tx_handler(int irq, void *dev_id)
 {
        struct fsl_edma_engine *fsl_edma = dev_id;
@@ -125,16 +132,12 @@ fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma
        int ret;
 
        fsl_edma->txirq = platform_get_irq_byname(pdev, "edma-tx");
-       if (fsl_edma->txirq < 0) {
-               dev_err(&pdev->dev, "Can't get edma-tx irq.\n");
+       if (fsl_edma->txirq < 0)
                return fsl_edma->txirq;
-       }
 
        fsl_edma->errirq = platform_get_irq_byname(pdev, "edma-err");
-       if (fsl_edma->errirq < 0) {
-               dev_err(&pdev->dev, "Can't get edma-err irq.\n");
+       if (fsl_edma->errirq < 0)
                return fsl_edma->errirq;
-       }
 
        if (fsl_edma->txirq == fsl_edma->errirq) {
                ret = devm_request_irq(&pdev->dev, fsl_edma->txirq,
@@ -162,6 +165,49 @@ fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma
        return 0;
 }
 
+static int
+fsl_edma2_irq_init(struct platform_device *pdev,
+                  struct fsl_edma_engine *fsl_edma)
+{
+       int i, ret, irq;
+       int count;
+
+       count = platform_irq_count(pdev);
+       dev_dbg(&pdev->dev, "%s Found %d interrupts\r\n", __func__, count);
+       if (count <= 2) {
+               dev_err(&pdev->dev, "Interrupts in DTS not correct.\n");
+               return -EINVAL;
+       }
+       /*
+        * 16 channel independent interrupts + 1 error interrupt on i.mx7ulp.
+        * 2 channel share one interrupt, for example, ch0/ch16, ch1/ch17...
+        * For now, just simply request irq without IRQF_SHARED flag, since 16
+        * channels are enough on i.mx7ulp whose M4 domain own some peripherals.
+        */
+       for (i = 0; i < count; i++) {
+               irq = platform_get_irq(pdev, i);
+               if (irq < 0)
+                       return -ENXIO;
+
+               sprintf(fsl_edma->chans[i].chan_name, "eDMA2-CH%02d", i);
+
+               /* The last IRQ is for eDMA err */
+               if (i == count - 1)
+                       ret = devm_request_irq(&pdev->dev, irq,
+                                               fsl_edma_err_handler,
+                                               0, "eDMA2-ERR", fsl_edma);
+               else
+                       ret = devm_request_irq(&pdev->dev, irq,
+                                               fsl_edma_tx_handler, 0,
+                                               fsl_edma->chans[i].chan_name,
+                                               fsl_edma);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static void fsl_edma_irq_exit(
                struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
 {
@@ -187,8 +233,16 @@ static struct fsl_edma_drvdata vf610_data = {
        .setup_irq = fsl_edma_irq_init,
 };
 
+static struct fsl_edma_drvdata imx7ulp_data = {
+       .version = v3,
+       .dmamuxs = 1,
+       .has_dmaclk = true,
+       .setup_irq = fsl_edma2_irq_init,
+};
+
 static const struct of_device_id fsl_edma_dt_ids[] = {
        { .compatible = "fsl,vf610-edma", .data = &vf610_data},
+       { .compatible = "fsl,imx7ulp-edma", .data = &imx7ulp_data},
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
@@ -236,6 +290,20 @@ static int fsl_edma_probe(struct platform_device *pdev)
        fsl_edma_setup_regs(fsl_edma);
        regs = &fsl_edma->regs;
 
+       if (drvdata->has_dmaclk) {
+               fsl_edma->dmaclk = devm_clk_get(&pdev->dev, "dma");
+               if (IS_ERR(fsl_edma->dmaclk)) {
+                       dev_err(&pdev->dev, "Missing DMA block clock.\n");
+                       return PTR_ERR(fsl_edma->dmaclk);
+               }
+
+               ret = clk_prepare_enable(fsl_edma->dmaclk);
+               if (ret) {
+                       dev_err(&pdev->dev, "DMA clk block failed.\n");
+                       return ret;
+               }
+       }
+
        for (i = 0; i < fsl_edma->drvdata->dmamuxs; i++) {
                char clkname[32];
 
@@ -302,6 +370,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
        fsl_edma->dma_dev.device_pause = fsl_edma_pause;
        fsl_edma->dma_dev.device_resume = fsl_edma_resume;
        fsl_edma->dma_dev.device_terminate_all = fsl_edma_terminate_all;
+       fsl_edma->dma_dev.device_synchronize = fsl_edma_synchronize;
        fsl_edma->dma_dev.device_issue_pending = fsl_edma_issue_pending;
 
        fsl_edma->dma_dev.src_addr_widths = FSL_EDMA_BUSWIDTHS;