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

Chanwoo Choi cwchoi00 at gmail.com
Tue Jul 26 02:03:27 EDT 2011


Boojin Kim wrote:
> Signed-off-by: Boojin Kim <boojin.kim at 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




More information about the linux-arm-kernel mailing list