]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
mmc: tegra: Enable GPIO mode during device suspend
authorR Raj Kumar <rrajk@nvidia.com>
Fri, 12 Jun 2015 05:58:44 +0000 (11:28 +0530)
committermobile promotions <svcmobile_promotions@nvidia.com>
Mon, 20 Jul 2015 21:08:20 +0000 (14:08 -0700)
- Parse the sdmmc-pins details in tegra driver
- Enable GPIO mode and output a "1" on the entire
  sdmmc bus before shutdown of the sdmmc power rails.
- Disable GPIO mode after shutdown of the sdmmc power
  rails.
- Sequence to turn-off vddio rail for SD2.0 cards is
  3.3V --> 1.8V --> 0V
- Set PWR_DET_VAL(E_3v3) to 1 (default value) after
  sdmmc power rail shutdown.

Bug 1646287

Change-Id: I12868353a6132a5321623b1c9302b735914f15b5
Signed-off-by: R Raj Kumar <rrajk@nvidia.com>
Reviewed-on: http://git-master/r/757950
GVS: Gerrit_Virtual_Submit
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
drivers/mmc/host/sdhci-tegra.c
include/linux/platform_data/mmc-sdhci-tegra.h

index 58628c5ab947637489e440378cd07932e94b83a8..fb244991613056591a6a5cf4277cfe4bb9dafd6f 100644 (file)
@@ -2261,6 +2261,13 @@ static int tegra_sdhci_configure_regulators(struct sdhci_tegra *tegra_host,
        break;
        case CONFIG_REG_DIS:
                if (tegra_host->is_rail_enabled) {
+                       if (tegra_host->vdd_io_reg) {
+                               vddio_prev = regulator_get_voltage(
+                                               tegra_host->vdd_io_reg);
+                               if (vddio_prev > SDHOST_LOW_VOLT_MAX)
+                                       tegra_sdhci_signal_voltage_switch(
+                                               sdhci, MMC_SIGNAL_VOLTAGE_180);
+                       }
                        if (tegra_host->vdd_io_reg)
                                rc = regulator_disable(tegra_host->vdd_io_reg);
                        if (tegra_host->vdd_slot_reg)
@@ -4007,7 +4014,7 @@ static int tegra_sdhci_suspend(struct sdhci_host *sdhci)
        struct sdhci_tegra *tegra_host = pltfm_host->priv;
        int err = 0;
        struct platform_device *pdev = to_platform_device(mmc_dev(sdhci->mmc));
-       const struct tegra_sdhci_platform_data *plat;
+       const struct tegra_sdhci_platform_data *plat = pdev->dev.platform_data;
        unsigned int cd_irq;
 
        if (sdhci->is_clk_on) {
@@ -4018,13 +4025,18 @@ static int tegra_sdhci_suspend(struct sdhci_host *sdhci)
 
        /* Disable the power rails if any */
        if (tegra_host->card_present) {
+
+               /* Configure sdmmc pins to GPIO mode if needed */
+               if (plat->pin_count > 0)
+                       gpio_request_array(plat->gpios,
+                               ARRAY_SIZE(plat->gpios));
+
                err = tegra_sdhci_configure_regulators(tegra_host,
                        CONFIG_REG_DIS, 0, 0);
                if (err)
                        dev_err(mmc_dev(sdhci->mmc),
                        "Regulators disable in suspend failed %d\n", err);
        }
-       plat = pdev->dev.platform_data;
        if (plat && gpio_is_valid(plat->cd_gpio)) {
                if (!plat->cd_wakeup_incapable) {
                        /* Enable wake irq at end of suspend */
@@ -4036,6 +4048,18 @@ static int tegra_sdhci_suspend(struct sdhci_host *sdhci)
                                cd_irq, err);
                }
        }
+
+       if (plat->pwrdet_support && tegra_host->sdmmc_padctrl) {
+               err = padctrl_set_voltage(tegra_host->sdmmc_padctrl,
+                               SDHOST_HIGH_VOLT_3V3);
+               if (err)
+                       dev_err(mmc_dev(sdhci->mmc),
+                               "padcontrol set volt failed: %d\n", err);
+       }
+
+       if (plat->pin_count > 0)
+               gpio_free_array(plat->gpios, ARRAY_SIZE(plat->gpios));
+
        return err;
 }
 
@@ -5199,6 +5223,8 @@ static struct tegra_sdhci_platform_data *sdhci_tegra_dt_parse_pdata(
        struct tegra_sdhci_platform_data *plat;
        struct device_node *np = pdev->dev.of_node;
        u32 bus_width;
+       int i;
+       char label[12];
 
        if (!np)
                return NULL;
@@ -5301,6 +5327,16 @@ static struct tegra_sdhci_platform_data *sdhci_tegra_dt_parse_pdata(
 
        plat->en_periodic_calib = of_property_read_bool(np,
                        "nvidia,en-periodic-calib");
+       plat->pin_count = of_gpio_named_count(np, "nvidia,sdmmc-pin-gpios");
+       for (i = 0; i < plat->pin_count; ++i) {
+               val = of_get_named_gpio(np, "nvidia,sdmmc-pin-gpios", i);
+               if (gpio_is_valid(val)) {
+                       plat->gpios[i].gpio = val;
+                       plat->gpios[i].flags = GPIOF_DIR_OUT;
+                       sprintf(label, "sdmmc_pin%d", i);
+                       plat->gpios[i].label = label;
+               }
+       }
        return plat;
 }
 
index 1ad0733b0e1d40a1c4e3c574b0c92c506908810d..2085c82f7730cb39670ca560cfb4f965cb39f0b4 100644 (file)
@@ -107,6 +107,8 @@ struct tegra_sdhci_platform_data {
        bool en_strobe; /* Enable enhance strobe mode for eMMC */
        bool enb_feedback_clock;
        bool en_periodic_calib;
+       int pin_count;
+       struct gpio gpios[6];
 };
 
 #endif