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>
This commit is contained in:
Sahitya Tummala 2013-08-06 15:22:28 +05:30 committed by Subhash Jadavani
parent 0c6d03791c
commit 2858ae8ace

View file

@ -43,6 +43,9 @@
#define CORE_HC_MODE 0x78 #define CORE_HC_MODE 0x78
#define HC_MODE_EN 0x1 #define HC_MODE_EN 0x1
#define CORE_GENERICS 0x70
#define SWITCHABLE_SIGNALLING_VOL (1 << 29)
#define CORE_POWER 0x0 #define CORE_POWER 0x0
#define CORE_SW_RST (1 << 7) #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; struct sdhci_msm_host *msm_host = pltfm_host->priv;
unsigned long flags; unsigned long flags;
bool done = false; bool done = false;
u32 io_sig_sts;
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);
pr_debug("%s: %s: request %d curr_pwr_state %x curr_io_level %x\n", pr_debug("%s: %s: request %d curr_pwr_state %x curr_io_level %x\n",
mmc_hostname(host->mmc), __func__, req_type, mmc_hostname(host->mmc), __func__, req_type,
msm_host->curr_pwr_state, msm_host->curr_io_level); 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) || if ((req_type & msm_host->curr_pwr_state) ||
(req_type & msm_host->curr_io_level)) (req_type & msm_host->curr_io_level))
done = true; done = true;