public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] mmc: sdhci-of-dwcmshc: add reset control support in suspend/resume
@ 2026-04-15 12:34 Artem Shimko
  2026-04-15 14:51 ` Andy Shevchenko
  0 siblings, 1 reply; 3+ messages in thread
From: Artem Shimko @ 2026-04-15 12:34 UTC (permalink / raw)
  To: andriy.shevchenko, Jisheng.Zhang, hehuan1, yifeng.zhao,
	Adrian Hunter, Ulf Hansson, Philipp Zabel
  Cc: Artem Shimko, linux-mmc, linux-kernel

The driver currently handles reset control only during initializations,
but does not manage the controller reset signal during system
suspend/resume. This can leave the hardware in an undefined state
after resume. Additionally, the reset control is stored in vendor
structs making it inaccessible for power management operations.

Move the reset control to dwcmshc_priv structure and add proper
assertion during suspend and deassertion during resume. This ensures the
controller is properly reset before entering low power state and correctly
reinitialized upon wake.

Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com>
---

Hello maintainers and reviewers,

This patch adds reset control support for the MMC controller
during system suspend/resume.

Currently, the reset control is only handled during initialization and
is stored in vendor-specific private structures. This makes it
inaccessible to the common power management code and leaves the
controller in an undefined state after resume.

The changes move the reset control to the generic dwcmshc_priv structure,
update all platform-specific users (Rockchip, EIC7700), and add proper
reset assertion/deassertion in dwcmshc_suspend/resume.

Kindly, please review.

Many thanks.

--
Regards,
Artem

 drivers/mmc/host/sdhci-of-dwcmshc.c | 43 +++++++++++++++++------------
 1 file changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
index 2b75a36c096b..aca176d2c809 100644
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
@@ -258,13 +258,11 @@ enum dwcmshc_rk_type {
 };
 
 struct rk35xx_priv {
-	struct reset_control *reset;
 	enum dwcmshc_rk_type devtype;
 	u8 txclk_tapnum;
 };
 
 struct eic7700_priv {
-	struct reset_control *reset;
 	unsigned int drive_impedance;
 };
 
@@ -272,6 +270,7 @@ struct eic7700_priv {
 
 struct dwcmshc_priv {
 	struct clk	*bus_clk;
+	struct reset_control *reset;
 	int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA1 reg */
 	int vendor_specific_area2; /* P_VENDOR_SPECIFIC_AREA2 reg */
 
@@ -829,16 +828,15 @@ static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
-	struct rk35xx_priv *priv = dwc_priv->priv;
 	u32 extra = sdhci_readl(host, DECMSHC_EMMC_MISC_CON);
 
 	if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL))
 		cqhci_deactivate(host->mmc);
 
-	if (mask & SDHCI_RESET_ALL && priv->reset) {
-		reset_control_assert(priv->reset);
+	if (mask & SDHCI_RESET_ALL && dwc_priv->reset) {
+		reset_control_assert(dwc_priv->reset);
 		udelay(1);
-		reset_control_deassert(priv->reset);
+		reset_control_deassert(dwc_priv->reset);
 	}
 
 	sdhci_reset(host, mask);
@@ -863,9 +861,9 @@ static int dwcmshc_rk35xx_init(struct device *dev, struct sdhci_host *host,
 	else
 		priv->devtype = DWCMSHC_RK3568;
 
-	priv->reset = devm_reset_control_array_get_optional_exclusive(mmc_dev(host->mmc));
-	if (IS_ERR(priv->reset)) {
-		err = PTR_ERR(priv->reset);
+	dwc_priv->reset = devm_reset_control_array_get_optional_exclusive(mmc_dev(host->mmc));
+	if (IS_ERR(dwc_priv->reset)) {
+		err = PTR_ERR(dwc_priv->reset);
 		dev_err(mmc_dev(host->mmc), "failed to get reset control %d\n", err);
 		return err;
 	}
@@ -1331,24 +1329,24 @@ static void sdhci_eic7700_reset(struct sdhci_host *host, u8 mask)
 		sdhci_eic7700_config_phy(host);
 }
 
-static int sdhci_eic7700_reset_init(struct device *dev, struct eic7700_priv *priv)
+static int sdhci_eic7700_reset_init(struct device *dev, struct dwcmshc_priv *dwc_priv)
 {
 	int ret;
 
-	priv->reset = devm_reset_control_array_get_optional_exclusive(dev);
-	if (IS_ERR(priv->reset)) {
-		ret = PTR_ERR(priv->reset);
+	dwc_priv->reset = devm_reset_control_array_get_optional_exclusive(dev);
+	if (IS_ERR(dwc_priv->reset)) {
+		ret = PTR_ERR(dwc_priv->reset);
 		dev_err(dev, "failed to get reset control %d\n", ret);
 		return ret;
 	}
 
-	ret = reset_control_assert(priv->reset);
+	ret = reset_control_assert(dwc_priv->reset);
 	if (ret) {
 		dev_err(dev, "Failed to assert reset signals: %d\n", ret);
 		return ret;
 	}
 	usleep_range(2000, 2100);
-	ret = reset_control_deassert(priv->reset);
+	ret = reset_control_deassert(dwc_priv->reset);
 	if (ret) {
 		dev_err(dev, "Failed to deassert reset signals: %d\n", ret);
 		return ret;
@@ -1607,7 +1605,7 @@ static int eic7700_init(struct device *dev, struct sdhci_host *host, struct dwcm
 
 	dwc_priv->priv = priv;
 
-	ret = sdhci_eic7700_reset_init(dev, dwc_priv->priv);
+	ret = sdhci_eic7700_reset_init(dev, dwc_priv);
 	if (ret) {
 		dev_err(dev, "failed to reset\n");
 		return ret;
@@ -2122,6 +2120,8 @@ static int dwcmshc_suspend(struct device *dev)
 	if (ret)
 		return ret;
 
+	reset_control_assert(priv->reset);
+
 	clk_disable_unprepare(pltfm_host->clk);
 	if (!IS_ERR(priv->bus_clk))
 		clk_disable_unprepare(priv->bus_clk);
@@ -2152,18 +2152,25 @@ static int dwcmshc_resume(struct device *dev)
 	if (ret)
 		goto disable_bus_clk;
 
-	ret = sdhci_resume_host(host);
+	ret = reset_control_deassert(priv->reset);
 	if (ret)
 		goto disable_other_clks;
 
+
+	ret = sdhci_resume_host(host);
+	if (ret)
+		goto assert_reset;
+
 	if (host->mmc->caps2 & MMC_CAP2_CQE) {
 		ret = cqhci_resume(host->mmc);
 		if (ret)
-			goto disable_other_clks;
+			goto assert_reset;
 	}
 
 	return 0;
 
+assert_reset:
+	reset_control_assert(priv->reset);
 disable_other_clks:
 	clk_bulk_disable_unprepare(priv->num_other_clks, priv->other_clks);
 disable_bus_clk:
-- 
2.43.0


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

end of thread, other threads:[~2026-04-17 10:45 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-15 12:34 [PATCH] mmc: sdhci-of-dwcmshc: add reset control support in suspend/resume Artem Shimko
2026-04-15 14:51 ` Andy Shevchenko
2026-04-17 10:45   ` Artem Shimko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox