mmc: sdhci-sprd: Fix vqmmc not shutting down after the card was pulled
authorWenchao Chen <wenchao.chen@unisoc.com>
Wed, 15 Nov 2023 08:34:06 +0000 (16:34 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 8 Dec 2023 07:52:16 +0000 (08:52 +0100)
commit 477865af60b2117ceaa1d558e03559108c15c78c upstream.

With cat regulator_summary, we found that vqmmc was not shutting
down after the card was pulled.

cat /sys/kernel/debug/regulator/regulator_summary
1.before fix
1)Insert SD card
 vddsdio 1    1  0 unknown  3500mV 0mA  1200mV  3750mV
    71100000.mmc-vqmmc  1                         0mA  3500mV  3600mV

2)Pull out the SD card
 vddsdio                1    1  0 unknown  3500mV 0mA  1200mV  3750mV
    71100000.mmc-vqmmc  1                         0mA  3500mV  3600mV

2.after fix
1)Insert SD cardt
 vddsdio                1    1  0 unknown  3500mV 0mA  1200mV  3750mV
    71100000.mmc-vqmmc  1                         0mA  3500mV  3600mV

2)Pull out the SD card
 vddsdio 0    1  0 unknown  3500mV 0mA  1200mV  3750mV
    71100000.mmc-vqmmc  0                         0mA  3500mV  3600mV

Fixes: fb8bd90f83c4 ("mmc: sdhci-sprd: Add Spreadtrum's initial host controller")
Signed-off-by: Wenchao Chen <wenchao.chen@unisoc.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20231115083406.7368-1-wenchao.chen@unisoc.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/mmc/host/sdhci-sprd.c

index 6b84ba27e6ab0d83f5b20154c376c0e38af3c7a4..6b8a57e2d20f0a75e860f59c3e1737bb55211e52 100644 (file)
@@ -416,12 +416,33 @@ static void sdhci_sprd_request_done(struct sdhci_host *host,
        mmc_request_done(host->mmc, mrq);
 }
 
+static void sdhci_sprd_set_power(struct sdhci_host *host, unsigned char mode,
+                                unsigned short vdd)
+{
+       struct mmc_host *mmc = host->mmc;
+
+       switch (mode) {
+       case MMC_POWER_OFF:
+               mmc_regulator_set_ocr(host->mmc, mmc->supply.vmmc, 0);
+
+               mmc_regulator_disable_vqmmc(mmc);
+               break;
+       case MMC_POWER_ON:
+               mmc_regulator_enable_vqmmc(mmc);
+               break;
+       case MMC_POWER_UP:
+               mmc_regulator_set_ocr(host->mmc, mmc->supply.vmmc, vdd);
+               break;
+       }
+}
+
 static struct sdhci_ops sdhci_sprd_ops = {
        .read_l = sdhci_sprd_readl,
        .write_l = sdhci_sprd_writel,
        .write_w = sdhci_sprd_writew,
        .write_b = sdhci_sprd_writeb,
        .set_clock = sdhci_sprd_set_clock,
+       .set_power = sdhci_sprd_set_power,
        .get_max_clock = sdhci_sprd_get_max_clock,
        .get_min_clock = sdhci_sprd_get_min_clock,
        .set_bus_width = sdhci_set_bus_width,
@@ -823,6 +844,10 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
        host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
                         SDHCI_SUPPORT_DDR50);
 
+       ret = mmc_regulator_get_supply(host->mmc);
+       if (ret)
+               goto pm_runtime_disable;
+
        ret = sdhci_setup_host(host);
        if (ret)
                goto pm_runtime_disable;