]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
mmc: sdhci-msm: Ensure SD card power isn't ON when card removed
authorSarthak Garg <quic_sartgarg@quicinc.com>
Tue, 1 Jul 2025 10:06:59 +0000 (15:36 +0530)
committerUlf Hansson <ulf.hansson@linaro.org>
Thu, 3 Jul 2025 13:25:01 +0000 (15:25 +0200)
Many mobile phones feature multi-card tray designs, where the same
tray is used for both SD and SIM cards. If the SD card is placed
at the outermost location in the tray, the SIM card may come in
contact with SD card power-supply while removing the tray, possibly
resulting in SIM damage.

To prevent that, make sure the SD card is really inserted by reading
the Card Detect pin state. If it's not, turn off the power in
sdhci_msm_check_power_status() and also set the BUS_FAIL power state
on the controller as part of pwr_irq handling for BUS_ON request.

Signed-off-by: Sarthak Garg <quic_sartgarg@quicinc.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Link: https://lore.kernel.org/r/20250701100659.3310386-1-quic_sartgarg@quicinc.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/sdhci-msm.c

index 732b65d4b61a347090ddef58c0dae0cffbb0998d..5b97a47e55fb06bf690acc1f2ae723b347af66cc 100644 (file)
@@ -1564,6 +1564,7 @@ static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+       struct mmc_host *mmc = host->mmc;
        bool done = false;
        u32 val = SWITCHABLE_SIGNALING_VOLTAGE;
        const struct sdhci_msm_offset *msm_offset =
@@ -1621,6 +1622,12 @@ static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type)
                                 "%s: pwr_irq for req: (%d) timed out\n",
                                 mmc_hostname(host->mmc), req_type);
        }
+
+       if ((req_type & REQ_BUS_ON) && mmc->card && !mmc->ops->get_cd(mmc)) {
+               sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+               host->pwr = 0;
+       }
+
        pr_debug("%s: %s: request %d done\n", mmc_hostname(host->mmc),
                        __func__, req_type);
 }
@@ -1679,6 +1686,13 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq)
                udelay(10);
        }
 
+       if ((irq_status & CORE_PWRCTL_BUS_ON) && mmc->card &&
+           !mmc->ops->get_cd(mmc)) {
+               msm_host_writel(msm_host, CORE_PWRCTL_BUS_FAIL, host,
+                               msm_offset->core_pwrctl_ctl);
+               return;
+       }
+
        /* Handle BUS ON/OFF*/
        if (irq_status & CORE_PWRCTL_BUS_ON) {
                pwr_state = REQ_BUS_ON;