mmc: add hs400 enhanced strobe support for mmc subsystem
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / host / sdhci.c
index fbc7efdddcb5a4cb9c2726b91e2ee29acfa85f08..6e13fa8471bf253980ccdfa6c529f858058cb6f4 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
@@ -1364,7 +1367,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);
 
@@ -1895,9 +1898,9 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
                tuning_count = host->tuning_count;
 
        /*
-        * The Host Controller needs tuning only in case of SDR104 mode
-        * and for SDR50 mode when Use Tuning for SDR50 is set in the
-        * Capabilities register.
+        * The Host Controller needs tuning in case of SDR104 and DDR50
+        * mode, and for SDR50 mode when Use Tuning for SDR50 is set in
+        * the Capabilities register.
         * If the Host Controller supports the HS200 mode then the
         * tuning function has to be executed.
         */
@@ -1917,6 +1920,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
                break;
 
        case MMC_TIMING_UHS_SDR104:
+       case MMC_TIMING_UHS_DDR50:
                break;
 
        case MMC_TIMING_UHS_SDR50:
@@ -2074,6 +2078,16 @@ out_unlock:
        return err;
 }
 
+static int sdhci_prepare_enhanced_strobe(struct mmc_host *mmc, bool enable)
+{
+       /*
+       * Currently we can't find a register to enable enhanced strobe
+       * function for standard sdhci, so we expect variant drivers to
+       * overwrite it.
+       */
+       return -EINVAL;
+}
+
 static int sdhci_select_drive_strength(struct mmc_card *card,
                                       unsigned int max_dtr, int host_drv,
                                       int card_drv, int *drv_type)
@@ -2210,6 +2224,7 @@ static const struct mmc_host_ops sdhci_ops = {
        .enable_sdio_irq = sdhci_enable_sdio_irq,
        .start_signal_voltage_switch    = sdhci_start_signal_voltage_switch,
        .prepare_hs400_tuning           = sdhci_prepare_hs400_tuning,
+       .prepare_enhanced_strobe        = sdhci_prepare_enhanced_strobe,
        .execute_tuning                 = sdhci_execute_tuning,
        .select_drive_strength          = sdhci_select_drive_strength,
        .card_event                     = sdhci_card_event,
@@ -2716,17 +2731,6 @@ int sdhci_resume_host(struct sdhci_host *host)
                        host->ops->enable_dma(host);
        }
 
-       if (!device_may_wakeup(mmc_dev(host->mmc))) {
-               ret = request_threaded_irq(host->irq, sdhci_irq,
-                                          sdhci_thread_irq, IRQF_SHARED,
-                                          mmc_hostname(host->mmc), host);
-               if (ret)
-                       return ret;
-       } else {
-               sdhci_disable_irq_wakeups(host);
-               disable_irq_wake(host->irq);
-       }
-
        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 */
@@ -2739,6 +2743,17 @@ int sdhci_resume_host(struct sdhci_host *host)
                mmiowb();
        }
 
+       if (!device_may_wakeup(mmc_dev(host->mmc))) {
+               ret = request_threaded_irq(host->irq, sdhci_irq,
+                                          sdhci_thread_irq, IRQF_SHARED,
+                                          mmc_hostname(host->mmc), host);
+               if (ret)
+                       return ret;
+       } else {
+               sdhci_disable_irq_wakeups(host);
+               disable_irq_wake(host->irq);
+       }
+
        sdhci_enable_card_detection(host);
 
        return ret;
@@ -2759,7 +2774,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);
@@ -2767,7 +2782,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);
@@ -2860,6 +2875,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;
 }
@@ -3056,7 +3073,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)
@@ -3090,14 +3106,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;