[PATCH v23 11/14] mmc: renesas_sdhi: Save and restore IOVS across suspend/resume
Biju <[email protected]> Thu, 30 Jul 2026 12:31:49 +0100
| Newsgroups | org.kernel.vger.linux-mmc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-renesas-soc |
|---|---|
| Message-ID | <[email protected]> |
From: Biju Das <[email protected]> The SD_STATUS register, specifically the IOVS (I/O Voltage Switch) bit, is not automatically restored after a suspend/resume cycle, causing the regulator to report an incorrect voltage on resume. Fix this by caching the CTL_SD_STATUS register value in the renesas_sdhi private struct at suspend time and writing it back during resume. The save/restore is only performed when a regulator device (rdev) is present, as the IOVS bit is only relevant in that context. Signed-off-by: Biju Das <[email protected]> --- v22->v23: * No change. v21->v22: * No change. v20->v21: * No change. v19->v20: * Updated resume() with scoped PM runtime call. v18->v19: * Updated suspend/resume with scoped runtime calls in suspend. v17->v18: * No change. v1->v17: * No change. --- drivers/mmc/host/renesas_sdhi.h | 2 ++ drivers/mmc/host/renesas_sdhi_core.c | 26 +++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h index 3b140cd4ee0c..3e08b099ee87 100644 --- a/drivers/mmc/host/renesas_sdhi.h +++ b/drivers/mmc/host/renesas_sdhi.h @@ -105,6 +105,8 @@ struct renesas_sdhi { struct reset_control *rstc_axim; struct tmio_mmc_host *host; struct regulator_dev *rdev; + + u32 cache_sd_status; }; #define host_to_priv(host) \ diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 65002e6ebf9b..3459df084a02 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -1434,6 +1434,15 @@ int renesas_sdhi_suspend(struct device *dev) }; int ret; + if (priv->rdev) { + PM_RUNTIME_ACQUIRE_IF_ENABLED(dev, pm); + ret = PM_RUNTIME_ACQUIRE_ERR(&pm); + if (ret < 0) + return ret; + + priv->cache_sd_status = sd_ctrl_read32(host, CTL_SD_STATUS); + } + ret = pm_runtime_force_suspend(dev); if (ret) return ret; @@ -1463,8 +1472,23 @@ int renesas_sdhi_resume(struct device *dev) ret = pm_runtime_force_resume(dev); if (ret) - reset_control_bulk_assert(ARRAY_SIZE(resets), resets); + goto err_assert; + + if (priv->rdev) { + PM_RUNTIME_ACQUIRE_IF_ENABLED(dev, pm); + ret = PM_RUNTIME_ACQUIRE_ERR(&pm); + if (ret < 0) + goto err_pm; + + sd_ctrl_write32(host, CTL_SD_STATUS, priv->cache_sd_status); + } + + return 0; +err_pm: + pm_runtime_force_suspend(dev); +err_assert: + reset_control_bulk_assert(ARRAY_SIZE(resets), resets); return ret; } EXPORT_SYMBOL_GPL(renesas_sdhi_resume); -- 2.43.0