MLK-22284-1 dmaengine: fsl-edma-v3: add power domains for each channel
authorRobin Gong <yibin.gong@nxp.com>
Wed, 17 Apr 2019 09:05:42 +0000 (17:05 +0800)
committerRobin Gong <yibin.gong@nxp.com>
Tue, 23 Jul 2019 16:50:48 +0000 (00:50 +0800)
Add power domains for each dma channel so that edma channel could
know the power state of every dma channel anytime and clear easily
unexpected interrupt which triggered before the last partition reset.

Signed-off-by: Robin Gong <yibin.gong@nxp.com>
Reviewed-by: S.j. Wang <shengjiu.wang@nxp.com>
(cherry picked from commit 0b6da46b7bdb2284e24757d48466268b9feb5b7c)

Documentation/devicetree/bindings/dma/fsl-edma-v3.txt
drivers/dma/fsl-edma-v3.c

index a8d0542..2fb7d1b 100644 (file)
@@ -30,6 +30,7 @@ Required properties:
                0: not dual fifo case, 1: dualfifo case.
        See the SoC's reference manual for all the supported request sources.
 - dma-channels : Number of channels supported by the controller
+- pdomains: Power domains for edma channel used.
 
 Examples:
 edma0: dma-controller@40018000 {
@@ -46,6 +47,8 @@ edma0: dma-controller@40018000 {
                     <GIC_SPI 437 IRQ_TYPE_LEVEL_HIGH>;
        interrupt-names = "edma0-chan12-rx", "edma0-chan13-tx",
                          "edma0-chan14-rx", "edma0-chan15-tx";
+       pdomains =  <&pd_dma0_chan12>, <&pd_dma0_chan13>,
+                   <&pd_dma0_chan14>, <&pd_dma0_chan15>,
        status = "okay";
 };
 
index 0e7f5ee..1d63c68 100644 (file)
@@ -27,6 +27,8 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_dma.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_domain.h>
 
 #include <soc/imx/revision.h>
 #include <soc/imx8/soc.h>
@@ -799,8 +801,10 @@ static int fsl_edma3_alloc_chan_resources(struct dma_chan *chan)
        fsl_chan->tcd_pool = dma_pool_create("tcd_pool", chan->device->dev,
                                sizeof(struct fsl_edma3_hw_tcd),
                                32, 0);
+       pm_runtime_get_sync(&fsl_chan->vchan.chan.dev->device);
        /* clear meaningless pending irq anyway */
        writel(1, fsl_chan->membase + EDMA_CH_INT);
+
        ret = devm_request_irq(&pdev->dev, fsl_chan->txirq,
                        fsl_edma3_tx_handler, fsl_chan->edma3->irqflag,
                        fsl_chan->txirq_name, fsl_chan);
@@ -831,6 +835,7 @@ static void fsl_edma3_free_chan_resources(struct dma_chan *chan)
        dma_pool_destroy(fsl_chan->tcd_pool);
        fsl_chan->tcd_pool = NULL;
        fsl_chan->used = false;
+       pm_runtime_put_sync(&fsl_chan->vchan.chan.dev->device);
 }
 
 static void fsl_edma3_synchronize(struct dma_chan *chan)
@@ -975,6 +980,28 @@ static int fsl_edma3_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "Can't register Freescale eDMA engine.\n");
                return ret;
        }
+       /* Attach power domains from dts for each dma chanel device */
+       for (i = 0; i < fsl_edma3->n_chans; i++) {
+               struct fsl_edma3_chan *fsl_chan = &fsl_edma3->chans[i];
+               struct device *dev = &fsl_chan->vchan.chan.dev->device;
+               struct of_phandle_args args;
+
+               ret = of_parse_phandle_with_args(np, "pdomains", NULL, i,
+                                               &args);
+               if (ret < 0) {
+                       dev_err(dev, "parse phandle failed(%d)\n", ret);
+                       return ret;
+               }
+
+               of_genpd_add_device(&args, dev);
+               pm_runtime_dont_use_autosuspend(dev);
+               pm_runtime_enable(dev);
+
+               pm_runtime_get_sync(dev);
+               /* clear meaningless pending irq anyway */
+               writel(1, fsl_chan->membase + EDMA_CH_INT);
+               pm_runtime_put_sync(dev);
+       }
 
        ret = of_dma_controller_register(np, fsl_edma3_xlate, fsl_edma3);
        if (ret) {