soc/tegra: pmc: Add I/O pad voltage support
authorLaxman Dewangan <ldewangan@nvidia.com>
Mon, 10 Oct 2016 13:14:34 +0000 (15:14 +0200)
committerThierry Reding <treding@nvidia.com>
Tue, 15 Nov 2016 14:51:51 +0000 (15:51 +0100)
I/O pins on Tegra SoCs are grouped into so-called I/O pads. Each such
pad can be used to control the common voltage signal level and power
state of the pins in the given pad.

I/O pads can be powered down even if the system is active, which can
save power from that I/O interface. For SoC generations prior to
Tegra124 the I/O pad voltage is automatically detected and hence the
system software doesn't need to configure it. However, starting with
Tegra210 the detection logic has been removed, so explicit control of
the I/O pad voltage by system software is required.

Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/soc/tegra/pmc.c
include/soc/tegra/pmc.h

index d57f3e0f5f2719581e93c165eb65ae7b0a873226..81968ef196184eb098d8c9dd0fc3863bc8f3b28a 100644 (file)
@@ -64,6 +64,8 @@
 
 #define PWRGATE_STATUS                 0x38
 
+#define PMC_PWR_DET                    0x48
+
 #define PMC_SCRATCH0                   0x50
 #define  PMC_SCRATCH0_MODE_RECOVERY    BIT(31)
 #define  PMC_SCRATCH0_MODE_BOOTLOADER  BIT(30)
@@ -75,6 +77,8 @@
 #define PMC_CPUPWRGOOD_TIMER           0xc8
 #define PMC_CPUPWROFF_TIMER            0xcc
 
+#define PMC_PWR_DET_VALUE              0xe4
+
 #define PMC_SCRATCH41                  0x140
 
 #define PMC_SENSOR_CTRL                        0x1b0
@@ -124,6 +128,12 @@ struct tegra_powergate {
        unsigned int num_resets;
 };
 
+struct tegra_io_pad_soc {
+       enum tegra_io_pad id;
+       unsigned int dpd;
+       unsigned int voltage;
+};
+
 struct tegra_pmc_soc {
        unsigned int num_powergates;
        const char *const *powergates;
@@ -132,6 +142,9 @@ struct tegra_pmc_soc {
 
        bool has_tsense_reset;
        bool has_gpu_clamps;
+
+       const struct tegra_io_pad_soc *io_pads;
+       unsigned int num_io_pads;
 };
 
 /**
@@ -908,21 +921,34 @@ static void tegra_powergate_init(struct tegra_pmc *pmc,
        of_node_put(np);
 }
 
-static int tegra_io_rail_prepare(unsigned int id, unsigned long *request,
-                                unsigned long *status, unsigned int *bit)
+static const struct tegra_io_pad_soc *
+tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id)
+{
+       unsigned int i;
+
+       for (i = 0; i < pmc->soc->num_io_pads; i++)
+               if (pmc->soc->io_pads[i].id == id)
+                       return &pmc->soc->io_pads[i];
+
+       return NULL;
+}
+
+static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request,
+                               unsigned long *status, unsigned int *bit)
 {
+       const struct tegra_io_pad_soc *pad;
        unsigned long rate, value;
 
-       *bit = id % 32;
+       pad = tegra_io_pad_find(pmc, id);
+       if (!pad)
+               return -ENOENT;
 
-       /*
-        * There are two sets of 30 bits to select IO rails, but bits 30 and
-        * 31 are control bits rather than IO rail selection bits.
-        */
-       if (id > 63 || *bit == 30 || *bit == 31)
-               return -EINVAL;
+       if (pad->dpd == UINT_MAX)
+               return -ENOTSUPP;
 
-       if (id < 32) {
+       *bit = pad->dpd % 32;
+
+       if (pad->dpd < 32) {
                *status = IO_DPD_STATUS;
                *request = IO_DPD_REQ;
        } else {
@@ -942,8 +968,8 @@ static int tegra_io_rail_prepare(unsigned int id, unsigned long *request,
        return 0;
 }
 
-static int tegra_io_rail_poll(unsigned long offset, u32 mask,
-                             u32 val, unsigned long timeout)
+static int tegra_io_pad_poll(unsigned long offset, u32 mask,
+                            u32 val, unsigned long timeout)
 {
        u32 value;
 
@@ -960,12 +986,18 @@ static int tegra_io_rail_poll(unsigned long offset, u32 mask,
        return -ETIMEDOUT;
 }
 
-static void tegra_io_rail_unprepare(void)
+static void tegra_io_pad_unprepare(void)
 {
        tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
 }
 
-int tegra_io_rail_power_on(unsigned int id)
+/**
+ * tegra_io_pad_power_enable() - enable power to I/O pad
+ * @id: Tegra I/O pad ID for which to enable power
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+int tegra_io_pad_power_enable(enum tegra_io_pad id)
 {
        unsigned long request, status;
        unsigned int bit;
@@ -973,28 +1005,35 @@ int tegra_io_rail_power_on(unsigned int id)
 
        mutex_lock(&pmc->powergates_lock);
 
-       err = tegra_io_rail_prepare(id, &request, &status, &bit);
-       if (err)
-               goto error;
+       err = tegra_io_pad_prepare(id, &request, &status, &bit);
+       if (err < 0) {
+               dev_err(pmc->dev, "tegra_io_pad_prepare() failed: %d\n", err);
+               goto unlock;
+       }
 
        tegra_pmc_writel(IO_DPD_REQ_CODE_OFF | BIT(bit), request);
 
-       err = tegra_io_rail_poll(status, BIT(bit), 0, 250);
-       if (err) {
-               pr_info("tegra_io_rail_poll() failed: %d\n", err);
-               goto error;
+       err = tegra_io_pad_poll(status, BIT(bit), 0, 250);
+       if (err < 0) {
+               dev_err(pmc->dev, "tegra_io_pad_poll() failed: %d\n", err);
+               goto unlock;
        }
 
-       tegra_io_rail_unprepare();
+       tegra_io_pad_unprepare();
 
-error:
+unlock:
        mutex_unlock(&pmc->powergates_lock);
-
        return err;
 }
-EXPORT_SYMBOL(tegra_io_rail_power_on);
+EXPORT_SYMBOL(tegra_io_pad_power_enable);
 
-int tegra_io_rail_power_off(unsigned int id)
+/**
+ * tegra_io_pad_power_disable() - disable power to I/O pad
+ * @id: Tegra I/O pad ID for which to disable power
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+int tegra_io_pad_power_disable(enum tegra_io_pad id)
 {
        unsigned long request, status;
        unsigned int bit;
@@ -1002,25 +1041,109 @@ int tegra_io_rail_power_off(unsigned int id)
 
        mutex_lock(&pmc->powergates_lock);
 
-       err = tegra_io_rail_prepare(id, &request, &status, &bit);
-       if (err) {
-               pr_info("tegra_io_rail_prepare() failed: %d\n", err);
-               goto error;
+       err = tegra_io_pad_prepare(id, &request, &status, &bit);
+       if (err < 0) {
+               dev_err(pmc->dev, "tegra_io_pad_prepare() failed: %d\n", err);
+               goto unlock;
        }
 
        tegra_pmc_writel(IO_DPD_REQ_CODE_ON | BIT(bit), request);
 
-       err = tegra_io_rail_poll(status, BIT(bit), BIT(bit), 250);
-       if (err)
-               goto error;
+       err = tegra_io_pad_poll(status, BIT(bit), BIT(bit), 250);
+       if (err < 0) {
+               dev_err(pmc->dev, "tegra_io_pad_poll() failed: %d\n", err);
+               goto unlock;
+       }
 
-       tegra_io_rail_unprepare();
+       tegra_io_pad_unprepare();
 
-error:
+unlock:
        mutex_unlock(&pmc->powergates_lock);
-
        return err;
 }
+EXPORT_SYMBOL(tegra_io_pad_power_disable);
+
+int tegra_io_pad_set_voltage(enum tegra_io_pad id,
+                            enum tegra_io_pad_voltage voltage)
+{
+       const struct tegra_io_pad_soc *pad;
+       u32 value;
+
+       pad = tegra_io_pad_find(pmc, id);
+       if (!pad)
+               return -ENOENT;
+
+       if (pad->voltage == UINT_MAX)
+               return -ENOTSUPP;
+
+       mutex_lock(&pmc->powergates_lock);
+
+       /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */
+       value = tegra_pmc_readl(PMC_PWR_DET);
+       value |= BIT(pad->voltage);
+       tegra_pmc_writel(value, PMC_PWR_DET);
+
+       /* update I/O voltage */
+       value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
+
+       if (voltage == TEGRA_IO_PAD_1800000UV)
+               value &= ~BIT(pad->voltage);
+       else
+               value |= BIT(pad->voltage);
+
+       tegra_pmc_writel(value, PMC_PWR_DET_VALUE);
+
+       mutex_unlock(&pmc->powergates_lock);
+
+       usleep_range(100, 250);
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_io_pad_set_voltage);
+
+int tegra_io_pad_get_voltage(enum tegra_io_pad id)
+{
+       const struct tegra_io_pad_soc *pad;
+       u32 value;
+
+       pad = tegra_io_pad_find(pmc, id);
+       if (!pad)
+               return -ENOENT;
+
+       if (pad->voltage == UINT_MAX)
+               return -ENOTSUPP;
+
+       value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
+
+       if ((value & BIT(pad->voltage)) == 0)
+               return TEGRA_IO_PAD_1800000UV;
+
+       return TEGRA_IO_PAD_3300000UV;
+}
+EXPORT_SYMBOL(tegra_io_pad_get_voltage);
+
+/**
+ * tegra_io_rail_power_on() - enable power to I/O rail
+ * @id: Tegra I/O pad ID for which to enable power
+ *
+ * See also: tegra_io_pad_power_enable()
+ */
+int tegra_io_rail_power_on(unsigned int id)
+{
+       return tegra_io_pad_power_enable(id);
+}
+EXPORT_SYMBOL(tegra_io_rail_power_on);
+
+/**
+ * tegra_io_rail_power_off() - disable power to I/O rail
+ * @id: Tegra I/O pad ID for which to disable power
+ *
+ * See also: tegra_io_pad_power_disable()
+ */
+int tegra_io_rail_power_off(unsigned int id)
+{
+       return tegra_io_pad_power_disable(id);
+}
 EXPORT_SYMBOL(tegra_io_rail_power_off);
 
 #ifdef CONFIG_PM_SLEEP
@@ -1454,6 +1577,39 @@ static const u8 tegra124_cpu_powergates[] = {
        TEGRA_POWERGATE_CPU3,
 };
 
+static const struct tegra_io_pad_soc tegra124_io_pads[] = {
+       { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_BB, .dpd = 15, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CAM, .dpd = 36, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_COMP, .dpd = 22, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSIE, .dpd = 44, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_DSI, .dpd = 2, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_DSIB, .dpd = 39, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_DSIC, .dpd = 40, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_DSID, .dpd = 41, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_HDMI, .dpd = 28, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_HSIC, .dpd = 19, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_HV, .dpd = 38, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_LVDS, .dpd = 57, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_NAND, .dpd = 13, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_BIAS, .dpd = 4, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 5, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = 32, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_SDMMC1, .dpd = 33, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_SDMMC3, .dpd = 34, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_SDMMC4, .dpd = 35, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_SYS_DDC, .dpd = 58, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_USB0, .dpd = 9, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_USB1, .dpd = 10, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_USB2, .dpd = 11, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_USB_BIAS, .dpd = 12, .voltage = UINT_MAX },
+};
+
 static const struct tegra_pmc_soc tegra124_pmc_soc = {
        .num_powergates = ARRAY_SIZE(tegra124_powergates),
        .powergates = tegra124_powergates,
@@ -1461,6 +1617,8 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
        .cpu_powergates = tegra124_cpu_powergates,
        .has_tsense_reset = true,
        .has_gpu_clamps = true,
+       .num_io_pads = ARRAY_SIZE(tegra124_io_pads),
+       .io_pads = tegra124_io_pads,
 };
 
 static const char * const tegra210_powergates[] = {
@@ -1497,6 +1655,47 @@ static const u8 tegra210_cpu_powergates[] = {
        TEGRA_POWERGATE_CPU3,
 };
 
+static const struct tegra_io_pad_soc tegra210_io_pads[] = {
+       { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = 5 },
+       { .id = TEGRA_IO_PAD_AUDIO_HV, .dpd = 61, .voltage = 18 },
+       { .id = TEGRA_IO_PAD_CAM, .dpd = 36, .voltage = 10 },
+       { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSIC, .dpd = 42, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSID, .dpd = 43, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSIE, .dpd = 44, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSIF, .dpd = 45, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_DBG, .dpd = 25, .voltage = 19 },
+       { .id = TEGRA_IO_PAD_DEBUG_NONAO, .dpd = 26, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_DMIC, .dpd = 50, .voltage = 20 },
+       { .id = TEGRA_IO_PAD_DP, .dpd = 51, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_DSI, .dpd = 2, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_DSIB, .dpd = 39, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_DSIC, .dpd = 40, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_DSID, .dpd = 41, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_EMMC, .dpd = 35, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_EMMC2, .dpd = 37, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_GPIO, .dpd = 27, .voltage = 21 },
+       { .id = TEGRA_IO_PAD_HDMI, .dpd = 28, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_HSIC, .dpd = 19, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_LVDS, .dpd = 57, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_BIAS, .dpd = 4, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 5, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = UINT_MAX, .voltage = 11 },
+       { .id = TEGRA_IO_PAD_SDMMC1, .dpd = 33, .voltage = 12 },
+       { .id = TEGRA_IO_PAD_SDMMC3, .dpd = 34, .voltage = 13 },
+       { .id = TEGRA_IO_PAD_SPI, .dpd = 46, .voltage = 22 },
+       { .id = TEGRA_IO_PAD_SPI_HV, .dpd = 47, .voltage = 23 },
+       { .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = 2 },
+       { .id = TEGRA_IO_PAD_USB0, .dpd = 9, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_USB1, .dpd = 10, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_USB2, .dpd = 11, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_USB3, .dpd = 18, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_USB_BIAS, .dpd = 12, .voltage = UINT_MAX },
+};
+
 static const struct tegra_pmc_soc tegra210_pmc_soc = {
        .num_powergates = ARRAY_SIZE(tegra210_powergates),
        .powergates = tegra210_powergates,
@@ -1504,6 +1703,8 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
        .cpu_powergates = tegra210_cpu_powergates,
        .has_tsense_reset = true,
        .has_gpu_clamps = true,
+       .num_io_pads = ARRAY_SIZE(tegra210_io_pads),
+       .io_pads = tegra210_io_pads,
 };
 
 static const struct of_device_id tegra_pmc_match[] = {
index e9e53473a63e528bc96957bf1cd2a552993d6b20..2f271d1b9cea6fdc9bb1678077eab3222ea3bf92 100644 (file)
@@ -76,37 +76,73 @@ int tegra_pmc_cpu_remove_clamping(unsigned int cpuid);
 
 #define TEGRA_POWERGATE_3D0    TEGRA_POWERGATE_3D
 
-#define TEGRA_IO_RAIL_CSIA     0
-#define TEGRA_IO_RAIL_CSIB     1
-#define TEGRA_IO_RAIL_DSI      2
-#define TEGRA_IO_RAIL_MIPI_BIAS        3
-#define TEGRA_IO_RAIL_PEX_BIAS 4
-#define TEGRA_IO_RAIL_PEX_CLK1 5
-#define TEGRA_IO_RAIL_PEX_CLK2 6
-#define TEGRA_IO_RAIL_USB0     9
-#define TEGRA_IO_RAIL_USB1     10
-#define TEGRA_IO_RAIL_USB2     11
-#define TEGRA_IO_RAIL_USB_BIAS 12
-#define TEGRA_IO_RAIL_NAND     13
-#define TEGRA_IO_RAIL_UART     14
-#define TEGRA_IO_RAIL_BB       15
-#define TEGRA_IO_RAIL_AUDIO    17
-#define TEGRA_IO_RAIL_HSIC     19
-#define TEGRA_IO_RAIL_COMP     22
-#define TEGRA_IO_RAIL_HDMI     28
-#define TEGRA_IO_RAIL_PEX_CNTRL        32
-#define TEGRA_IO_RAIL_SDMMC1   33
-#define TEGRA_IO_RAIL_SDMMC3   34
-#define TEGRA_IO_RAIL_SDMMC4   35
-#define TEGRA_IO_RAIL_CAM      36
-#define TEGRA_IO_RAIL_RES      37
-#define TEGRA_IO_RAIL_HV       38
-#define TEGRA_IO_RAIL_DSIB     39
-#define TEGRA_IO_RAIL_DSIC     40
-#define TEGRA_IO_RAIL_DSID     41
-#define TEGRA_IO_RAIL_CSIE     44
-#define TEGRA_IO_RAIL_LVDS     57
-#define TEGRA_IO_RAIL_SYS_DDC  58
+/**
+ * enum tegra_io_pad - I/O pad group identifier
+ *
+ * I/O pins on Tegra SoCs are grouped into so-called I/O pads. Each such pad
+ * can be used to control the common voltage signal level and power state of
+ * the pins of the given pad.
+ */
+enum tegra_io_pad {
+       TEGRA_IO_PAD_AUDIO,
+       TEGRA_IO_PAD_AUDIO_HV,
+       TEGRA_IO_PAD_BB,
+       TEGRA_IO_PAD_CAM,
+       TEGRA_IO_PAD_COMP,
+       TEGRA_IO_PAD_CSIA,
+       TEGRA_IO_PAD_CSIB,
+       TEGRA_IO_PAD_CSIC,
+       TEGRA_IO_PAD_CSID,
+       TEGRA_IO_PAD_CSIE,
+       TEGRA_IO_PAD_CSIF,
+       TEGRA_IO_PAD_DBG,
+       TEGRA_IO_PAD_DEBUG_NONAO,
+       TEGRA_IO_PAD_DMIC,
+       TEGRA_IO_PAD_DP,
+       TEGRA_IO_PAD_DSI,
+       TEGRA_IO_PAD_DSIB,
+       TEGRA_IO_PAD_DSIC,
+       TEGRA_IO_PAD_DSID,
+       TEGRA_IO_PAD_EMMC,
+       TEGRA_IO_PAD_EMMC2,
+       TEGRA_IO_PAD_GPIO,
+       TEGRA_IO_PAD_HDMI,
+       TEGRA_IO_PAD_HSIC,
+       TEGRA_IO_PAD_HV,
+       TEGRA_IO_PAD_LVDS,
+       TEGRA_IO_PAD_MIPI_BIAS,
+       TEGRA_IO_PAD_NAND,
+       TEGRA_IO_PAD_PEX_BIAS,
+       TEGRA_IO_PAD_PEX_CLK1,
+       TEGRA_IO_PAD_PEX_CLK2,
+       TEGRA_IO_PAD_PEX_CNTRL,
+       TEGRA_IO_PAD_SDMMC1,
+       TEGRA_IO_PAD_SDMMC3,
+       TEGRA_IO_PAD_SDMMC4,
+       TEGRA_IO_PAD_SPI,
+       TEGRA_IO_PAD_SPI_HV,
+       TEGRA_IO_PAD_SYS_DDC,
+       TEGRA_IO_PAD_UART,
+       TEGRA_IO_PAD_USB0,
+       TEGRA_IO_PAD_USB1,
+       TEGRA_IO_PAD_USB2,
+       TEGRA_IO_PAD_USB3,
+       TEGRA_IO_PAD_USB_BIAS,
+};
+
+/* deprecated, use TEGRA_IO_PAD_{HDMI,LVDS} instead */
+#define TEGRA_IO_RAIL_HDMI     TEGRA_IO_PAD_HDMI
+#define TEGRA_IO_RAIL_LVDS     TEGRA_IO_PAD_LVDS
+
+/**
+ * enum tegra_io_pad_voltage - voltage level of the I/O pad's source rail
+ * @TEGRA_IO_PAD_1800000UV: 1.8 V
+ * @TEGRA_IO_PAD_3300000UV: 3.3 V
+ */
+enum tegra_io_pad_voltage {
+       TEGRA_IO_PAD_1800000UV,
+       TEGRA_IO_PAD_3300000UV,
+};
 
 #ifdef CONFIG_ARCH_TEGRA
 int tegra_powergate_is_powered(unsigned int id);
@@ -118,6 +154,13 @@ int tegra_powergate_remove_clamping(unsigned int id);
 int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
                                      struct reset_control *rst);
 
+int tegra_io_pad_power_enable(enum tegra_io_pad id);
+int tegra_io_pad_power_disable(enum tegra_io_pad id);
+int tegra_io_pad_set_voltage(enum tegra_io_pad id,
+                            enum tegra_io_pad_voltage voltage);
+int tegra_io_pad_get_voltage(enum tegra_io_pad id);
+
+/* deprecated, use tegra_io_pad_power_{enable,disable}() instead */
 int tegra_io_rail_power_on(unsigned int id);
 int tegra_io_rail_power_off(unsigned int id);
 #else
@@ -148,6 +191,27 @@ static inline int tegra_powergate_sequence_power_up(unsigned int id,
        return -ENOSYS;
 }
 
+static inline int tegra_io_pad_power_enable(enum tegra_io_pad id)
+{
+       return -ENOSYS;
+}
+
+static inline int tegra_io_pad_power_disable(enum tegra_io_pad id)
+{
+       return -ENOSYS;
+}
+
+static inline int tegra_io_pad_set_voltage(enum tegra_io_pad id,
+                                          enum tegra_io_pad_voltage voltage)
+{
+       return -ENOSYS;
+}
+
+static inline int tegra_io_pad_get_voltage(enum tegra_io_pad id)
+{
+       return -ENOSYS;
+}
+
 static inline int tegra_io_rail_power_on(unsigned int id)
 {
        return -ENOSYS;