diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r-- | drivers/mmc/host/sdhci.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 1c828e0e9905..1b3fbd9bd5c5 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1029,7 +1029,9 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, if (data == NULL) { if (host->quirks2 & SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) { - sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); + /* must not clear SDHCI_TRANSFER_MODE when tuning */ + if (cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) + sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); } else { /* clear Auto CMD settings for no data CMDs */ mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); @@ -2103,7 +2105,7 @@ static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) return 0; } -static void sdhci_start_tuning(struct sdhci_host *host) +void sdhci_start_tuning(struct sdhci_host *host) { u16 ctrl; @@ -2126,14 +2128,16 @@ static void sdhci_start_tuning(struct sdhci_host *host) sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); } +EXPORT_SYMBOL_GPL(sdhci_start_tuning); -static void sdhci_end_tuning(struct sdhci_host *host) +void sdhci_end_tuning(struct sdhci_host *host) { sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); } +EXPORT_SYMBOL_GPL(sdhci_end_tuning); -static void sdhci_reset_tuning(struct sdhci_host *host) +void sdhci_reset_tuning(struct sdhci_host *host) { u16 ctrl; @@ -2142,6 +2146,7 @@ static void sdhci_reset_tuning(struct sdhci_host *host) ctrl &= ~SDHCI_CTRL_EXEC_TUNING; sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); } +EXPORT_SYMBOL_GPL(sdhci_reset_tuning); static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) { @@ -2162,7 +2167,7 @@ static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) * interrupt setup is different to other commands and there is no timeout * interrupt so special handling is needed. */ -static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) +void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) { struct mmc_host *mmc = host->mmc; struct mmc_command cmd = {}; @@ -2212,6 +2217,7 @@ static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) msecs_to_jiffies(50)); } +EXPORT_SYMBOL_GPL(sdhci_send_tuning); static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) { @@ -3734,14 +3740,21 @@ int sdhci_setup_host(struct sdhci_host *host) mmc_gpio_get_cd(host->mmc) < 0) mmc->caps |= MMC_CAP_NEEDS_POLL; - /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */ if (!IS_ERR(mmc->supply.vqmmc)) { ret = regulator_enable(mmc->supply.vqmmc); + + /* If vqmmc provides no 1.8V signalling, then there's no UHS */ if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000, 1950000)) host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); + + /* In eMMC case vqmmc might be a fixed 1.8V regulator */ + if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 2700000, + 3600000)) + host->flags &= ~SDHCI_SIGNALING_330; + if (ret) { pr_warn("%s: Failed to enable vqmmc regulator: %d\n", mmc_hostname(mmc), ret); |