mmc: sdhci-msm: Fix wakeup functionality for SDIO

There could be a case where after platform device (sdhci_msm)
suspend, (where external gpio to IRQ is configured for wakeup
in case of sdio) external gpioIRQ is raised before
system suspend is completed.
To solve this problem we use a flag to signal
sdhci_msm_suspend_noirq to abort suspend with -EBUSY signal.

Change-Id: I82617d5a02674af24d330601e41fb3c20278f672
Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>
This commit is contained in:
Ritesh Harjani 2015-12-17 19:59:04 +05:30 committed by Subhash Jadavani
parent d906a5c18b
commit c45bebe32d
2 changed files with 13 additions and 2 deletions

View file

@ -2292,6 +2292,9 @@ static void sdhci_msm_cfg_sdiowakeup_gpio_irq(struct sdhci_host *host,
static irqreturn_t sdhci_msm_sdiowakeup_irq(int irq, void *data)
{
struct sdhci_host *host = (struct sdhci_host *)data;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
unsigned long flags;
pr_debug("%s: irq (%d) received\n", __func__, irq);
@ -2299,6 +2302,7 @@ static irqreturn_t sdhci_msm_sdiowakeup_irq(int irq, void *data)
spin_lock_irqsave(&host->lock, flags);
sdhci_msm_cfg_sdiowakeup_gpio_irq(host, false);
spin_unlock_irqrestore(&host->lock, flags);
msm_host->sdio_pending_processing = true;
return IRQ_HANDLED;
}
@ -4264,9 +4268,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
msm_host->pdata->sdiowakeup_irq = platform_get_irq_byname(pdev,
"sdiowakeup_irq");
dev_info(&pdev->dev, "%s: sdiowakeup_irq = %d\n", __func__,
msm_host->pdata->sdiowakeup_irq);
if (sdhci_is_valid_gpio_wakeup_int(msm_host)) {
dev_info(&pdev->dev, "%s: sdiowakeup_irq = %d\n", __func__,
msm_host->pdata->sdiowakeup_irq);
msm_host->is_sdiowakeup_enabled = true;
ret = request_irq(msm_host->pdata->sdiowakeup_irq,
sdhci_msm_sdiowakeup_irq,
@ -4421,6 +4425,7 @@ static int sdhci_msm_cfg_sdio_wakeup(struct sdhci_host *host, bool enable)
if (enable) {
/* configure DAT1 gpio if applicable */
if (sdhci_is_valid_gpio_wakeup_int(msm_host)) {
msm_host->sdio_pending_processing = false;
ret = enable_irq_wake(msm_host->pdata->sdiowakeup_irq);
if (!ret)
sdhci_msm_cfg_sdiowakeup_gpio_irq(host, true);
@ -4433,6 +4438,7 @@ static int sdhci_msm_cfg_sdio_wakeup(struct sdhci_host *host, bool enable)
if (sdhci_is_valid_gpio_wakeup_int(msm_host)) {
ret = disable_irq_wake(msm_host->pdata->sdiowakeup_irq);
sdhci_msm_cfg_sdiowakeup_gpio_irq(host, false);
msm_host->sdio_pending_processing = false;
} else {
pr_err("%s: sdiowakeup_irq(%d)invalid\n",
mmc_hostname(host->mmc), enable);
@ -4601,6 +4607,10 @@ static int sdhci_msm_suspend_noirq(struct device *dev)
ret = -EAGAIN;
}
if (host->mmc->card && mmc_card_sdio(host->mmc->card))
if (msm_host->sdio_pending_processing)
ret = -EBUSY;
return ret;
}

View file

@ -197,6 +197,7 @@ struct sdhci_msm_host {
bool en_auto_cmd21;
struct device_attribute auto_cmd21_attr;
bool is_sdiowakeup_enabled;
bool sdio_pending_processing;
atomic_t controller_clock;
bool use_cdclp533;
bool use_updated_dll_reset;