171 lines
5.3 KiB
Diff
171 lines
5.3 KiB
Diff
From 9050c0619cdf5399d19e3683d6fb1db355dda110 Mon Sep 17 00:00:00 2001
|
|
From: Robin Gong <yibin.gong@nxp.com>
|
|
Date: Wed, 17 Apr 2019 17:05:42 +0800
|
|
Subject: [PATCH] MLK-22284-1 dmaengine: fsl-edma-v3: add power domains for
|
|
each channel
|
|
|
|
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)
|
|
---
|
|
.../devicetree/bindings/dma/fsl-edma-v3.txt | 11 +++-
|
|
drivers/dma/fsl-edma-v3.c | 58 +++++++++++++++++++++-
|
|
2 files changed, 67 insertions(+), 2 deletions(-)
|
|
|
|
--- a/Documentation/devicetree/bindings/dma/fsl-edma-v3.txt
|
|
+++ b/Documentation/devicetree/bindings/dma/fsl-edma-v3.txt
|
|
@@ -30,6 +30,8 @@ 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
|
|
+- power-domains: Power domains for edma channel used.
|
|
+- power-domain-names: Power domains name for edma channel used.
|
|
|
|
Examples:
|
|
edma0: dma-controller@40018000 {
|
|
@@ -46,6 +48,12 @@ 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";
|
|
+ power-domains = <&pd IMX_SC_R_DMA_0_CH12>,
|
|
+ <&pd IMX_SC_R_DMA_0_CH13>,
|
|
+ <&pd IMX_SC_R_DMA_0_CH14>,
|
|
+ <&pd IMX_SC_R_DMA_0_CH15>;
|
|
+ power-domain-names = "edma0-chan12", "edma0-chan13",
|
|
+ "edma0-chan14", "edma0-chan15";
|
|
status = "okay";
|
|
};
|
|
|
|
@@ -65,7 +73,8 @@ lpuart1: serial@5a070000 {
|
|
clock-names = "ipg";
|
|
assigned-clock-names = <&clk IMX8QM_UART1_CLK>;
|
|
assigned-clock-rates = <80000000>;
|
|
- power-domains = <&pd_dma_lpuart1>;
|
|
+ power-domains = <&pd IMX_SC_R_UART_1>,
|
|
+ power-domain-names = "uart";
|
|
dma-names = "tx","rx";
|
|
dmas = <&edma0 15 0 0>,
|
|
<&edma0 14 0 1>;
|
|
--- a/drivers/dma/fsl-edma-v3.c
|
|
+++ b/drivers/dma/fsl-edma-v3.c
|
|
@@ -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 "virt-dma.h"
|
|
|
|
@@ -164,6 +166,7 @@ struct fsl_edma3_chan {
|
|
u32 chn_real_count;
|
|
char txirq_name[32];
|
|
struct platform_device *pdev;
|
|
+ struct device *dev;
|
|
};
|
|
|
|
struct fsl_edma3_desc {
|
|
@@ -798,8 +801,10 @@ static int fsl_edma3_alloc_chan_resource
|
|
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->dev);
|
|
/* 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);
|
|
@@ -830,6 +835,7 @@ static void fsl_edma3_free_chan_resource
|
|
dma_pool_destroy(fsl_chan->tcd_pool);
|
|
fsl_chan->tcd_pool = NULL;
|
|
fsl_chan->used = false;
|
|
+ pm_runtime_put_sync(fsl_chan->dev);
|
|
}
|
|
|
|
static void fsl_edma3_synchronize(struct dma_chan *chan)
|
|
@@ -839,6 +845,37 @@ static void fsl_edma3_synchronize(struct
|
|
vchan_synchronize(&fsl_chan->vchan);
|
|
}
|
|
|
|
+static struct device *fsl_edma3_attach_pd(struct device *dev,
|
|
+ struct device_node *np, int index)
|
|
+{
|
|
+ const char *domn = "edma0-chan01";
|
|
+ struct device *pd_chan;
|
|
+ struct device_link *link;
|
|
+ int ret;
|
|
+
|
|
+ ret = of_property_read_string_index(np, "power-domain-names", index,
|
|
+ &domn);
|
|
+ if (ret) {
|
|
+ dev_err(dev, "parse power-domain-names error.(%d)\n", ret);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ pd_chan = dev_pm_domain_attach_by_name(dev, domn);
|
|
+ if (!pd_chan)
|
|
+ return NULL;
|
|
+
|
|
+ link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS |
|
|
+ DL_FLAG_PM_RUNTIME |
|
|
+ DL_FLAG_RPM_ACTIVE);
|
|
+ if (IS_ERR(link)) {
|
|
+ dev_err(dev, "Failed to add device_link to %s: %ld\n", domn,
|
|
+ PTR_ERR(link));
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return pd_chan;
|
|
+}
|
|
+
|
|
static int fsl_edma3_probe(struct platform_device *pdev)
|
|
{
|
|
struct device_node *np = pdev->dev.of_node;
|
|
@@ -962,6 +999,22 @@ static int fsl_edma3_probe(struct platfo
|
|
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;
|
|
+
|
|
+ dev = fsl_edma3_attach_pd(&pdev->dev, np, i);
|
|
+ if (!dev) {
|
|
+ dev_err(dev, "edma channel attach failed.\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ fsl_chan->dev = 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) {
|
|
@@ -970,6 +1023,9 @@ static int fsl_edma3_probe(struct platfo
|
|
return ret;
|
|
}
|
|
|
|
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
|
|
+ pm_runtime_enable(&pdev->dev);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -1068,7 +1124,7 @@ static int __init fsl_edma3_init(void)
|
|
{
|
|
return platform_driver_register(&fsl_edma3_driver);
|
|
}
|
|
-subsys_initcall(fsl_edma3_init);
|
|
+fs_initcall(fsl_edma3_init);
|
|
|
|
static void __exit fsl_edma3_exit(void)
|
|
{
|