Re: [PATCH V4] mmc: sdhci-msm: Update system suspend/resume callbacks of sdhci-msm platform driver
From: Ulf Hansson <hidden>
Date: 2020-03-04 15:35:12
Also in:
linux-arm-msm, linux-mmc, lkml
On Thu, 20 Feb 2020 at 07:45, Shaik Sajida Bhanu [off-list ref] wrote:
quoted hunk ↗ jump to hunk
The existing suspend/resume callbacks of sdhci-msm driver are just gating/un-gating the clocks. During suspend cycle more can be done like disabling controller, disabling card detection, enabling wake-up events. So updating the system pm callbacks for performing these extra actions besides controlling the clocks. Signed-off-by: Shaik Sajida Bhanu <redacted> Reviewed-by: Stephen Boyd <redacted> --- Changes since V3: Invoking sdhci & cqhci resume if sdhci_host_suspend fails. Removed condition check before invoking cqhci_resume since its a dummy function. Changes since V2: Removed disabling/enabling pwr-irq from system pm ops. Changes since V1: Invoking pm_runtime_force_suspend/resume instead of sdhci_msm_runtime_suepend/resume. --- drivers/mmc/host/sdhci-msm.c | 47 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-)diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 3955fa5d..3559b50 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c@@ -2159,9 +2159,52 @@ static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev) return 0; } +static int sdhci_msm_suspend(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + int ret; + + if (host->mmc->caps2 & MMC_CAP2_CQE) { + ret = cqhci_suspend(host->mmc); + if (ret) + return ret; + } + + ret = sdhci_suspend_host(host); + if (ret) + goto resume_cqhci;
sdhci_suspend_host() can't be called on a device that has been runtime suspended, as that would lead to accessing device registers when clocks/PM domains are gated. Depending on how the corresponding cqhci device is managed from a runtime PM point of view, it could also be problematic to call cqhci_suspend().
+ + ret = pm_runtime_force_suspend(dev);
It looks to me that perhaps you could make use of solely pm_runtime_force_suspend(), then just skip calling sdhci_suspend|resume_host() altogether. Do you think that could work? And vice versa for sdhci_msm_resume(), of course.
+ if (!ret)
+ return ret;
+
+ sdhci_resume_host(host);
+
+resume_cqhci:
+ cqhci_resume(host->mmc);
+ return ret;
+}
+
+static int sdhci_msm_resume(struct device *dev)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+ int ret;
+
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ ret = sdhci_resume_host(host);
+ if (ret < 0)
+ return ret;
+
+ ret = cqhci_resume(host->mmc);
+ return ret;
+}
+
static const struct dev_pm_ops sdhci_msm_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ SET_SYSTEM_SLEEP_PM_OPS(sdhci_msm_suspend,
+ sdhci_msm_resume)
SET_RUNTIME_PM_OPS(sdhci_msm_runtime_suspend,
sdhci_msm_runtime_resume,
NULL)
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux FoundationKind regards Uffe