[PATCH 3/6] sdhci-tegra: add support for updating pad I/O voltage via PMC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [ARM Kernel]     [Linux ARM]     [Linux ARM MSM]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux