Re: [PATCH v3 1/2] mmc: sdhci: fix abort due to missing runtime PM

2015-08-25 Thread Ulf Hansson
On 30 July 2015 at 13:37, Stefan Agner ste...@agner.ch wrote:
 Hi Ulf,

 What is the status on that?

 --
 Stefan

 On 2015-05-21 09:15, Stefan Agner wrote:
 When using i.MX ESDHC driver, while entering suspend while the device
 is in runtime PM, the sdhci_(suspend|resume)_host function are called
 with disabled clocks. Since this functions access the SDHC host
 registers, this leads to an external abort on Vybrid SoC:

 [   37.772967] Unhandled fault: imprecise external abort (0x1c06) at 
 0x76f5f000
 [   37.780304] Internal error: : 1c06 [#1] ARM
 [   37.784670] Modules linked in:
 [   37.787908] CPU: 0 PID: 428 Comm: sh Not tainted
 3.18.0-rc5-00119-geefd097-dirty #1540
 [   37.796142] task: 8e246c00 ti: 8ca6c000 task.ti: 8ca6c000
 [   37.801785] PC is at esdhc_writel_le+0x40/0xec
 [   37.806431] LR is at sdhci_set_card_detection+0xe0/0xe4
 [   37.811877] pc : [803f0584]lr : [803eaaa0]psr: 400f0013
 [   37.811877] sp : 8ca6dd28  ip : 0001  fp : 8ca6dd3c
 [   37.823766] r10: 807a233c  r9 :   r8 : 8e8b7210
 [   37.829194] r7 : 802d8a08  r6 : 8082e928  r5 :   r4 : 0002
 [   37.835974] r3 : 8ea34e90  r2 : 0038  r1 :   r0 : 8ea32ac0
 ...

 Clocks need to be enabled to access the registers. Fix the issue by
 add runtime PM enabled pltfm implementation of suspend/resume which
 take care of clocks by using the runtime PM API properly.

 Signed-off-by: Stefan Agner ste...@agner.ch
 ---
 Changes since v2:
 - Implement a generic pltfm suspend/resume function instead of a local
   function in sdhci-esdhc-imx.c
 - Convert sdhci-pxav3 to use the runtime PM enabled pltfm suspend/resume
   function too

  drivers/mmc/host/sdhci-esdhc-imx.c |  2 +-
  drivers/mmc/host/sdhci-pltfm.c | 36 
  drivers/mmc/host/sdhci-pltfm.h |  2 ++
  3 files changed, 39 insertions(+), 1 deletion(-)

 diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c
 b/drivers/mmc/host/sdhci-esdhc-imx.c
 index 82f512d..7b7b3a3 100644
 --- a/drivers/mmc/host/sdhci-esdhc-imx.c
 +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
 @@ -1132,7 +1132,7 @@ static int sdhci_esdhc_runtime_resume(struct device 
 *dev)
  #endif

  static const struct dev_pm_ops sdhci_esdhc_pmops = {
 - SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_pltfm_resume)
 + SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_rpm_suspend, 
 sdhci_pltfm_rpm_resume)
   SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend,
   sdhci_esdhc_runtime_resume, NULL)
  };
 diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
 index a207f5a..38c03cd 100644
 --- a/drivers/mmc/host/sdhci-pltfm.c
 +++ b/drivers/mmc/host/sdhci-pltfm.c
 @@ -31,6 +31,7 @@
  #include linux/err.h
  #include linux/module.h
  #include linux/of.h
 +#include linux/pm_runtime.h
  #ifdef CONFIG_PPC
  #include asm/machdep.h
  #endif
 @@ -256,6 +257,41 @@ const struct dev_pm_ops sdhci_pltfm_pmops = {
   .resume = sdhci_pltfm_resume,
  };
  EXPORT_SYMBOL_GPL(sdhci_pltfm_pmops);
 +
 +int sdhci_pltfm_rpm_suspend(struct device *dev)
 +{
 + int ret;
 + struct sdhci_host *host = dev_get_drvdata(dev);
 +
 + pm_runtime_get_sync(dev);
 + ret = sdhci_suspend_host(host);
 + pm_runtime_mark_last_busy(dev);
 + pm_runtime_put_autosuspend(dev);
 + if (ret)
 + return ret;
 +
 + return pm_runtime_force_suspend(dev);
 +}
 +EXPORT_SYMBOL_GPL(sdhci_pltfm_rpm_suspend);
 +
 +int sdhci_pltfm_rpm_resume(struct device *dev)
 +{
 + int ret;
 + struct sdhci_host *host = dev_get_drvdata(dev);
 +
 + ret = pm_runtime_force_resume(dev);
 +
 + if (ret)
 + return ret;
 +
 + pm_runtime_get_sync(dev);
 + ret = sdhci_resume_host(host);
 + pm_runtime_mark_last_busy(dev);
 + pm_runtime_put_autosuspend(dev);
 +
 + return ret;
 +}
 +EXPORT_SYMBOL_GPL(sdhci_pltfm_rpm_resume);
  #endif   /* CONFIG_PM */

  static int __init sdhci_pltfm_drv_init(void)
 diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h
 index 04bc248..ac5f6ea 100644
 --- a/drivers/mmc/host/sdhci-pltfm.h
 +++ b/drivers/mmc/host/sdhci-pltfm.h
 @@ -114,6 +114,8 @@ static inline void *sdhci_pltfm_priv(struct
 sdhci_pltfm_host *host)
  extern int sdhci_pltfm_suspend(struct device *dev);
  extern int sdhci_pltfm_resume(struct device *dev);
  extern const struct dev_pm_ops sdhci_pltfm_pmops;
 +extern int sdhci_pltfm_rpm_suspend(struct device *dev);
 +extern int sdhci_pltfm_rpm_resume(struct device *dev);
  #define SDHCI_PLTFM_PMOPS (sdhci_pltfm_pmops)
  #else
  #define SDHCI_PLTFM_PMOPS NULL


This is a bit complicated, mostly due to the code structure of sdhci
and around how it handles wakeup settings. I do understand that you
want to fix a real bug, but in this case I think we need to figure out
a long term solution, else we will be solving one problem but
inserting another.

Obviously the sdhci device needs to be runtime resumed while accessing
it. Now, I wonder *why* 

Re: [PATCH v3 1/2] mmc: sdhci: fix abort due to missing runtime PM

2015-07-31 Thread Stefan Agner
Hi Ulf,

What is the status on that?

--
Stefan

On 2015-05-21 09:15, Stefan Agner wrote:
 When using i.MX ESDHC driver, while entering suspend while the device
 is in runtime PM, the sdhci_(suspend|resume)_host function are called
 with disabled clocks. Since this functions access the SDHC host
 registers, this leads to an external abort on Vybrid SoC:
 
 [   37.772967] Unhandled fault: imprecise external abort (0x1c06) at 
 0x76f5f000
 [   37.780304] Internal error: : 1c06 [#1] ARM
 [   37.784670] Modules linked in:
 [   37.787908] CPU: 0 PID: 428 Comm: sh Not tainted
 3.18.0-rc5-00119-geefd097-dirty #1540
 [   37.796142] task: 8e246c00 ti: 8ca6c000 task.ti: 8ca6c000
 [   37.801785] PC is at esdhc_writel_le+0x40/0xec
 [   37.806431] LR is at sdhci_set_card_detection+0xe0/0xe4
 [   37.811877] pc : [803f0584]lr : [803eaaa0]psr: 400f0013
 [   37.811877] sp : 8ca6dd28  ip : 0001  fp : 8ca6dd3c
 [   37.823766] r10: 807a233c  r9 :   r8 : 8e8b7210
 [   37.829194] r7 : 802d8a08  r6 : 8082e928  r5 :   r4 : 0002
 [   37.835974] r3 : 8ea34e90  r2 : 0038  r1 :   r0 : 8ea32ac0
 ...
 
 Clocks need to be enabled to access the registers. Fix the issue by
 add runtime PM enabled pltfm implementation of suspend/resume which
 take care of clocks by using the runtime PM API properly.
 
 Signed-off-by: Stefan Agner ste...@agner.ch
 ---
 Changes since v2:
 - Implement a generic pltfm suspend/resume function instead of a local
   function in sdhci-esdhc-imx.c
 - Convert sdhci-pxav3 to use the runtime PM enabled pltfm suspend/resume
   function too
 
  drivers/mmc/host/sdhci-esdhc-imx.c |  2 +-
  drivers/mmc/host/sdhci-pltfm.c | 36 
  drivers/mmc/host/sdhci-pltfm.h |  2 ++
  3 files changed, 39 insertions(+), 1 deletion(-)
 
 diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c
 b/drivers/mmc/host/sdhci-esdhc-imx.c
 index 82f512d..7b7b3a3 100644
 --- a/drivers/mmc/host/sdhci-esdhc-imx.c
 +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
 @@ -1132,7 +1132,7 @@ static int sdhci_esdhc_runtime_resume(struct device 
 *dev)
  #endif
  
  static const struct dev_pm_ops sdhci_esdhc_pmops = {
 - SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_pltfm_resume)
 + SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_rpm_suspend, sdhci_pltfm_rpm_resume)
   SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend,
   sdhci_esdhc_runtime_resume, NULL)
  };
 diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
 index a207f5a..38c03cd 100644
 --- a/drivers/mmc/host/sdhci-pltfm.c
 +++ b/drivers/mmc/host/sdhci-pltfm.c
 @@ -31,6 +31,7 @@
  #include linux/err.h
  #include linux/module.h
  #include linux/of.h
 +#include linux/pm_runtime.h
  #ifdef CONFIG_PPC
  #include asm/machdep.h
  #endif
 @@ -256,6 +257,41 @@ const struct dev_pm_ops sdhci_pltfm_pmops = {
   .resume = sdhci_pltfm_resume,
  };
  EXPORT_SYMBOL_GPL(sdhci_pltfm_pmops);
 +
 +int sdhci_pltfm_rpm_suspend(struct device *dev)
 +{
 + int ret;
 + struct sdhci_host *host = dev_get_drvdata(dev);
 +
 + pm_runtime_get_sync(dev);
 + ret = sdhci_suspend_host(host);
 + pm_runtime_mark_last_busy(dev);
 + pm_runtime_put_autosuspend(dev);
 + if (ret)
 + return ret;
 +
 + return pm_runtime_force_suspend(dev);
 +}
 +EXPORT_SYMBOL_GPL(sdhci_pltfm_rpm_suspend);
 +
 +int sdhci_pltfm_rpm_resume(struct device *dev)
 +{
 + int ret;
 + struct sdhci_host *host = dev_get_drvdata(dev);
 +
 + ret = pm_runtime_force_resume(dev);
 +
 + if (ret)
 + return ret;
 +
 + pm_runtime_get_sync(dev);
 + ret = sdhci_resume_host(host);
 + pm_runtime_mark_last_busy(dev);
 + pm_runtime_put_autosuspend(dev);
 +
 + return ret;
 +}
 +EXPORT_SYMBOL_GPL(sdhci_pltfm_rpm_resume);
  #endif   /* CONFIG_PM */
  
  static int __init sdhci_pltfm_drv_init(void)
 diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h
 index 04bc248..ac5f6ea 100644
 --- a/drivers/mmc/host/sdhci-pltfm.h
 +++ b/drivers/mmc/host/sdhci-pltfm.h
 @@ -114,6 +114,8 @@ static inline void *sdhci_pltfm_priv(struct
 sdhci_pltfm_host *host)
  extern int sdhci_pltfm_suspend(struct device *dev);
  extern int sdhci_pltfm_resume(struct device *dev);
  extern const struct dev_pm_ops sdhci_pltfm_pmops;
 +extern int sdhci_pltfm_rpm_suspend(struct device *dev);
 +extern int sdhci_pltfm_rpm_resume(struct device *dev);
  #define SDHCI_PLTFM_PMOPS (sdhci_pltfm_pmops)
  #else
  #define SDHCI_PLTFM_PMOPS NULL

--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 1/2] mmc: sdhci: fix abort due to missing runtime PM

2015-05-27 Thread Dong Aisheng
On Thu, May 21, 2015 at 09:15:03AM +0200, Stefan Agner wrote:
 When using i.MX ESDHC driver, while entering suspend while the device
 is in runtime PM, the sdhci_(suspend|resume)_host function are called
 with disabled clocks. Since this functions access the SDHC host
 registers, this leads to an external abort on Vybrid SoC:
 
 [   37.772967] Unhandled fault: imprecise external abort (0x1c06) at 
 0x76f5f000
 [   37.780304] Internal error: : 1c06 [#1] ARM
 [   37.784670] Modules linked in:
 [   37.787908] CPU: 0 PID: 428 Comm: sh Not tainted 
 3.18.0-rc5-00119-geefd097-dirty #1540
 [   37.796142] task: 8e246c00 ti: 8ca6c000 task.ti: 8ca6c000
 [   37.801785] PC is at esdhc_writel_le+0x40/0xec
 [   37.806431] LR is at sdhci_set_card_detection+0xe0/0xe4
 [   37.811877] pc : [803f0584]lr : [803eaaa0]psr: 400f0013
 [   37.811877] sp : 8ca6dd28  ip : 0001  fp : 8ca6dd3c
 [   37.823766] r10: 807a233c  r9 :   r8 : 8e8b7210
 [   37.829194] r7 : 802d8a08  r6 : 8082e928  r5 :   r4 : 0002
 [   37.835974] r3 : 8ea34e90  r2 : 0038  r1 :   r0 : 8ea32ac0
 ...
 
 Clocks need to be enabled to access the registers. Fix the issue by
 add runtime PM enabled pltfm implementation of suspend/resume which
 take care of clocks by using the runtime PM API properly.
 
 Signed-off-by: Stefan Agner ste...@agner.ch
 ---
 Changes since v2:
 - Implement a generic pltfm suspend/resume function instead of a local
   function in sdhci-esdhc-imx.c
 - Convert sdhci-pxav3 to use the runtime PM enabled pltfm suspend/resume
   function too
 
  drivers/mmc/host/sdhci-esdhc-imx.c |  2 +-
  drivers/mmc/host/sdhci-pltfm.c | 36 
  drivers/mmc/host/sdhci-pltfm.h |  2 ++
  3 files changed, 39 insertions(+), 1 deletion(-)
 
 diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c 
 b/drivers/mmc/host/sdhci-esdhc-imx.c
 index 82f512d..7b7b3a3 100644
 --- a/drivers/mmc/host/sdhci-esdhc-imx.c
 +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
 @@ -1132,7 +1132,7 @@ static int sdhci_esdhc_runtime_resume(struct device 
 *dev)
  #endif
  
  static const struct dev_pm_ops sdhci_esdhc_pmops = {
 - SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_pltfm_resume)
 + SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_rpm_suspend, sdhci_pltfm_rpm_resume)
   SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend,
   sdhci_esdhc_runtime_resume, NULL)
  };
 diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
 index a207f5a..38c03cd 100644
 --- a/drivers/mmc/host/sdhci-pltfm.c
 +++ b/drivers/mmc/host/sdhci-pltfm.c
 @@ -31,6 +31,7 @@
  #include linux/err.h
  #include linux/module.h
  #include linux/of.h
 +#include linux/pm_runtime.h
  #ifdef CONFIG_PPC
  #include asm/machdep.h
  #endif
 @@ -256,6 +257,41 @@ const struct dev_pm_ops sdhci_pltfm_pmops = {
   .resume = sdhci_pltfm_resume,
  };
  EXPORT_SYMBOL_GPL(sdhci_pltfm_pmops);
 +
 +int sdhci_pltfm_rpm_suspend(struct device *dev)

Why invent a new API?
Can't put into sdhci_pltfm_suspend?

Regards
Dong Aisheng

 +{
 + int ret;
 + struct sdhci_host *host = dev_get_drvdata(dev);
 +
 + pm_runtime_get_sync(dev);
 + ret = sdhci_suspend_host(host);
 + pm_runtime_mark_last_busy(dev);
 + pm_runtime_put_autosuspend(dev);
 + if (ret)
 + return ret;
 +
 + return pm_runtime_force_suspend(dev);
 +}
 +EXPORT_SYMBOL_GPL(sdhci_pltfm_rpm_suspend);
 +
 +int sdhci_pltfm_rpm_resume(struct device *dev)
 +{
 + int ret;
 + struct sdhci_host *host = dev_get_drvdata(dev);
 +
 + ret = pm_runtime_force_resume(dev);
 +
 + if (ret)
 + return ret;
 +
 + pm_runtime_get_sync(dev);
 + ret = sdhci_resume_host(host);
 + pm_runtime_mark_last_busy(dev);
 + pm_runtime_put_autosuspend(dev);
 +
 + return ret;
 +}
 +EXPORT_SYMBOL_GPL(sdhci_pltfm_rpm_resume);
  #endif   /* CONFIG_PM */
  
  static int __init sdhci_pltfm_drv_init(void)
 diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h
 index 04bc248..ac5f6ea 100644
 --- a/drivers/mmc/host/sdhci-pltfm.h
 +++ b/drivers/mmc/host/sdhci-pltfm.h
 @@ -114,6 +114,8 @@ static inline void *sdhci_pltfm_priv(struct 
 sdhci_pltfm_host *host)
  extern int sdhci_pltfm_suspend(struct device *dev);
  extern int sdhci_pltfm_resume(struct device *dev);
  extern const struct dev_pm_ops sdhci_pltfm_pmops;
 +extern int sdhci_pltfm_rpm_suspend(struct device *dev);
 +extern int sdhci_pltfm_rpm_resume(struct device *dev);
  #define SDHCI_PLTFM_PMOPS (sdhci_pltfm_pmops)
  #else
  #define SDHCI_PLTFM_PMOPS NULL
 -- 
 2.4.1
 
--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 1/2] mmc: sdhci: fix abort due to missing runtime PM

2015-05-27 Thread Stefan Agner
On 2015-05-27 12:05, Dong Aisheng wrote:
snip
 diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c 
 b/drivers/mmc/host/sdhci-esdhc-imx.c
 index 82f512d..7b7b3a3 100644
 --- a/drivers/mmc/host/sdhci-esdhc-imx.c
 +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
 @@ -1132,7 +1132,7 @@ static int sdhci_esdhc_runtime_resume(struct device 
 *dev)
  #endif

  static const struct dev_pm_ops sdhci_esdhc_pmops = {
 -SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_pltfm_resume)
 +SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_rpm_suspend, sdhci_pltfm_rpm_resume)
  SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend,
  sdhci_esdhc_runtime_resume, NULL)
  };
 diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
 index a207f5a..38c03cd 100644
 --- a/drivers/mmc/host/sdhci-pltfm.c
 +++ b/drivers/mmc/host/sdhci-pltfm.c
 @@ -31,6 +31,7 @@
  #include linux/err.h
  #include linux/module.h
  #include linux/of.h
 +#include linux/pm_runtime.h
  #ifdef CONFIG_PPC
  #include asm/machdep.h
  #endif
 @@ -256,6 +257,41 @@ const struct dev_pm_ops sdhci_pltfm_pmops = {
  .resume = sdhci_pltfm_resume,
  };
  EXPORT_SYMBOL_GPL(sdhci_pltfm_pmops);
 +
 +int sdhci_pltfm_rpm_suspend(struct device *dev)
 
 Why invent a new API?
 Can't put into sdhci_pltfm_suspend?

There are several drivers making use of the API without runtime PM
support. Afaik, you can't call the pm_runtime functions without having
runtime PM support, at least pm_runtime_force_suspend seems to return an
error when runtime_suspend callback is not there... Maybe I'm wrong on
that?

--
Stefan

 
 Regards
 Dong Aisheng
 
 +{
 +int ret;
 +struct sdhci_host *host = dev_get_drvdata(dev);
 +
 +pm_runtime_get_sync(dev);
 +ret = sdhci_suspend_host(host);
 +pm_runtime_mark_last_busy(dev);
 +pm_runtime_put_autosuspend(dev);
 +if (ret)
 +return ret;
 +
 +return pm_runtime_force_suspend(dev);
 +}
 +EXPORT_SYMBOL_GPL(sdhci_pltfm_rpm_suspend);
 +
 +int sdhci_pltfm_rpm_resume(struct device *dev)
 +{
 +int ret;
 +struct sdhci_host *host = dev_get_drvdata(dev);
 +
 +ret = pm_runtime_force_resume(dev);
 +
 +if (ret)
 +return ret;
 +
 +pm_runtime_get_sync(dev);
 +ret = sdhci_resume_host(host);
 +pm_runtime_mark_last_busy(dev);
 +pm_runtime_put_autosuspend(dev);
 +
 +return ret;
 +}
 +EXPORT_SYMBOL_GPL(sdhci_pltfm_rpm_resume);
  #endif  /* CONFIG_PM */

  static int __init sdhci_pltfm_drv_init(void)
 diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h
 index 04bc248..ac5f6ea 100644
 --- a/drivers/mmc/host/sdhci-pltfm.h
 +++ b/drivers/mmc/host/sdhci-pltfm.h
 @@ -114,6 +114,8 @@ static inline void *sdhci_pltfm_priv(struct 
 sdhci_pltfm_host *host)
  extern int sdhci_pltfm_suspend(struct device *dev);
  extern int sdhci_pltfm_resume(struct device *dev);
  extern const struct dev_pm_ops sdhci_pltfm_pmops;
 +extern int sdhci_pltfm_rpm_suspend(struct device *dev);
 +extern int sdhci_pltfm_rpm_resume(struct device *dev);
  #define SDHCI_PLTFM_PMOPS (sdhci_pltfm_pmops)
  #else
  #define SDHCI_PLTFM_PMOPS NULL
 --
 2.4.1


--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 1/2] mmc: sdhci: fix abort due to missing runtime PM

2015-05-21 Thread Stefan Agner
When using i.MX ESDHC driver, while entering suspend while the device
is in runtime PM, the sdhci_(suspend|resume)_host function are called
with disabled clocks. Since this functions access the SDHC host
registers, this leads to an external abort on Vybrid SoC:

[   37.772967] Unhandled fault: imprecise external abort (0x1c06) at 0x76f5f000
[   37.780304] Internal error: : 1c06 [#1] ARM
[   37.784670] Modules linked in:
[   37.787908] CPU: 0 PID: 428 Comm: sh Not tainted 
3.18.0-rc5-00119-geefd097-dirty #1540
[   37.796142] task: 8e246c00 ti: 8ca6c000 task.ti: 8ca6c000
[   37.801785] PC is at esdhc_writel_le+0x40/0xec
[   37.806431] LR is at sdhci_set_card_detection+0xe0/0xe4
[   37.811877] pc : [803f0584]lr : [803eaaa0]psr: 400f0013
[   37.811877] sp : 8ca6dd28  ip : 0001  fp : 8ca6dd3c
[   37.823766] r10: 807a233c  r9 :   r8 : 8e8b7210
[   37.829194] r7 : 802d8a08  r6 : 8082e928  r5 :   r4 : 0002
[   37.835974] r3 : 8ea34e90  r2 : 0038  r1 :   r0 : 8ea32ac0
...

Clocks need to be enabled to access the registers. Fix the issue by
add runtime PM enabled pltfm implementation of suspend/resume which
take care of clocks by using the runtime PM API properly.

Signed-off-by: Stefan Agner ste...@agner.ch
---
Changes since v2:
- Implement a generic pltfm suspend/resume function instead of a local
  function in sdhci-esdhc-imx.c
- Convert sdhci-pxav3 to use the runtime PM enabled pltfm suspend/resume
  function too

 drivers/mmc/host/sdhci-esdhc-imx.c |  2 +-
 drivers/mmc/host/sdhci-pltfm.c | 36 
 drivers/mmc/host/sdhci-pltfm.h |  2 ++
 3 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c 
b/drivers/mmc/host/sdhci-esdhc-imx.c
index 82f512d..7b7b3a3 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1132,7 +1132,7 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
 #endif
 
 static const struct dev_pm_ops sdhci_esdhc_pmops = {
-   SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_pltfm_resume)
+   SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_rpm_suspend, sdhci_pltfm_rpm_resume)
SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend,
sdhci_esdhc_runtime_resume, NULL)
 };
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index a207f5a..38c03cd 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -31,6 +31,7 @@
 #include linux/err.h
 #include linux/module.h
 #include linux/of.h
+#include linux/pm_runtime.h
 #ifdef CONFIG_PPC
 #include asm/machdep.h
 #endif
@@ -256,6 +257,41 @@ const struct dev_pm_ops sdhci_pltfm_pmops = {
.resume = sdhci_pltfm_resume,
 };
 EXPORT_SYMBOL_GPL(sdhci_pltfm_pmops);
+
+int sdhci_pltfm_rpm_suspend(struct device *dev)
+{
+   int ret;
+   struct sdhci_host *host = dev_get_drvdata(dev);
+
+   pm_runtime_get_sync(dev);
+   ret = sdhci_suspend_host(host);
+   pm_runtime_mark_last_busy(dev);
+   pm_runtime_put_autosuspend(dev);
+   if (ret)
+   return ret;
+
+   return pm_runtime_force_suspend(dev);
+}
+EXPORT_SYMBOL_GPL(sdhci_pltfm_rpm_suspend);
+
+int sdhci_pltfm_rpm_resume(struct device *dev)
+{
+   int ret;
+   struct sdhci_host *host = dev_get_drvdata(dev);
+
+   ret = pm_runtime_force_resume(dev);
+
+   if (ret)
+   return ret;
+
+   pm_runtime_get_sync(dev);
+   ret = sdhci_resume_host(host);
+   pm_runtime_mark_last_busy(dev);
+   pm_runtime_put_autosuspend(dev);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(sdhci_pltfm_rpm_resume);
 #endif /* CONFIG_PM */
 
 static int __init sdhci_pltfm_drv_init(void)
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h
index 04bc248..ac5f6ea 100644
--- a/drivers/mmc/host/sdhci-pltfm.h
+++ b/drivers/mmc/host/sdhci-pltfm.h
@@ -114,6 +114,8 @@ static inline void *sdhci_pltfm_priv(struct 
sdhci_pltfm_host *host)
 extern int sdhci_pltfm_suspend(struct device *dev);
 extern int sdhci_pltfm_resume(struct device *dev);
 extern const struct dev_pm_ops sdhci_pltfm_pmops;
+extern int sdhci_pltfm_rpm_suspend(struct device *dev);
+extern int sdhci_pltfm_rpm_resume(struct device *dev);
 #define SDHCI_PLTFM_PMOPS (sdhci_pltfm_pmops)
 #else
 #define SDHCI_PLTFM_PMOPS NULL
-- 
2.4.1

--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html