Skip to content

Commit 904a97f

Browse files
Sai Krishna Potthurigregkh
authored andcommitted
mmc: sdhci-of-arasan: Ensure CD logic stabilization before power-up
commit e251709 upstream. During SD suspend/resume without a full card rescan (when using non-removable SD cards for rootfs), the SD card initialization may fail after resume. This occurs because, after a host controller reset, the card detect logic may take time to stabilize due to debounce logic. Without waiting for stabilization, the host may attempt powering up the card prematurely, leading to command timeouts during resume flow. Add sdhci_arasan_set_power_and_bus_voltage() to wait for the card detect stable bit before power up the card. Since the stabilization time is not fixed, a maximum timeout of one second is used to ensure sufficient wait time for the card detect signal to stabilize. Signed-off-by: Sai Krishna Potthuri <sai.krishna.potthuri@amd.com> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250730060543.1735971-1-sai.krishna.potthuri@amd.com Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent f9045bb commit 904a97f

File tree

1 file changed

+31
-2
lines changed

1 file changed

+31
-2
lines changed

drivers/mmc/host/sdhci-of-arasan.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@
9999
#define HIWORD_UPDATE(val, mask, shift) \
100100
((val) << (shift) | (mask) << ((shift) + 16))
101101

102+
#define CD_STABLE_TIMEOUT_US 1000000
103+
#define CD_STABLE_MAX_SLEEP_US 10
104+
102105
/**
103106
* struct sdhci_arasan_soc_ctl_field - Field used in sdhci_arasan_soc_ctl_map
104107
*
@@ -206,12 +209,15 @@ struct sdhci_arasan_data {
206209
* 19MHz instead
207210
*/
208211
#define SDHCI_ARASAN_QUIRK_CLOCK_25_BROKEN BIT(2)
212+
/* Enable CD stable check before power-up */
213+
#define SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE BIT(3)
209214
};
210215

211216
struct sdhci_arasan_of_data {
212217
const struct sdhci_arasan_soc_ctl_map *soc_ctl_map;
213218
const struct sdhci_pltfm_data *pdata;
214219
const struct sdhci_arasan_clk_ops *clk_ops;
220+
u32 quirks;
215221
};
216222

217223
static const struct sdhci_arasan_soc_ctl_map rk3399_soc_ctl_map = {
@@ -514,14 +520,32 @@ static int sdhci_arasan_voltage_switch(struct mmc_host *mmc,
514520
return -EINVAL;
515521
}
516522

523+
static void sdhci_arasan_set_power_and_bus_voltage(struct sdhci_host *host, unsigned char mode,
524+
unsigned short vdd)
525+
{
526+
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
527+
struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
528+
u32 reg;
529+
530+
/*
531+
* Ensure that the card detect logic has stabilized before powering up, this is
532+
* necessary after a host controller reset.
533+
*/
534+
if (mode == MMC_POWER_UP && sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE)
535+
read_poll_timeout(sdhci_readl, reg, reg & SDHCI_CD_STABLE, CD_STABLE_MAX_SLEEP_US,
536+
CD_STABLE_TIMEOUT_US, false, host, SDHCI_PRESENT_STATE);
537+
538+
sdhci_set_power_and_bus_voltage(host, mode, vdd);
539+
}
540+
517541
static const struct sdhci_ops sdhci_arasan_ops = {
518542
.set_clock = sdhci_arasan_set_clock,
519543
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
520544
.get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
521545
.set_bus_width = sdhci_set_bus_width,
522546
.reset = sdhci_arasan_reset,
523547
.set_uhs_signaling = sdhci_set_uhs_signaling,
524-
.set_power = sdhci_set_power_and_bus_voltage,
548+
.set_power = sdhci_arasan_set_power_and_bus_voltage,
525549
.hw_reset = sdhci_arasan_hw_reset,
526550
};
527551

@@ -570,7 +594,7 @@ static const struct sdhci_ops sdhci_arasan_cqe_ops = {
570594
.set_bus_width = sdhci_set_bus_width,
571595
.reset = sdhci_arasan_reset,
572596
.set_uhs_signaling = sdhci_set_uhs_signaling,
573-
.set_power = sdhci_set_power_and_bus_voltage,
597+
.set_power = sdhci_arasan_set_power_and_bus_voltage,
574598
.irq = sdhci_arasan_cqhci_irq,
575599
};
576600

@@ -1447,6 +1471,7 @@ static const struct sdhci_arasan_clk_ops zynqmp_clk_ops = {
14471471
static struct sdhci_arasan_of_data sdhci_arasan_zynqmp_data = {
14481472
.pdata = &sdhci_arasan_zynqmp_pdata,
14491473
.clk_ops = &zynqmp_clk_ops,
1474+
.quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE,
14501475
};
14511476

14521477
static const struct sdhci_arasan_clk_ops versal_clk_ops = {
@@ -1457,6 +1482,7 @@ static const struct sdhci_arasan_clk_ops versal_clk_ops = {
14571482
static struct sdhci_arasan_of_data sdhci_arasan_versal_data = {
14581483
.pdata = &sdhci_arasan_zynqmp_pdata,
14591484
.clk_ops = &versal_clk_ops,
1485+
.quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE,
14601486
};
14611487

14621488
static const struct sdhci_arasan_clk_ops versal_net_clk_ops = {
@@ -1467,6 +1493,7 @@ static const struct sdhci_arasan_clk_ops versal_net_clk_ops = {
14671493
static struct sdhci_arasan_of_data sdhci_arasan_versal_net_data = {
14681494
.pdata = &sdhci_arasan_versal_net_pdata,
14691495
.clk_ops = &versal_net_clk_ops,
1496+
.quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE,
14701497
};
14711498

14721499
static struct sdhci_arasan_of_data intel_keembay_emmc_data = {
@@ -1945,6 +1972,8 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
19451972
if (of_device_is_compatible(np, "rockchip,rk3399-sdhci-5.1"))
19461973
sdhci_arasan_update_clockmultiplier(host, 0x0);
19471974

1975+
sdhci_arasan->quirks |= data->quirks;
1976+
19481977
if (of_device_is_compatible(np, "intel,keembay-sdhci-5.1-emmc") ||
19491978
of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sd") ||
19501979
of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sdio")) {

0 commit comments

Comments
 (0)