@@ -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);
@@ -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);
@@ -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
@@ -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;