summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSahitya Tummala <stummala@codeaurora.org>2013-08-06 15:22:28 +0530
committerSubhash Jadavani <subhashj@codeaurora.org>2016-05-27 10:28:49 -0700
commit2858ae8aceb39b24d51eec05975d93b73ca271d2 (patch)
treeda31d3f37bd2c486532a30bdcd454761446ec6ed /drivers
parent0c6d03791ca275d3d8f6c57bbee1a5a39e80d93b (diff)
mmc: sdhci-msm: Fix power IRQ issue uncovered in 3.10 kernel
The request to change the VDD I/O voltage level to high/low will trigger an IRQ only when - 1. SWITCHABLE_SIGNALING_VOLTAGE bit 29 of SDCC_MCI_GENERICS register is set. 2. Above condition is true and when there is a state change in VDD bit 3 of SDHCi Host Control 2 register. Until now, the MMC core layer issues I/O high request only after the controller is powered up. The I/O high request is same as the reset state of host control2 register which will never trigger an IRQ. The driver already handles this case by ensuring that I/O voltage is set to high as part of power up itself and thus returns immediately when I/O high request is issued later. But in 3.10 kernel, this request is issued even before the controller is powered up. Hence, check for host->pwr state to avoid waiting for an IRQ that never comes. Change-Id: I31b6723f53397be1ba151305ead89e739560eb20 Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/sdhci-msm.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index f2fb9f56564a..9ec0ec0baf84 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -43,6 +43,9 @@
#define CORE_HC_MODE 0x78
#define HC_MODE_EN 0x1
+#define CORE_GENERICS 0x70
+#define SWITCHABLE_SIGNALLING_VOL (1 << 29)
+
#define CORE_POWER 0x0
#define CORE_SW_RST (1 << 7)
@@ -1891,11 +1894,36 @@ static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type)
struct sdhci_msm_host *msm_host = pltfm_host->priv;
unsigned long flags;
bool done = false;
+ u32 io_sig_sts;
spin_lock_irqsave(&host->lock, flags);
pr_debug("%s: %s: request %d curr_pwr_state %x curr_io_level %x\n",
mmc_hostname(host->mmc), __func__, req_type,
msm_host->curr_pwr_state, msm_host->curr_io_level);
+ io_sig_sts = readl_relaxed(msm_host->core_mem + CORE_GENERICS);
+ /*
+ * The IRQ for request type IO High/Low will be generated when -
+ * 1. SWITCHABLE_SIGNALLING_VOL is enabled in HW.
+ * 2. If 1 is true and when there is a state change in 1.8V enable
+ * bit (bit 3) of SDHCI_HOST_CONTROL2 register. The reset state of
+ * that bit is 0 which indicates 3.3V IO voltage. So, when MMC core
+ * layer tries to set it to 3.3V before card detection happens, the
+ * IRQ doesn't get triggered as there is no state change in this bit.
+ * The driver already handles this case by changing the IO voltage
+ * level to high as part of controller power up sequence. Hence, check
+ * for host->pwr to handle a case where IO voltage high request is
+ * issued even before controller power up.
+ */
+ if (req_type & (REQ_IO_HIGH | REQ_IO_LOW)) {
+ if (!(io_sig_sts & SWITCHABLE_SIGNALLING_VOL) ||
+ ((req_type & REQ_IO_HIGH) && !host->pwr)) {
+ pr_debug("%s: do not wait for power IRQ that never comes\n",
+ mmc_hostname(host->mmc));
+ spin_unlock_irqrestore(&host->lock, flags);
+ return;
+ }
+ }
+
if ((req_type & msm_host->curr_pwr_state) ||
(req_type & msm_host->curr_io_level))
done = true;