[PATCH v11 6/6] mmc: core: Add support for resetting an eMMC at system resume
From: Kamal Dasu
Date: Fri Oct 30 2026 - 14:12:59 EST
From: Ulf Hansson <ulf.hansson@xxxxxxxxxxxxxxxx>
The DT property reset-card-at-resume specifies that we need to make a reset
of an eMMC card at system resume, assuming it also has stayed powered on
during system suspend.
To implement support for this, let's start by parsing for the new DT
property and set the new bit MMC_CAP2_RESET_AT_RESUME if it's found. Based
on the property, we must also set MMC_PM_KEEP_POWER in the pm_flags for the
host, to keep the eMMC powered on during system suspend.
Finally, to manage the actual reset during system resume, let's extend
mmc_resume() to support the needed behaviour.
The property only makes sense together with keep-power-in-suspend, as the
card would otherwise be powered off and system suspend is refused. Warn
about that while parsing the DT properties, to flag the misconfiguration
upfront. While at it, claim the host around the reset in mmc_resume(), as
it sends commands to the card.
Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxxxxxxxx>
Co-developed-by: Kamal Dasu <kamal.dasu@xxxxxxxxxxxx>
Signed-off-by: Kamal Dasu <kamal.dasu@xxxxxxxxxxxx>
---
drivers/mmc/core/host.c | 13 +++++++++++++
drivers/mmc/core/mmc.c | 8 ++++++++
include/linux/mmc/host.h | 1 +
3 files changed, 22 insertions(+)
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 8e9e61839198..8b38ff45d20f 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -48,6 +48,14 @@ static int mmc_host_class_prepare(struct device *dev)
if (host->bus_ops->pre_suspend)
return host->bus_ops->pre_suspend(host);
+ /*
+ * If it's required to make a reset of the card at system resume, this
+ * indirectly also means that we must keep the card powered on during
+ * system suspend.
+ */
+ if (host->caps2 & MMC_CAP2_RESET_AT_RESUME)
+ return mmc_set_host_pm_flags(host, MMC_PM_KEEP_POWER);
+
return 0;
}
@@ -375,6 +383,11 @@ int mmc_of_parse(struct mmc_host *host)
host->pm_caps |= MMC_PM_KEEP_POWER;
if (device_property_read_bool(dev, "wakeup-source"))
host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
+ if (device_property_read_bool(dev, "reset-card-at-resume")) {
+ host->caps2 |= MMC_CAP2_RESET_AT_RESUME;
+ if (!(host->pm_caps & MMC_PM_KEEP_POWER))
+ dev_warn(dev, "reset-card-at-resume without keep-power-in-suspend, system suspend will fail\n");
+ }
if (device_property_read_bool(dev, "mmc-ddr-3_3v"))
host->caps |= MMC_CAP_3_3V_DDR;
if (device_property_read_bool(dev, "mmc-ddr-1_8v"))
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 026003ba507d..a9e3cf7ae039 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -2320,6 +2320,14 @@ static int mmc_resume(struct mmc_host *host)
}
pm_runtime_enable(&host->card->dev);
+
+ if (mmc_card_keep_power(host) &&
+ host->caps2 & MMC_CAP2_RESET_AT_RESUME) {
+ mmc_claim_host(host);
+ _mmc_hw_reset(host);
+ mmc_release_host(host);
+ }
+
host->pm_flags &= ~MMC_PM_KEEP_POWER;
return 0;
}
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 032c018650e0..3c0ea74e3e35 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -430,6 +430,7 @@ struct mmc_host {
u32 caps2; /* More host capabilities */
#define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */
+#define MMC_CAP2_RESET_AT_RESUME BIT(1) /* Reset the card at system resume */
#define MMC_CAP2_FULL_PWR_CYCLE (1 << 2) /* Can do full power cycle */
#define MMC_CAP2_FULL_PWR_CYCLE_IN_SUSPEND (1 << 3) /* Can do full power cycle in suspend */
#define MMC_CAP2_HS200_1_8V_SDR (1 << 5) /* can support */
--
2.34.1