mmc: sdhci-of-arasan: wakeup genpd when being in suspend
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / host / sdhci.c
index b48565ed5616c79302008963a05aa7e1e18d742c..6ffff1651438239dbd50fdf20f8e1b998c8cd1be 100644 (file)
@@ -540,9 +540,12 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
 
                BUG_ON(len > 65536);
 
-               /* tran, valid */
-               sdhci_adma_write_desc(host, desc, addr, len, ADMA2_TRAN_VALID);
-               desc += host->desc_sz;
+               if (len) {
+                       /* tran, valid */
+                       sdhci_adma_write_desc(host, desc, addr, len,
+                                             ADMA2_TRAN_VALID);
+                       desc += host->desc_sz;
+               }
 
                /*
                 * If this triggers then we have a calculation bug
@@ -663,9 +666,20 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
        if (!data)
                target_timeout = cmd->busy_timeout * 1000;
        else {
-               target_timeout = data->timeout_ns / 1000;
-               if (host->clock)
-                       target_timeout += data->timeout_clks / host->clock;
+               target_timeout = DIV_ROUND_UP(data->timeout_ns, 1000);
+               if (host->clock && data->timeout_clks) {
+                       unsigned long long val;
+
+                       /*
+                        * data->timeout_clks is in units of clock cycles.
+                        * host->clock is in Hz.  target_timeout is in us.
+                        * Hence, us = 1000000 * cycles / Hz.  Round up.
+                        */
+                       val = 1000000 * data->timeout_clks;
+                       if (do_div(val, host->clock))
+                               target_timeout++;
+                       target_timeout += val;
+               }
        }
 
        /*
@@ -1364,7 +1378,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
        sdhci_runtime_pm_get(host);
 
        /* Firstly check card presence */
-       present = sdhci_do_get_cd(host);
+       present = mmc->ops->get_cd(mmc);
 
        spin_lock_irqsave(&host->lock, flags);
 
@@ -1856,11 +1870,11 @@ static int sdhci_card_busy(struct mmc_host *mmc)
        u32 present_state;
 
        sdhci_runtime_pm_get(host);
-       /* Check whether DAT[3:0] is 0000 */
+       /* Check whether DAT[0] is 0 */
        present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
        sdhci_runtime_pm_put(host);
 
-       return !(present_state & SDHCI_DATA_LVL_MASK);
+       return !(present_state & SDHCI_DATA_0_LVL_MASK);
 }
 
 static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
@@ -2701,7 +2715,6 @@ int sdhci_suspend_host(struct sdhci_host *host)
                free_irq(host->irq, host);
        } else {
                sdhci_enable_irq_wakeups(host);
-               enable_irq_wake(host->irq);
        }
        return 0;
 }
@@ -2737,7 +2750,6 @@ int sdhci_resume_host(struct sdhci_host *host)
                        return ret;
        } else {
                sdhci_disable_irq_wakeups(host);
-               disable_irq_wake(host->irq);
        }
 
        sdhci_enable_card_detection(host);
@@ -2760,7 +2772,7 @@ static int sdhci_runtime_pm_put(struct sdhci_host *host)
 
 static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
 {
-       if (host->runtime_suspended || host->bus_on)
+       if (host->bus_on)
                return;
        host->bus_on = true;
        pm_runtime_get_noresume(host->mmc->parent);
@@ -2768,7 +2780,7 @@ static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
 
 static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)
 {
-       if (host->runtime_suspended || !host->bus_on)
+       if (!host->bus_on)
                return;
        host->bus_on = false;
        pm_runtime_put_noidle(host->mmc->parent);
@@ -2861,6 +2873,8 @@ struct sdhci_host *sdhci_alloc_host(struct device *dev,
 
        host = mmc_priv(mmc);
        host->mmc = mmc;
+       host->mmc_host_ops = sdhci_ops;
+       mmc->ops = &host->mmc_host_ops;
 
        return host;
 }
@@ -3057,7 +3071,6 @@ int sdhci_add_host(struct sdhci_host *host)
        /*
         * Set host parameters.
         */
-       mmc->ops = &sdhci_ops;
        max_clk = host->max_clk;
 
        if (host->ops->get_min_clock)
@@ -3091,14 +3104,14 @@ int sdhci_add_host(struct sdhci_host *host)
                if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT)
                        host->timeout_clk *= 1000;
 
+               if (override_timeout_clk)
+                       host->timeout_clk = override_timeout_clk;
+
                mmc->max_busy_timeout = host->ops->get_max_timeout_count ?
                        host->ops->get_max_timeout_count(host) : 1 << 27;
                mmc->max_busy_timeout /= host->timeout_clk;
        }
 
-       if (override_timeout_clk)
-               host->timeout_clk = override_timeout_clk;
-
        mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
        mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;