summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarthak Garg <quic_sartgarg@quicinc.com>2025-07-01 15:36:59 +0530
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-08-20 18:30:25 +0200
commit6f38d9ae4b6c857ee144586886f5a34169735a7f (patch)
tree7a0e5ba9a4a4c035a1e6a2bbc10f7995b68b1cd4
parentde12d2c69b5db303bd3b745beb32ad8fd6c4dd81 (diff)
mmc: sdhci-msm: Ensure SD card power isn't ON when card removed
[ Upstream commit db58532188ebf51d52b1d7693d9e94c76b926e9f ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/mmc/host/sdhci-msm.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 82808cc373f6..c2144a3efb30 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -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;