|
@@ -1878,6 +1878,18 @@ static int sdhci_card_busy(struct mmc_host *mmc)
|
|
|
return !(present_state & SDHCI_DATA_LVL_MASK);
|
|
|
}
|
|
|
|
|
|
+static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
|
|
|
+{
|
|
|
+ struct sdhci_host *host = mmc_priv(mmc);
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&host->lock, flags);
|
|
|
+ host->flags |= SDHCI_HS400_TUNING;
|
|
|
+ spin_unlock_irqrestore(&host->lock, flags);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
|
|
{
|
|
|
struct sdhci_host *host = mmc_priv(mmc);
|
|
@@ -1886,10 +1898,14 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
|
|
int err = 0;
|
|
|
unsigned long flags;
|
|
|
unsigned int tuning_count = 0;
|
|
|
+ bool hs400_tuning;
|
|
|
|
|
|
sdhci_runtime_pm_get(host);
|
|
|
spin_lock_irqsave(&host->lock, flags);
|
|
|
|
|
|
+ hs400_tuning = host->flags & SDHCI_HS400_TUNING;
|
|
|
+ host->flags &= ~SDHCI_HS400_TUNING;
|
|
|
+
|
|
|
if (host->tuning_mode == SDHCI_TUNING_MODE_1)
|
|
|
tuning_count = host->tuning_count;
|
|
|
|
|
@@ -1901,8 +1917,20 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
|
|
* tuning function has to be executed.
|
|
|
*/
|
|
|
switch (host->timing) {
|
|
|
+ /* HS400 tuning is done in HS200 mode */
|
|
|
case MMC_TIMING_MMC_HS400:
|
|
|
+ err = -EINVAL;
|
|
|
+ goto out_unlock;
|
|
|
+
|
|
|
case MMC_TIMING_MMC_HS200:
|
|
|
+ /*
|
|
|
+ * Periodic re-tuning for HS400 is not expected to be needed, so
|
|
|
+ * disable it here.
|
|
|
+ */
|
|
|
+ if (hs400_tuning)
|
|
|
+ tuning_count = 0;
|
|
|
+ break;
|
|
|
+
|
|
|
case MMC_TIMING_UHS_SDR104:
|
|
|
break;
|
|
|
|
|
@@ -2130,6 +2158,7 @@ static const struct mmc_host_ops sdhci_ops = {
|
|
|
.hw_reset = sdhci_hw_reset,
|
|
|
.enable_sdio_irq = sdhci_enable_sdio_irq,
|
|
|
.start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
|
|
|
+ .prepare_hs400_tuning = sdhci_prepare_hs400_tuning,
|
|
|
.execute_tuning = sdhci_execute_tuning,
|
|
|
.card_event = sdhci_card_event,
|
|
|
.card_busy = sdhci_card_busy,
|