From: SwtcR <swtcr0@xxxxxxxxx> Provide a hook to be called *before* a voltage switch takes place. This may be required, for example, to configure pins as 3.3V tolerant prior to switching back from 1.8V to 3.3V. This adds a 'struct mmc_ios' arg to voltage_switch to signal which voltage we have just switched to. Signed-off-by: SwtcR <swtcr0@xxxxxxxxx> Signed-off-by: Andre Heider <a.heider@xxxxxxxxx> --- drivers/mmc/host/sdhci-tegra.c | 2 +- drivers/mmc/host/sdhci.c | 16 +++++++++++++++- drivers/mmc/host/sdhci.h | 4 +++- drivers/mmc/host/sdhci_f_sdh30.c | 7 ++++++- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index b877c13184c2..c545f0f34bf9 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -289,7 +289,7 @@ static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) return mmc_send_tuning(host->mmc, opcode, NULL); } -static void tegra_sdhci_voltage_switch(struct sdhci_host *host) +static void tegra_sdhci_voltage_switch(struct sdhci_host *host, struct mmc_ios *ios) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 2020e57ffa7e..6a6ca87e9859 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1929,6 +1929,10 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, case MMC_SIGNAL_VOLTAGE_330: if (!(host->flags & SDHCI_SIGNALING_330)) return -EINVAL; + + if (host->ops->pre_voltage_switch) + host->ops->pre_voltage_switch(host, ios); + /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ ctrl &= ~SDHCI_CTRL_VDD_180; sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); @@ -1941,6 +1945,11 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, return -EIO; } } + + /* Some controller need to do more when switching */ + if (host->ops->voltage_switch) + host->ops->voltage_switch(host, ios); + /* Wait for 5ms */ usleep_range(5000, 5500); @@ -1956,6 +1965,11 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, case MMC_SIGNAL_VOLTAGE_180: if (!(host->flags & SDHCI_SIGNALING_180)) return -EINVAL; + + /* Some controller need to do more when switching */ + if (host->ops->pre_voltage_switch) + host->ops->pre_voltage_switch(host, ios); + if (!IS_ERR(mmc->supply.vqmmc)) { ret = mmc_regulator_set_vqmmc(mmc, ios); if (ret) { @@ -1974,7 +1988,7 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, /* Some controller need to do more when switching */ if (host->ops->voltage_switch) - host->ops->voltage_switch(host); + host->ops->voltage_switch(host, ios); /* 1.8V regulator output should be stable within 5 ms */ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index c95b0a4a7594..57a0ea885d1f 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -587,7 +587,9 @@ struct sdhci_ops { void (*hw_reset)(struct sdhci_host *host); void (*adma_workaround)(struct sdhci_host *host, u32 intmask); void (*card_event)(struct sdhci_host *host); - void (*voltage_switch)(struct sdhci_host *host); + void (*pre_voltage_switch)(struct sdhci_host *host, + struct mmc_ios *ios); + void (*voltage_switch)(struct sdhci_host *host, struct mmc_ios *ios); }; #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c index 485f7591fae4..d902b1fa6b2c 100644 --- a/drivers/mmc/host/sdhci_f_sdh30.c +++ b/drivers/mmc/host/sdhci_f_sdh30.c @@ -53,11 +53,16 @@ struct f_sdhost_priv { bool enable_cmd_dat_delay; }; -static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host) +static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host, + struct mmc_ios *ios) { struct f_sdhost_priv *priv = sdhci_priv(host); u32 ctrl = 0; + // FIXME: do something when switching back to 3.3V? + if (ios->signal_voltage != MMC_SIGNAL_VOLTAGE_180) + return; + usleep_range(2500, 3000); ctrl = sdhci_readl(host, F_SDH30_IO_CONTROL2); ctrl |= F_SDH30_CRES_O_DN; -- 2.16.3 -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html