diff mbox

[V4,01/14] DMA: PL330: Add support runtime PM for PL330 DMAC

Message ID 1311557312-26107-2-git-send-email-boojin.kim@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

boojin.kim July 25, 2011, 1:28 a.m. UTC
Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
---
 drivers/dma/pl330.c |   75 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 73 insertions(+), 2 deletions(-)

Comments

Chanwoo Choi July 26, 2011, 6:03 a.m. UTC | #1
Boojin Kim wrote:
> Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> ---
>  drivers/dma/pl330.c |   75 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 73 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 6abe1ec..b7ecf47 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -17,6 +17,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/amba/bus.h>
>  #include <linux/amba/pl330.h>
> +#include <linux/pm_runtime.h>
>  
>  #define NR_DEFAULT_DESC	16
>  
> @@ -83,6 +84,8 @@ struct dma_pl330_dmac {
>  
>  	/* Peripheral channels connected to this DMAC */
>  	struct dma_pl330_chan peripherals[0]; /* keep at end */
> +
> +	struct clk *clk;
>  };
>  
>  struct dma_pl330_desc {
> @@ -696,6 +699,30 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
>  		goto probe_err1;
>  	}
>  
> +	pdmac->clk = clk_get(&adev->dev, "dma");
> +	if (IS_ERR(pdmac->clk)) {
> +		dev_err(&adev->dev, "Cannot get operation clock.\n");
> +		ret = -EINVAL;
> +		goto probe_err1;
> +	}
> +
> +	amba_set_drvdata(adev, pdmac);
> +
> +#ifdef CONFIG_PM_RUNTIME
> +	/* to use the runtime PM helper functions */
> +	pm_runtime_enable(&adev->dev);
> +
> +	/* enable the power domain */
> +	if (pm_runtime_get_sync(&adev->dev)) {
> +		dev_err(&adev->dev, "failed to get runtime pm\n");
> +		ret = -ENODEV;
> +		goto probe_err1;
> +	}
> +#else
> +	/* enable dma clk */
> +	clk_enable(pdmac->clk);
> +#endif
> +
>  	irq = adev->irq[0];
>  	ret = request_irq(irq, pl330_irq_handler, 0,
>  			dev_name(&adev->dev), pi);
> @@ -763,8 +790,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
>  		goto probe_err4;
>  	}
>  
> -	amba_set_drvdata(adev, pdmac);
> -
>  	dev_info(&adev->dev,
>  		"Loaded driver for PL330 DMAC-%d\n", adev->periphid);
>  	dev_info(&adev->dev,
> @@ -825,6 +850,13 @@ static int __devexit pl330_remove(struct amba_device *adev)
>  	res = &adev->res;
>  	release_mem_region(res->start, resource_size(res));
>  
> +#ifdef CONFIG_PM_RUNTIME
> +	pm_runtime_put(&adev->dev);
> +	pm_runtime_disable(&adev->dev);
> +#else
> +	clk_disable(pdmac->clk);
> +#endif
> +
>  	kfree(pdmac);
>  
>  	return 0;
> @@ -838,10 +870,49 @@ static struct amba_id pl330_ids[] = {
>  	{ 0, 0 },
>  };
>  
> +#ifdef CONFIG_PM_RUNTIME
> +static int pl330_runtime_suspend(struct device *dev)
> +{
> +	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
> +
> +	if (!pdmac) {
> +		dev_err(dev, "failed to get dmac\n");
> +		return -ENODEV;
> +	}
> +
> +	clk_disable(pdmac->clk);
> +
> +	return 0;
> +}
> +
> +static int pl330_runtime_resume(struct device *dev)
> +{
> +	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
> +
> +	if (!pdmac) {
> +		dev_err(dev, "failed to get dmac\n");
> +		return -ENODEV;
> +	}
> +
> +	clk_enable(pdmac->clk);
> +
> +	return 0;
> +}
> +#else
> +#define pl330_runtime_suspend	NULL
> +#define pl330_runtime_resume	NULL
> +#endif /* CONFIG_PM_RUNTIME */
> +
> +static const struct dev_pm_ops pl330_pm_ops = {
> +	.runtime_suspend = pl330_runtime_suspend,
> +	.runtime_resume = pl330_runtime_resume,
> +};
> +
>  static struct amba_driver pl330_driver = {
>  	.drv = {
>  		.owner = THIS_MODULE,
>  		.name = "dma-pl330",
> +		.pm = &pl330_pm_ops,
>  	},
>  	.id_table = pl330_ids,
>  	.probe = pl330_probe,

I have a question for runtime PM of PL330 DMAC

This patch support runtime PM for PL330 DMAC, but the clock of "dma" is always on.
If the clock of "dma" is always on, additional power(10mA) is consumed. I tested it.

I think that the PL330 DMAC only turn on the clock of "dma" when using DMA.


Thanks,
Chanwoo Choi
diff mbox

Patch

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 6abe1ec..b7ecf47 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -17,6 +17,7 @@ 
 #include <linux/interrupt.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl330.h>
+#include <linux/pm_runtime.h>
 
 #define NR_DEFAULT_DESC	16
 
@@ -83,6 +84,8 @@  struct dma_pl330_dmac {
 
 	/* Peripheral channels connected to this DMAC */
 	struct dma_pl330_chan peripherals[0]; /* keep at end */
+
+	struct clk *clk;
 };
 
 struct dma_pl330_desc {
@@ -696,6 +699,30 @@  pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		goto probe_err1;
 	}
 
+	pdmac->clk = clk_get(&adev->dev, "dma");
+	if (IS_ERR(pdmac->clk)) {
+		dev_err(&adev->dev, "Cannot get operation clock.\n");
+		ret = -EINVAL;
+		goto probe_err1;
+	}
+
+	amba_set_drvdata(adev, pdmac);
+
+#ifdef CONFIG_PM_RUNTIME
+	/* to use the runtime PM helper functions */
+	pm_runtime_enable(&adev->dev);
+
+	/* enable the power domain */
+	if (pm_runtime_get_sync(&adev->dev)) {
+		dev_err(&adev->dev, "failed to get runtime pm\n");
+		ret = -ENODEV;
+		goto probe_err1;
+	}
+#else
+	/* enable dma clk */
+	clk_enable(pdmac->clk);
+#endif
+
 	irq = adev->irq[0];
 	ret = request_irq(irq, pl330_irq_handler, 0,
 			dev_name(&adev->dev), pi);
@@ -763,8 +790,6 @@  pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		goto probe_err4;
 	}
 
-	amba_set_drvdata(adev, pdmac);
-
 	dev_info(&adev->dev,
 		"Loaded driver for PL330 DMAC-%d\n", adev->periphid);
 	dev_info(&adev->dev,
@@ -825,6 +850,13 @@  static int __devexit pl330_remove(struct amba_device *adev)
 	res = &adev->res;
 	release_mem_region(res->start, resource_size(res));
 
+#ifdef CONFIG_PM_RUNTIME
+	pm_runtime_put(&adev->dev);
+	pm_runtime_disable(&adev->dev);
+#else
+	clk_disable(pdmac->clk);
+#endif
+
 	kfree(pdmac);
 
 	return 0;
@@ -838,10 +870,49 @@  static struct amba_id pl330_ids[] = {
 	{ 0, 0 },
 };
 
+#ifdef CONFIG_PM_RUNTIME
+static int pl330_runtime_suspend(struct device *dev)
+{
+	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+	if (!pdmac) {
+		dev_err(dev, "failed to get dmac\n");
+		return -ENODEV;
+	}
+
+	clk_disable(pdmac->clk);
+
+	return 0;
+}
+
+static int pl330_runtime_resume(struct device *dev)
+{
+	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+	if (!pdmac) {
+		dev_err(dev, "failed to get dmac\n");
+		return -ENODEV;
+	}
+
+	clk_enable(pdmac->clk);
+
+	return 0;
+}
+#else
+#define pl330_runtime_suspend	NULL
+#define pl330_runtime_resume	NULL
+#endif /* CONFIG_PM_RUNTIME */
+
+static const struct dev_pm_ops pl330_pm_ops = {
+	.runtime_suspend = pl330_runtime_suspend,
+	.runtime_resume = pl330_runtime_resume,
+};
+
 static struct amba_driver pl330_driver = {
 	.drv = {
 		.owner = THIS_MODULE,
 		.name = "dma-pl330",
+		.pm = &pl330_pm_ops,
 	},
 	.id_table = pl330_ids,
 	.probe = pl330_probe,