linux-mmc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 3/3] mmc: sdhci-of-arasan: add runtime pm support
@ 2015-10-20  7:05 Shawn Lin
  2015-10-20  8:00 ` kbuild test robot
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Shawn Lin @ 2015-10-20  7:05 UTC (permalink / raw)
  To: Ulf Hansson, Michal Simek, soren.brinkmann
  Cc: linux-mmc, linux-kernel, Shawn Lin

This patch add runtime_suspend and runtime_resume for
sdhci-of-arasan. Currently we also suspend phy at
runtime_suspend for power-saving.

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
---

Changes in v2: None

 drivers/mmc/host/sdhci-of-arasan.c | 80 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 77 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
index 85bd0f9d..579f7bb 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -30,6 +30,8 @@
 #define CLK_CTRL_TIMEOUT_MASK		(0xf << CLK_CTRL_TIMEOUT_SHIFT)
 #define CLK_CTRL_TIMEOUT_MIN_EXP	13
 
+#define ARASAN_RPM_DELAY_MS		50
+
 /**
  * struct sdhci_arasan_data
  * @clk_ahb:	Pointer to the AHB clock
@@ -183,8 +185,70 @@ static int sdhci_arasan_resume(struct device *dev)
 }
 #endif /* ! CONFIG_PM_SLEEP */
 
-static SIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops, sdhci_arasan_suspend,
-			 sdhci_arasan_resume);
+
+#ifdef CONFIG_PM
+static int sdhci_arasan_runtime_suspend(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv;
+	int ret;
+
+	ret = sdhci_runtime_suspend_host(host);
+	if (ret)
+		return ret;
+
+	if (!IS_ERR(sdhci_arasan->phy)) {
+		ret = sdhci_arasan_suspend_phy(sdhci_arasan->phy);
+		if (ret) {
+			dev_err(dev, "Cannot suspend phy at runtime.\n");
+			sdhci_runtime_resume_host(host);
+			return ret;
+		}
+	}
+
+	clk_disable_unprepare(sdhci_arasan->clk_ahb);
+	clk_disable_unprepare(pltfm_host->clk);
+
+	return 0;
+}
+
+static int sdhci_arasan_runtime_resume(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv;
+	int ret;
+
+	clk_prepare_enable(pltfm_host->clk);
+	clk_prepare_enable(sdhci_arasan->clk_ahb);
+
+	if (!IS_ERR(sdhci_arasan->phy)) {
+		ret = sdhci_arasan_resume_phy(sdhci_arasan->phy);
+		if (ret) {
+			dev_err(dev, "Cannot resume phy at runtime.\n");
+			clk_disable_unprepare(sdhci_arasan->clk_ahb);
+			clk_disable_unprepare(pltfm_host->clk);
+			return ret;
+		}
+	}
+
+	return sdhci_runtime_resume_host(host);
+}
+#endif
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops sdhci_arasan_pmops = {
+	SET_SYSTEM_SLEEP_PM_OPS(sdhci_arasan_suspend, sdhci_arasan_resume)
+	SET_RUNTIME_PM_OPS(sdhci_arasan_runtime_suspend,
+				sdhci_arasan_runtime_resume, NULL)
+};
+
+#define SDHCI_ARASAN_PMOPS (&sdhci_arasan_pmops)
+
+#else
+#define SDHCI_ARASAN_PMOPS NULL
+#endif
 
 static int sdhci_arasan_probe(struct platform_device *pdev)
 {
@@ -272,6 +336,11 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
 		goto clk_disable_all;
 	}
 
+	pm_runtime_set_autosuspend_delay(&pdev->dev, ARASAN_RPM_DELAY_MS);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, 1);
+
 	ret = sdhci_add_host(host);
 	if (ret)
 		goto err_pltfm_free;
@@ -279,6 +348,7 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
 	return 0;
 
 err_pltfm_free:
+	pm_runtime_disable(&pdev->dev);
 	sdhci_pltfm_free(pdev);
 clk_disable_all:
 	clk_disable_unprepare(clk_xin);
@@ -297,6 +367,10 @@ static int sdhci_arasan_remove(struct platform_device *pdev)
 	if (!IS_ERR(sdhci_arasan->phy))
 		phy_exit(sdhci_arasan->phy);
 
+	pm_runtime_get_sync(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
 	clk_disable_unprepare(sdhci_arasan->clk_ahb);
 
 	return sdhci_pltfm_unregister(pdev);
@@ -314,7 +388,7 @@ static struct platform_driver sdhci_arasan_driver = {
 	.driver = {
 		.name = "sdhci-arasan",
 		.of_match_table = sdhci_arasan_of_match,
-		.pm = &sdhci_arasan_dev_pm_ops,
+		.pm = SDHCI_ARASAN_PMOPS,
 	},
 	.probe = sdhci_arasan_probe,
 	.remove = sdhci_arasan_remove,
-- 
2.3.7

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 3/3] mmc: sdhci-of-arasan: add runtime pm support
  2015-10-20  7:05 [PATCH v3 3/3] mmc: sdhci-of-arasan: add runtime pm support Shawn Lin
@ 2015-10-20  8:00 ` kbuild test robot
  2015-10-20  8:03 ` Michal Simek
  2015-10-20  9:19 ` Ulf Hansson
  2 siblings, 0 replies; 5+ messages in thread
From: kbuild test robot @ 2015-10-20  8:00 UTC (permalink / raw)
  Cc: kbuild-all, Ulf Hansson, Michal Simek, soren.brinkmann, linux-mmc,
	linux-kernel, Shawn Lin

[-- Attachment #1: Type: text/plain, Size: 2516 bytes --]

Hi Shawn,

[auto build test ERROR on ulf.hansson-mmc/next -- if it's inappropriate base, please suggest rules for selecting the more suitable base]

url:    https://github.com/0day-ci/linux/commits/Shawn-Lin/Documentation-bindings-add-description-of-phy-for-sdhci-of-arasan/20151020-150853
config: i386-randconfig-i1-201542 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/mmc/host/sdhci-of-arasan.c: In function 'sdhci_arasan_runtime_suspend':
>> drivers/mmc/host/sdhci-of-arasan.c:202:9: error: implicit declaration of function 'sdhci_arasan_suspend_phy' [-Werror=implicit-function-declaration]
      ret = sdhci_arasan_suspend_phy(sdhci_arasan->phy);
            ^
   drivers/mmc/host/sdhci-of-arasan.c: In function 'sdhci_arasan_runtime_resume':
>> drivers/mmc/host/sdhci-of-arasan.c:227:9: error: implicit declaration of function 'sdhci_arasan_resume_phy' [-Werror=implicit-function-declaration]
      ret = sdhci_arasan_resume_phy(sdhci_arasan->phy);
            ^
   cc1: some warnings being treated as errors

vim +/sdhci_arasan_suspend_phy +202 drivers/mmc/host/sdhci-of-arasan.c

   196	
   197		ret = sdhci_runtime_suspend_host(host);
   198		if (ret)
   199			return ret;
   200	
   201		if (!IS_ERR(sdhci_arasan->phy)) {
 > 202			ret = sdhci_arasan_suspend_phy(sdhci_arasan->phy);
   203			if (ret) {
   204				dev_err(dev, "Cannot suspend phy at runtime.\n");
   205				sdhci_runtime_resume_host(host);
   206				return ret;
   207			}
   208		}
   209	
   210		clk_disable_unprepare(sdhci_arasan->clk_ahb);
   211		clk_disable_unprepare(pltfm_host->clk);
   212	
   213		return 0;
   214	}
   215	
   216	static int sdhci_arasan_runtime_resume(struct device *dev)
   217	{
   218		struct sdhci_host *host = dev_get_drvdata(dev);
   219		struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
   220		struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv;
   221		int ret;
   222	
   223		clk_prepare_enable(pltfm_host->clk);
   224		clk_prepare_enable(sdhci_arasan->clk_ahb);
   225	
   226		if (!IS_ERR(sdhci_arasan->phy)) {
 > 227			ret = sdhci_arasan_resume_phy(sdhci_arasan->phy);
   228			if (ret) {
   229				dev_err(dev, "Cannot resume phy at runtime.\n");
   230				clk_disable_unprepare(sdhci_arasan->clk_ahb);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 22567 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 3/3] mmc: sdhci-of-arasan: add runtime pm support
  2015-10-20  7:05 [PATCH v3 3/3] mmc: sdhci-of-arasan: add runtime pm support Shawn Lin
  2015-10-20  8:00 ` kbuild test robot
@ 2015-10-20  8:03 ` Michal Simek
  2015-10-20  8:41   ` Shawn Lin
  2015-10-20  9:19 ` Ulf Hansson
  2 siblings, 1 reply; 5+ messages in thread
From: Michal Simek @ 2015-10-20  8:03 UTC (permalink / raw)
  To: Shawn Lin, Ulf Hansson, Michal Simek, soren.brinkmann
  Cc: linux-mmc, linux-kernel

Hi,

On 10/20/2015 09:05 AM, Shawn Lin wrote:
> This patch add runtime_suspend and runtime_resume for
> sdhci-of-arasan. Currently we also suspend phy at
> runtime_suspend for power-saving.
> 
> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> ---
> 
> Changes in v2: None
> 
>  drivers/mmc/host/sdhci-of-arasan.c | 80 ++++++++++++++++++++++++++++++++++++--
>  1 file changed, 77 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
> index 85bd0f9d..579f7bb 100644
> --- a/drivers/mmc/host/sdhci-of-arasan.c
> +++ b/drivers/mmc/host/sdhci-of-arasan.c
> @@ -30,6 +30,8 @@
>  #define CLK_CTRL_TIMEOUT_MASK		(0xf << CLK_CTRL_TIMEOUT_SHIFT)
>  #define CLK_CTRL_TIMEOUT_MIN_EXP	13
>  
> +#define ARASAN_RPM_DELAY_MS		50
> +
>  /**
>   * struct sdhci_arasan_data
>   * @clk_ahb:	Pointer to the AHB clock
> @@ -183,8 +185,70 @@ static int sdhci_arasan_resume(struct device *dev)
>  }
>  #endif /* ! CONFIG_PM_SLEEP */
>  
> -static SIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops, sdhci_arasan_suspend,
> -			 sdhci_arasan_resume);
> +
> +#ifdef CONFIG_PM
> +static int sdhci_arasan_runtime_suspend(struct device *dev)
> +{
> +	struct sdhci_host *host = dev_get_drvdata(dev);
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv;
> +	int ret;
> +
> +	ret = sdhci_runtime_suspend_host(host);
> +	if (ret)
> +		return ret;
> +
> +	if (!IS_ERR(sdhci_arasan->phy)) {
> +		ret = sdhci_arasan_suspend_phy(sdhci_arasan->phy);
> +		if (ret) {
> +			dev_err(dev, "Cannot suspend phy at runtime.\n");
> +			sdhci_runtime_resume_host(host);
> +			return ret;
> +		}
> +	}
> +
> +	clk_disable_unprepare(sdhci_arasan->clk_ahb);
> +	clk_disable_unprepare(pltfm_host->clk);
> +
> +	return 0;
> +}
> +
> +static int sdhci_arasan_runtime_resume(struct device *dev)
> +{
> +	struct sdhci_host *host = dev_get_drvdata(dev);
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv;
> +	int ret;
> +
> +	clk_prepare_enable(pltfm_host->clk);
> +	clk_prepare_enable(sdhci_arasan->clk_ahb);
> +
> +	if (!IS_ERR(sdhci_arasan->phy)) {
> +		ret = sdhci_arasan_resume_phy(sdhci_arasan->phy);
> +		if (ret) {
> +			dev_err(dev, "Cannot resume phy at runtime.\n");
> +			clk_disable_unprepare(sdhci_arasan->clk_ahb);
> +			clk_disable_unprepare(pltfm_host->clk);
> +			return ret;
> +		}
> +	}
> +
> +	return sdhci_runtime_resume_host(host);
> +}
> +#endif
> +
> +#ifdef CONFIG_PM
> +static const struct dev_pm_ops sdhci_arasan_pmops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(sdhci_arasan_suspend, sdhci_arasan_resume)
> +	SET_RUNTIME_PM_OPS(sdhci_arasan_runtime_suspend,
> +				sdhci_arasan_runtime_resume, NULL)
> +};
> +
> +#define SDHCI_ARASAN_PMOPS (&sdhci_arasan_pmops)
> +
> +#else
> +#define SDHCI_ARASAN_PMOPS NULL
> +#endif

This is completely wrong. SET_SYSTEM_SLEEP_PM_OPS, SET_RUNTIME_PM_OPS
have both declarations for !PM_SLEEP, !PM cases. It means you can remove
this ifdef mess.

I was doing experiment with your code and you need to add __maybe_unused
for functions which are not used when certain functions are not wired
for !PM, !PM_SLEEP cases.

Something like this should be added to any SDHCI header. (or Using
macros). Definitely this should be tested for all combinations.
#if !defined(CONFIG_PM)
static inline int sdhci_suspend_host(struct sdhci_host *host)	{ return -1; }
static inline int sdhci_resume_host(struct sdhci_host *host)	{ return -1; }
static inline int sdhci_runtime_suspend_host(struct sdhci_host *host)	{
return -1; }
static inline int sdhci_runtime_resume_host(struct sdhci_host *host)	{
return -1; }
#endif


>  
>  static int sdhci_arasan_probe(struct platform_device *pdev)
>  {
> @@ -272,6 +336,11 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
>  		goto clk_disable_all;
>  	}
>  
> +	pm_runtime_set_autosuspend_delay(&pdev->dev, ARASAN_RPM_DELAY_MS);
> +	pm_runtime_use_autosuspend(&pdev->dev);
> +	pm_runtime_enable(&pdev->dev);
> +	pm_suspend_ignore_children(&pdev->dev, 1);
> +
>  	ret = sdhci_add_host(host);
>  	if (ret)
>  		goto err_pltfm_free;
> @@ -279,6 +348,7 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
>  	return 0;
>  
>  err_pltfm_free:
> +	pm_runtime_disable(&pdev->dev);
>  	sdhci_pltfm_free(pdev);
>  clk_disable_all:
>  	clk_disable_unprepare(clk_xin);
> @@ -297,6 +367,10 @@ static int sdhci_arasan_remove(struct platform_device *pdev)
>  	if (!IS_ERR(sdhci_arasan->phy))
>  		phy_exit(sdhci_arasan->phy);
>  
> +	pm_runtime_get_sync(&pdev->dev);
> +	pm_runtime_dont_use_autosuspend(&pdev->dev);
> +	pm_runtime_disable(&pdev->dev);
> +
>  	clk_disable_unprepare(sdhci_arasan->clk_ahb);
>  
>  	return sdhci_pltfm_unregister(pdev);
> @@ -314,7 +388,7 @@ static struct platform_driver sdhci_arasan_driver = {
>  	.driver = {
>  		.name = "sdhci-arasan",
>  		.of_match_table = sdhci_arasan_of_match,
> -		.pm = &sdhci_arasan_dev_pm_ops,
> +		.pm = SDHCI_ARASAN_PMOPS,

Keep origin name here. No reason for this macro at all.

>  	},
>  	.probe = sdhci_arasan_probe,
>  	.remove = sdhci_arasan_remove,
> 

Thanks,
Michal

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 3/3] mmc: sdhci-of-arasan: add runtime pm support
  2015-10-20  8:03 ` Michal Simek
@ 2015-10-20  8:41   ` Shawn Lin
  0 siblings, 0 replies; 5+ messages in thread
From: Shawn Lin @ 2015-10-20  8:41 UTC (permalink / raw)
  To: Michal Simek, Ulf Hansson, soren.brinkmann
  Cc: shawn.lin, linux-mmc, linux-kernel

On 2015/10/20 16:03, Michal Simek wrote:
> Hi,
>
> On 10/20/2015 09:05 AM, Shawn Lin wrote:
>> This patch add runtime_suspend and runtime_resume for
>> sdhci-of-arasan. Currently we also suspend phy at
>> runtime_suspend for power-saving.
>>
>> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
>> ---
>>
>> Changes in v2: None
>>
>>   drivers/mmc/host/sdhci-of-arasan.c | 80 ++++++++++++++++++++++++++++++++++++--
>>   1 file changed, 77 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
>> index 85bd0f9d..579f7bb 100644
>> --- a/drivers/mmc/host/sdhci-of-arasan.c
>> +++ b/drivers/mmc/host/sdhci-of-arasan.c
>> @@ -30,6 +30,8 @@
>>   #define CLK_CTRL_TIMEOUT_MASK		(0xf << CLK_CTRL_TIMEOUT_SHIFT)
>>   #define CLK_CTRL_TIMEOUT_MIN_EXP	13
>>
>> +#define ARASAN_RPM_DELAY_MS		50
>> +
>>   /**
>>    * struct sdhci_arasan_data
>>    * @clk_ahb:	Pointer to the AHB clock
>> @@ -183,8 +185,70 @@ static int sdhci_arasan_resume(struct device *dev)
>>   }
>>   #endif /* ! CONFIG_PM_SLEEP */
>>
>> -static SIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops, sdhci_arasan_suspend,
>> -			 sdhci_arasan_resume);
>> +
>> +#ifdef CONFIG_PM
>> +static int sdhci_arasan_runtime_suspend(struct device *dev)
>> +{
>> +	struct sdhci_host *host = dev_get_drvdata(dev);
>> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>> +	struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv;
>> +	int ret;
>> +
>> +	ret = sdhci_runtime_suspend_host(host);
>> +	if (ret)
>> +		return ret;
>> +
>> +	if (!IS_ERR(sdhci_arasan->phy)) {
>> +		ret = sdhci_arasan_suspend_phy(sdhci_arasan->phy);
>> +		if (ret) {
>> +			dev_err(dev, "Cannot suspend phy at runtime.\n");
>> +			sdhci_runtime_resume_host(host);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	clk_disable_unprepare(sdhci_arasan->clk_ahb);
>> +	clk_disable_unprepare(pltfm_host->clk);
>> +
>> +	return 0;
>> +}
>> +
>> +static int sdhci_arasan_runtime_resume(struct device *dev)
>> +{
>> +	struct sdhci_host *host = dev_get_drvdata(dev);
>> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>> +	struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv;
>> +	int ret;
>> +
>> +	clk_prepare_enable(pltfm_host->clk);
>> +	clk_prepare_enable(sdhci_arasan->clk_ahb);
>> +
>> +	if (!IS_ERR(sdhci_arasan->phy)) {
>> +		ret = sdhci_arasan_resume_phy(sdhci_arasan->phy);
>> +		if (ret) {
>> +			dev_err(dev, "Cannot resume phy at runtime.\n");
>> +			clk_disable_unprepare(sdhci_arasan->clk_ahb);
>> +			clk_disable_unprepare(pltfm_host->clk);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	return sdhci_runtime_resume_host(host);
>> +}
>> +#endif
>> +
>> +#ifdef CONFIG_PM
>> +static const struct dev_pm_ops sdhci_arasan_pmops = {
>> +	SET_SYSTEM_SLEEP_PM_OPS(sdhci_arasan_suspend, sdhci_arasan_resume)
>> +	SET_RUNTIME_PM_OPS(sdhci_arasan_runtime_suspend,
>> +				sdhci_arasan_runtime_resume, NULL)
>> +};
>> +
>> +#define SDHCI_ARASAN_PMOPS (&sdhci_arasan_pmops)
>> +
>> +#else
>> +#define SDHCI_ARASAN_PMOPS NULL
>> +#endif
>
> This is completely wrong. SET_SYSTEM_SLEEP_PM_OPS, SET_RUNTIME_PM_OPS
> have both declarations for !PM_SLEEP, !PM cases. It means you can remove
> this ifdef mess.
>
> I was doing experiment with your code and you need to add __maybe_unused
> for functions which are not used when certain functions are not wired
> for !PM, !PM_SLEEP cases.
>
> Something like this should be added to any SDHCI header. (or Using
> macros). Definitely this should be tested for all combinations.
> #if !defined(CONFIG_PM)
> static inline int sdhci_suspend_host(struct sdhci_host *host)	{ return -1; }
> static inline int sdhci_resume_host(struct sdhci_host *host)	{ return -1; }
> static inline int sdhci_runtime_suspend_host(struct sdhci_host *host)	{
> return -1; }
> static inline int sdhci_runtime_resume_host(struct sdhci_host *host)	{
> return -1; }
> #endif
>

Thanks for pointing out it.

Actually I took a little bit from
sdhci-pxav3.c and sdhci-s3c.c. So I didn't find the mistake.

I now look into the SET_SYSTEM_SLEEP_PM_OPS, SET_RUNTIME_PM_OPS, yes,
it matches the case you mentioned.

Definitely I will fix it. :)

So let me wait for Ulf if he has some comments for this patchset and 
then re-spin my the next version.

>
>>
>>   static int sdhci_arasan_probe(struct platform_device *pdev)
>>   {
>> @@ -272,6 +336,11 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
>>   		goto clk_disable_all;
>>   	}
>>
>> +	pm_runtime_set_autosuspend_delay(&pdev->dev, ARASAN_RPM_DELAY_MS);
>> +	pm_runtime_use_autosuspend(&pdev->dev);
>> +	pm_runtime_enable(&pdev->dev);
>> +	pm_suspend_ignore_children(&pdev->dev, 1);
>> +
>>   	ret = sdhci_add_host(host);
>>   	if (ret)
>>   		goto err_pltfm_free;
>> @@ -279,6 +348,7 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
>>   	return 0;
>>
>>   err_pltfm_free:
>> +	pm_runtime_disable(&pdev->dev);
>>   	sdhci_pltfm_free(pdev);
>>   clk_disable_all:
>>   	clk_disable_unprepare(clk_xin);
>> @@ -297,6 +367,10 @@ static int sdhci_arasan_remove(struct platform_device *pdev)
>>   	if (!IS_ERR(sdhci_arasan->phy))
>>   		phy_exit(sdhci_arasan->phy);
>>
>> +	pm_runtime_get_sync(&pdev->dev);
>> +	pm_runtime_dont_use_autosuspend(&pdev->dev);
>> +	pm_runtime_disable(&pdev->dev);
>> +
>>   	clk_disable_unprepare(sdhci_arasan->clk_ahb);
>>
>>   	return sdhci_pltfm_unregister(pdev);
>> @@ -314,7 +388,7 @@ static struct platform_driver sdhci_arasan_driver = {
>>   	.driver = {
>>   		.name = "sdhci-arasan",
>>   		.of_match_table = sdhci_arasan_of_match,
>> -		.pm = &sdhci_arasan_dev_pm_ops,
>> +		.pm = SDHCI_ARASAN_PMOPS,
>
> Keep origin name here. No reason for this macro at all.

Got it.

>
>>   	},
>>   	.probe = sdhci_arasan_probe,
>>   	.remove = sdhci_arasan_remove,
>>
>
> Thanks,
> Michal
>
>
>


-- 
Best Regards
Shawn Lin

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 3/3] mmc: sdhci-of-arasan: add runtime pm support
  2015-10-20  7:05 [PATCH v3 3/3] mmc: sdhci-of-arasan: add runtime pm support Shawn Lin
  2015-10-20  8:00 ` kbuild test robot
  2015-10-20  8:03 ` Michal Simek
@ 2015-10-20  9:19 ` Ulf Hansson
  2 siblings, 0 replies; 5+ messages in thread
From: Ulf Hansson @ 2015-10-20  9:19 UTC (permalink / raw)
  To: Shawn Lin
  Cc: Michal Simek, Sören Brinkmann, linux-mmc,
	linux-kernel@vger.kernel.org

On 20 October 2015 at 09:05, Shawn Lin <shawn.lin@rock-chips.com> wrote:
> This patch add runtime_suspend and runtime_resume for
> sdhci-of-arasan. Currently we also suspend phy at
> runtime_suspend for power-saving.
>
> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> ---
>
> Changes in v2: None
>
>  drivers/mmc/host/sdhci-of-arasan.c | 80 ++++++++++++++++++++++++++++++++++++--
>  1 file changed, 77 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
> index 85bd0f9d..579f7bb 100644
> --- a/drivers/mmc/host/sdhci-of-arasan.c
> +++ b/drivers/mmc/host/sdhci-of-arasan.c
> @@ -30,6 +30,8 @@
>  #define CLK_CTRL_TIMEOUT_MASK          (0xf << CLK_CTRL_TIMEOUT_SHIFT)
>  #define CLK_CTRL_TIMEOUT_MIN_EXP       13
>
> +#define ARASAN_RPM_DELAY_MS            50
> +
>  /**
>   * struct sdhci_arasan_data
>   * @clk_ahb:   Pointer to the AHB clock
> @@ -183,8 +185,70 @@ static int sdhci_arasan_resume(struct device *dev)
>  }
>  #endif /* ! CONFIG_PM_SLEEP */
>
> -static SIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops, sdhci_arasan_suspend,
> -                        sdhci_arasan_resume);
> +
> +#ifdef CONFIG_PM
> +static int sdhci_arasan_runtime_suspend(struct device *dev)
> +{
> +       struct sdhci_host *host = dev_get_drvdata(dev);
> +       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +       struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv;
> +       int ret;
> +
> +       ret = sdhci_runtime_suspend_host(host);
> +       if (ret)
> +               return ret;
> +
> +       if (!IS_ERR(sdhci_arasan->phy)) {
> +               ret = sdhci_arasan_suspend_phy(sdhci_arasan->phy);
> +               if (ret) {
> +                       dev_err(dev, "Cannot suspend phy at runtime.\n");
> +                       sdhci_runtime_resume_host(host);
> +                       return ret;
> +               }
> +       }
> +
> +       clk_disable_unprepare(sdhci_arasan->clk_ahb);
> +       clk_disable_unprepare(pltfm_host->clk);

This looks correct, but comparing to the system PM callbacks clocks is
gated via clk_disable() and not via clk_disable_unprepare(). So, you
need to fix this for system PM.

> +
> +       return 0;
> +}
> +
> +static int sdhci_arasan_runtime_resume(struct device *dev)
> +{
> +       struct sdhci_host *host = dev_get_drvdata(dev);
> +       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +       struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv;
> +       int ret;
> +
> +       clk_prepare_enable(pltfm_host->clk);
> +       clk_prepare_enable(sdhci_arasan->clk_ahb);
> +
> +       if (!IS_ERR(sdhci_arasan->phy)) {
> +               ret = sdhci_arasan_resume_phy(sdhci_arasan->phy);
> +               if (ret) {
> +                       dev_err(dev, "Cannot resume phy at runtime.\n");
> +                       clk_disable_unprepare(sdhci_arasan->clk_ahb);
> +                       clk_disable_unprepare(pltfm_host->clk);
> +                       return ret;
> +               }
> +       }
> +
> +       return sdhci_runtime_resume_host(host);

The error handling in a runtime resume function sometimes tends to be
a bit tricky.

In this case you have decided to care only about the errors from the
phy API, but ignores the other ones. That isn't consistent, so I think
you need to decide if you want error handling and then for all cases,
or not.

> +}
> +#endif
> +
> +#ifdef CONFIG_PM

Remove this ifdef..

> +static const struct dev_pm_ops sdhci_arasan_pmops = {
> +       SET_SYSTEM_SLEEP_PM_OPS(sdhci_arasan_suspend, sdhci_arasan_resume)

Since you enabled runtime PM, that means sdhci_arasan_suspend() can
end up being invoked when the device is runtime suspended. You don't
deal with that case.

In the ideal scenario you could assign the system PM callbacks to
pm_runtime_force_suspend|resume(), unless you have specific wakeup
settings to manage at system PM. Using this solution would solve the
above problem, in other case you need to deal with it from
sdhci_arasan_suspend|resume().

> +       SET_RUNTIME_PM_OPS(sdhci_arasan_runtime_suspend,
> +                               sdhci_arasan_runtime_resume, NULL)
> +};
> +

... and everything below towards the endif.

Then use the reference of sdhci_arasan_pmops directly when needed below instead.

The minor overhead of having an empty sdhci_arasan_pmops struct when
CONFIG_PM isn't set can be neglected.

> +#define SDHCI_ARASAN_PMOPS (&sdhci_arasan_pmops)
> +
> +#else
> +#define SDHCI_ARASAN_PMOPS NULL
> +#endif
>
>  static int sdhci_arasan_probe(struct platform_device *pdev)
>  {
> @@ -272,6 +336,11 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
>                 goto clk_disable_all;
>         }
>
> +       pm_runtime_set_autosuspend_delay(&pdev->dev, ARASAN_RPM_DELAY_MS);
> +       pm_runtime_use_autosuspend(&pdev->dev);

pm_runtime_set_active() is missing.

> +       pm_runtime_enable(&pdev->dev);
> +       pm_suspend_ignore_children(&pdev->dev, 1);
> +
>         ret = sdhci_add_host(host);
>         if (ret)
>                 goto err_pltfm_free;
> @@ -279,6 +348,7 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
>         return 0;
>
>  err_pltfm_free:
> +       pm_runtime_disable(&pdev->dev);
>         sdhci_pltfm_free(pdev);
>  clk_disable_all:
>         clk_disable_unprepare(clk_xin);
> @@ -297,6 +367,10 @@ static int sdhci_arasan_remove(struct platform_device *pdev)
>         if (!IS_ERR(sdhci_arasan->phy))
>                 phy_exit(sdhci_arasan->phy);
>
> +       pm_runtime_get_sync(&pdev->dev);
> +       pm_runtime_dont_use_autosuspend(&pdev->dev);

pm_runtime_dont_use_autosuspend() shouldn't be needed here I think.

> +       pm_runtime_disable(&pdev->dev);
> +
>         clk_disable_unprepare(sdhci_arasan->clk_ahb);
>
>         return sdhci_pltfm_unregister(pdev);
> @@ -314,7 +388,7 @@ static struct platform_driver sdhci_arasan_driver = {
>         .driver = {
>                 .name = "sdhci-arasan",
>                 .of_match_table = sdhci_arasan_of_match,
> -               .pm = &sdhci_arasan_dev_pm_ops,
> +               .pm = SDHCI_ARASAN_PMOPS,
>         },
>         .probe = sdhci_arasan_probe,
>         .remove = sdhci_arasan_remove,
> --
> 2.3.7
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-10-20  9:19 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-20  7:05 [PATCH v3 3/3] mmc: sdhci-of-arasan: add runtime pm support Shawn Lin
2015-10-20  8:00 ` kbuild test robot
2015-10-20  8:03 ` Michal Simek
2015-10-20  8:41   ` Shawn Lin
2015-10-20  9:19 ` Ulf Hansson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).