diff options
author | Sahitya Tummala <stummala@codeaurora.org> | 2013-08-06 15:22:28 +0530 |
---|---|---|
committer | Subhash Jadavani <subhashj@codeaurora.org> | 2016-05-27 10:28:49 -0700 |
commit | 2858ae8aceb39b24d51eec05975d93b73ca271d2 (patch) | |
tree | da31d3f37bd2c486532a30bdcd454761446ec6ed /drivers | |
parent | 0c6d03791ca275d3d8f6c57bbee1a5a39e80d93b (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.c | 28 |
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; |