]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/mmc/host/sdhci.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
[karo-tx-linux.git] / drivers / mmc / host / sdhci.c
index 8d66706824a6105ceeac2f63526372a4f0c521fd..8262cadfdab77b82e5590da88ff0042479d3a697 100644 (file)
@@ -2267,8 +2267,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 {
        irqreturn_t result;
        struct sdhci_host *host = dev_id;
-       u32 intmask;
-       int cardint = 0;
+       u32 intmask, unexpected = 0;
+       int cardint = 0, max_loops = 16;
 
        spin_lock(&host->lock);
 
@@ -2286,6 +2286,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
                goto out;
        }
 
+again:
        DBG("*** %s got interrupt: 0x%08x\n",
                mmc_hostname(host->mmc), intmask);
 
@@ -2344,19 +2345,23 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
        intmask &= ~SDHCI_INT_CARD_INT;
 
        if (intmask) {
-               pr_err("%s: Unexpected interrupt 0x%08x.\n",
-                       mmc_hostname(host->mmc), intmask);
-               sdhci_dumpregs(host);
-
+               unexpected |= intmask;
                sdhci_writel(host, intmask, SDHCI_INT_STATUS);
        }
 
        result = IRQ_HANDLED;
 
-       mmiowb();
+       intmask = sdhci_readl(host, SDHCI_INT_STATUS);
+       if (intmask && --max_loops)
+               goto again;
 out:
        spin_unlock(&host->lock);
 
+       if (unexpected) {
+               pr_err("%s: Unexpected interrupt 0x%08x.\n",
+                          mmc_hostname(host->mmc), unexpected);
+               sdhci_dumpregs(host);
+       }
        /*
         * We have to delay this as it calls back into the driver.
         */
@@ -2379,6 +2384,9 @@ int sdhci_suspend_host(struct sdhci_host *host)
        int ret;
        bool has_tuning_timer;
 
+       if (host->ops->platform_suspend)
+               host->ops->platform_suspend(host);
+
        sdhci_disable_card_detection(host);
 
        /* Disable tuning since we are suspending */
@@ -2423,12 +2431,24 @@ int sdhci_resume_host(struct sdhci_host *host)
        if (ret)
                return ret;
 
-       sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
-       mmiowb();
+       if ((host->mmc->pm_flags & MMC_PM_KEEP_POWER) &&
+           (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) {
+               /* Card keeps power but host controller does not */
+               sdhci_init(host, 0);
+               host->pwr = 0;
+               host->clock = 0;
+               sdhci_do_set_ios(host, &host->mmc->ios);
+       } else {
+               sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
+               mmiowb();
+       }
 
        ret = mmc_resume_host(host->mmc);
        sdhci_enable_card_detection(host);
 
+       if (host->ops->platform_resume)
+               host->ops->platform_resume(host);
+
        /* Set the re-tuning expiration flag */
        if ((host->version >= SDHCI_SPEC_300) && host->tuning_count &&
            (host->tuning_mode == SDHCI_TUNING_MODE_1))