From: SwtcR <swtcr0@xxxxxxxxx> This is required on Tegra210 for 1.8V support. Signed-off-by: SwtcR <swtcr0@xxxxxxxxx> Signed-off-by: Andre Heider <a.heider@xxxxxxxxx> --- drivers/mmc/host/sdhci-tegra.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index c545f0f34bf9..254db23eab5f 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -27,6 +27,7 @@ #include <linux/mmc/mmc.h> #include <linux/mmc/slot-gpio.h> #include <linux/gpio/consumer.h> +#include <soc/tegra/pmc.h> #include "sdhci-pltfm.h" @@ -55,6 +56,7 @@ #define NVQUIRK_ENABLE_SDR104 BIT(4) #define NVQUIRK_ENABLE_DDR50 BIT(5) #define NVQUIRK_HAS_PADCALIB BIT(6) +#define NVQUIRK_NEEDS_PAD_CONTROL BIT(7) struct sdhci_tegra_soc_data { const struct sdhci_pltfm_data *pdata; @@ -66,6 +68,8 @@ struct sdhci_tegra { struct gpio_desc *power_gpio; bool ddr_signaling; bool pad_calib_required; + bool pad_control; + unsigned int pad_id; struct reset_control *rst; }; @@ -166,7 +170,9 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask) * even if the device supports it because the IO voltage * cannot be configured. */ - if (!IS_ERR(host->mmc->supply.vqmmc)) { + if (!IS_ERR(host->mmc->supply.vqmmc) && + (!(soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL) || + tegra_host->pad_control)) { /* Erratum: Enable SDHCI spec v3.00 support */ if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300) misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300; @@ -297,6 +303,24 @@ static void tegra_sdhci_voltage_switch(struct sdhci_host *host, struct mmc_ios * if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) tegra_host->pad_calib_required = true; + + if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { + if (tegra_host->pad_control) { + tegra_io_pad_set_voltage(tegra_host->pad_id, TEGRA_IO_PAD_1800000UV); + } + } +} + +static void tegra_sdhci_pre_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); + + if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { + if (tegra_host->pad_control) { + tegra_io_pad_set_voltage(tegra_host->pad_id, TEGRA_IO_PAD_3300000UV); + } + } } static const struct sdhci_ops tegra_sdhci_ops = { @@ -308,6 +332,7 @@ static const struct sdhci_ops tegra_sdhci_ops = { .reset = tegra_sdhci_reset, .platform_execute_tuning = tegra_sdhci_execute_tuning, .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, + .pre_voltage_switch = tegra_sdhci_pre_voltage_switch, .voltage_switch = tegra_sdhci_voltage_switch, .get_max_clock = tegra_sdhci_get_max_clock, }; @@ -458,6 +483,8 @@ static int sdhci_tegra_probe(struct platform_device *pdev) struct sdhci_tegra *tegra_host; struct clk *clk; int rc; + struct device_node *np = pdev->dev.of_node; + u32 prop; match = of_match_device(sdhci_tegra_dt_match, &pdev->dev); if (!match) @@ -472,8 +499,14 @@ static int sdhci_tegra_probe(struct platform_device *pdev) tegra_host = sdhci_pltfm_priv(pltfm_host); tegra_host->ddr_signaling = false; tegra_host->pad_calib_required = false; + tegra_host->pad_control = false; tegra_host->soc_data = soc_data; + if (!of_property_read_u32(np, "nvidia,pad", &prop)) { + tegra_host->pad_control = true; + tegra_host->pad_id = prop; + } + rc = mmc_of_parse(host->mmc); if (rc) goto err_parse_dt; -- 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