2018-07-12 12:01:08

by Aapo Vienamo

[permalink] [raw]
Subject: [PATCH v3 0/7] Tegra PMC pinctrl pad configuration

Hi all,

The Tegra Power Management Controller (PMC) can set pad power states
and voltage configuration. This series implements pinctrl interfaces
for configuring said pad properties.

Changelog
v3:
- Don't expose tegra_io_pad_is_powered()
- Remove tegra_io_pad_set_voltage() stub from pmc.h
- Fixes i386 build failure reported by kbuild test robot
v2:
- Add Tegra186 AO_HV pad
- Make the IO pad tables narrower
- Add parens to TEGRA_IO_PAD() and TEGRA_IO_PIN_DESC()
- Fix a typo in the dt-bindings docs
- Remove old pmc pad voltage configuration APIs
- Check return value of tegra_io_pad_find() in
tegra_io_pad_pinconf_get()/_set()

Aapo Vienamo (7):
soc/tegra: pmc: Fix pad voltage configuration for Tegra186
soc/tegra: pmc: Factor out DPD register bit calculation
soc/tegra: pmc: Implement tegra_io_pad_is_powered()
soc/tegra: pmc: Use X macro to generate IO pad tables
dt-bindings: Add Tegra PMC pad configuration bindings
soc/tegra: pmc: Remove public pad voltage APIs
soc/tegra: pmc: Implement pad configuration via pinctrl

.../bindings/arm/tegra/nvidia,tegra186-pmc.txt | 84 ++++
.../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 95 ++++
drivers/soc/tegra/pmc.c | 512 +++++++++++++++------
include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h | 18 +
include/soc/tegra/pmc.h | 20 +-
5 files changed, 581 insertions(+), 148 deletions(-)
create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h

--
2.7.4



2018-07-12 12:01:17

by Aapo Vienamo

[permalink] [raw]
Subject: [PATCH v3 3/7] soc/tegra: pmc: Implement tegra_io_pad_is_powered()

Implement a function to query whether a pad is in deep power down mode.
This will is needed by the pinctrl callbacks.

Signed-off-by: Aapo Vienamo <[email protected]>
Acked-by: Jon Hunter <[email protected]>
---
drivers/soc/tegra/pmc.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 393ca72..784c182 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1075,6 +1075,22 @@ int tegra_io_pad_power_disable(enum tegra_io_pad id)
}
EXPORT_SYMBOL(tegra_io_pad_power_disable);

+static int tegra_io_pad_is_powered(enum tegra_io_pad id)
+{
+ unsigned long request, status;
+ u32 mask;
+ u32 value;
+ int err;
+
+ err = tegra_io_pad_get_dpd_register_bit(id, &request, &status, &mask);
+ if (err)
+ return err;
+
+ value = tegra_pmc_readl(status);
+
+ return !(value & mask);
+}
+
int tegra_io_pad_set_voltage(enum tegra_io_pad id,
enum tegra_io_pad_voltage voltage)
{
--
2.7.4


2018-07-12 12:01:54

by Aapo Vienamo

[permalink] [raw]
Subject: [PATCH v3 2/7] soc/tegra: pmc: Factor out DPD register bit calculation

Factor out the the code to calculate the correct DPD register and bit
number for a given pad. This logic will be needed to query the status
register.

Signed-off-by: Aapo Vienamo <[email protected]>
Acked-by: Jon Hunter <[email protected]>
---
drivers/soc/tegra/pmc.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index f926332..393ca72 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -922,11 +922,12 @@ tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id)
return NULL;
}

-static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request,
- unsigned long *status, u32 *mask)
+static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id,
+ unsigned long *request,
+ unsigned long *status,
+ u32 *mask)
{
const struct tegra_io_pad_soc *pad;
- unsigned long rate, value;

pad = tegra_io_pad_find(pmc, id);
if (!pad) {
@@ -947,6 +948,19 @@ static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request,
*request = pmc->soc->regs->dpd2_req;
}

+ return 0;
+}
+
+static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request,
+ unsigned long *status, u32 *mask)
+{
+ unsigned long rate, value;
+ int err;
+
+ err = tegra_io_pad_get_dpd_register_bit(id, request, status, mask);
+ if (err)
+ return err;
+
if (pmc->clk) {
rate = clk_get_rate(pmc->clk);
if (!rate) {
--
2.7.4


2018-07-12 12:01:59

by Aapo Vienamo

[permalink] [raw]
Subject: [PATCH v3 4/7] soc/tegra: pmc: Use X macro to generate IO pad tables

Refactor the IO pad tables into macro tables so that they can be reused
to generate pinctrl pin descriptors. Also add a name field which is
needed by pinctrl.

Signed-off-by: Aapo Vienamo <[email protected]>
---
drivers/soc/tegra/pmc.c | 233 ++++++++++++++++++++++++++----------------------
1 file changed, 127 insertions(+), 106 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 784c182..38cb915 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -137,6 +137,7 @@ struct tegra_io_pad_soc {
enum tegra_io_pad id;
unsigned int dpd;
unsigned int voltage;
+ const char *name;
};

struct tegra_pmc_regs {
@@ -1696,37 +1697,49 @@ static const u8 tegra124_cpu_powergates[] = {
TEGRA_POWERGATE_CPU3,
};

+#define TEGRA_IO_PAD(_id, _dpd, _voltage, _name) \
+ ((struct tegra_io_pad_soc) { \
+ .id = (_id), \
+ .dpd = (_dpd), \
+ .voltage = (_voltage), \
+ .name = (_name), \
+ })
+
+#define TEGRA124_IO_PAD_TABLE(_pad) \
+ /* .id .dpd .voltage .name */ \
+ _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \
+ _pad(TEGRA_IO_PAD_BB, 15, UINT_MAX, "bb"), \
+ _pad(TEGRA_IO_PAD_CAM, 36, UINT_MAX, "cam"), \
+ _pad(TEGRA_IO_PAD_COMP, 22, UINT_MAX, "comp"), \
+ _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \
+ _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csb"), \
+ _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "cse"), \
+ _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \
+ _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"), \
+ _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"), \
+ _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"), \
+ _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"), \
+ _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \
+ _pad(TEGRA_IO_PAD_HV, 38, UINT_MAX, "hv"), \
+ _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"), \
+ _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \
+ _pad(TEGRA_IO_PAD_NAND, 13, UINT_MAX, "nand"), \
+ _pad(TEGRA_IO_PAD_PEX_BIAS, 4, UINT_MAX, "pex-bias"), \
+ _pad(TEGRA_IO_PAD_PEX_CLK1, 5, UINT_MAX, "pex-clk1"), \
+ _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \
+ _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \
+ _pad(TEGRA_IO_PAD_SDMMC1, 33, UINT_MAX, "sdmmc1"), \
+ _pad(TEGRA_IO_PAD_SDMMC3, 34, UINT_MAX, "sdmmc3"), \
+ _pad(TEGRA_IO_PAD_SDMMC4, 35, UINT_MAX, "sdmmc4"), \
+ _pad(TEGRA_IO_PAD_SYS_DDC, 58, UINT_MAX, "sys_ddc"), \
+ _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \
+ _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \
+ _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \
+ _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \
+ _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb_bias")
+
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 },
+ TEGRA124_IO_PAD_TABLE(TEGRA_IO_PAD)
};

static const struct tegra_pmc_soc tegra124_pmc_soc = {
@@ -1778,45 +1791,49 @@ static const u8 tegra210_cpu_powergates[] = {
TEGRA_POWERGATE_CPU3,
};

+#define TEGRA210_IO_PAD_TABLE(_pad) \
+ /* .id .dpd .voltage .name */ \
+ _pad(TEGRA_IO_PAD_AUDIO, 17, 5, "audio"), \
+ _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 18, "audio-hv"), \
+ _pad(TEGRA_IO_PAD_CAM, 36, 10, "cam"), \
+ _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \
+ _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \
+ _pad(TEGRA_IO_PAD_CSIC, 42, UINT_MAX, "csic"), \
+ _pad(TEGRA_IO_PAD_CSID, 43, UINT_MAX, "csid"), \
+ _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "csie"), \
+ _pad(TEGRA_IO_PAD_CSIF, 45, UINT_MAX, "csif"), \
+ _pad(TEGRA_IO_PAD_DBG, 25, 19, "dbg"), \
+ _pad(TEGRA_IO_PAD_DEBUG_NONAO, 26, UINT_MAX, "debug-nonao"), \
+ _pad(TEGRA_IO_PAD_DMIC, 50, 20, "dmic"), \
+ _pad(TEGRA_IO_PAD_DP, 51, UINT_MAX, "dp"), \
+ _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \
+ _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"), \
+ _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"), \
+ _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"), \
+ _pad(TEGRA_IO_PAD_EMMC, 35, UINT_MAX, "emmc"), \
+ _pad(TEGRA_IO_PAD_EMMC2, 37, UINT_MAX, "emmc2"), \
+ _pad(TEGRA_IO_PAD_GPIO, 27, 21, "gpio"), \
+ _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"), \
+ _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \
+ _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"), \
+ _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \
+ _pad(TEGRA_IO_PAD_PEX_BIAS, 4, UINT_MAX, "pex-bias"), \
+ _pad(TEGRA_IO_PAD_PEX_CLK1, 5, UINT_MAX, "pex-clk1"), \
+ _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \
+ _pad(TEGRA_IO_PAD_PEX_CNTRL, UINT_MAX, 11, "pex-cntrl"), \
+ _pad(TEGRA_IO_PAD_SDMMC1, 33, 12, "sdmmc1"), \
+ _pad(TEGRA_IO_PAD_SDMMC3, 34, 13, "sdmmc3"), \
+ _pad(TEGRA_IO_PAD_SPI, 46, 22, "spi"), \
+ _pad(TEGRA_IO_PAD_SPI_HV, 47, 23, "spi-hv"), \
+ _pad(TEGRA_IO_PAD_UART, 14, 2, "uart"), \
+ _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \
+ _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \
+ _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \
+ _pad(TEGRA_IO_PAD_USB3, 18, UINT_MAX, "usb3"), \
+ _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb-bias")
+
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 },
+ TEGRA210_IO_PAD_TABLE(TEGRA_IO_PAD)
};

static const struct tegra_pmc_soc tegra210_pmc_soc = {
@@ -1835,45 +1852,49 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
};

+#define TEGRA186_IO_PAD_TABLE(_pad) \
+ /* .id .dpd .voltage .name */ \
+ _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \
+ _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \
+ _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \
+ _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \
+ _pad(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, UINT_MAX, "pex-clk-bias"), \
+ _pad(TEGRA_IO_PAD_PEX_CLK3, 5, UINT_MAX, "pex-clk3"), \
+ _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \
+ _pad(TEGRA_IO_PAD_PEX_CLK1, 7, UINT_MAX, "pex-clk1"), \
+ _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \
+ _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \
+ _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \
+ _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb-bias"), \
+ _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \
+ _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \
+ _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \
+ _pad(TEGRA_IO_PAD_DBG, 25, UINT_MAX, "dbg"), \
+ _pad(TEGRA_IO_PAD_HDMI_DP0, 28, UINT_MAX, "hdmi-dp0"), \
+ _pad(TEGRA_IO_PAD_HDMI_DP1, 29, UINT_MAX, "hdmi-dp1"), \
+ _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \
+ _pad(TEGRA_IO_PAD_SDMMC2_HV, 34, 5, "sdmmc2-hv"), \
+ _pad(TEGRA_IO_PAD_SDMMC4, 36, UINT_MAX, "sdmmc4"), \
+ _pad(TEGRA_IO_PAD_CAM, 38, UINT_MAX, "cam"), \
+ _pad(TEGRA_IO_PAD_DSIB, 40, UINT_MAX, "dsib"), \
+ _pad(TEGRA_IO_PAD_DSIC, 41, UINT_MAX, "dsic"), \
+ _pad(TEGRA_IO_PAD_DSID, 42, UINT_MAX, "dsid"), \
+ _pad(TEGRA_IO_PAD_CSIC, 43, UINT_MAX, "csic"), \
+ _pad(TEGRA_IO_PAD_CSID, 44, UINT_MAX, "csid"), \
+ _pad(TEGRA_IO_PAD_CSIE, 45, UINT_MAX, "csie"), \
+ _pad(TEGRA_IO_PAD_CSIF, 46, UINT_MAX, "csif"), \
+ _pad(TEGRA_IO_PAD_SPI, 47, UINT_MAX, "spi"), \
+ _pad(TEGRA_IO_PAD_UFS, 49, UINT_MAX, "ufs"), \
+ _pad(TEGRA_IO_PAD_DMIC_HV, 52, 2, "dmic-hv"), \
+ _pad(TEGRA_IO_PAD_EDP, 53, UINT_MAX, "edp"), \
+ _pad(TEGRA_IO_PAD_SDMMC1_HV, 55, 4, "sdmmc1-hv"), \
+ _pad(TEGRA_IO_PAD_SDMMC3_HV, 56, 6, "sdmmc3-hv"), \
+ _pad(TEGRA_IO_PAD_CONN, 60, UINT_MAX, "conn"), \
+ _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 1, "audio-hv"), \
+ _pad(TEGRA_IO_PAD_AO_HV, UINT_MAX, 0, "ao-hv")
+
static const struct tegra_io_pad_soc tegra186_io_pads[] = {
- { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_DSI, .dpd = 2, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_PEX_CLK_BIAS, .dpd = 4, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_PEX_CLK3, .dpd = 5, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 7, .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 },
- { .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_HSIC, .dpd = 19, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_DBG, .dpd = 25, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_HDMI_DP0, .dpd = 28, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_HDMI_DP1, .dpd = 29, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = 32, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_SDMMC2_HV, .dpd = 34, .voltage = 5 },
- { .id = TEGRA_IO_PAD_SDMMC4, .dpd = 36, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_CAM, .dpd = 38, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_DSIB, .dpd = 40, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_DSIC, .dpd = 41, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_DSID, .dpd = 42, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_CSIC, .dpd = 43, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_CSID, .dpd = 44, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_CSIE, .dpd = 45, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_CSIF, .dpd = 46, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_SPI, .dpd = 47, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_UFS, .dpd = 49, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_DMIC_HV, .dpd = 52, .voltage = 2 },
- { .id = TEGRA_IO_PAD_EDP, .dpd = 53, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_SDMMC1_HV, .dpd = 55, .voltage = 4 },
- { .id = TEGRA_IO_PAD_SDMMC3_HV, .dpd = 56, .voltage = 6 },
- { .id = TEGRA_IO_PAD_CONN, .dpd = 60, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_AUDIO_HV, .dpd = 61, .voltage = 1 },
- { .id = TEGRA_IO_PAD_AO_HV, .dpd = UINT_MAX, .voltage = 0 },
+ TEGRA186_IO_PAD_TABLE(TEGRA_IO_PAD)
};

static const struct tegra_pmc_regs tegra186_pmc_regs = {
--
2.7.4


2018-07-12 12:02:02

by Aapo Vienamo

[permalink] [raw]
Subject: [PATCH v3 5/7] dt-bindings: Add Tegra PMC pad configuration bindings

Document the pinctrl bindings used by the PMC driver for performing pad
configuration. Both nvidia,tegra186-pmc.txt and nvidia,tegra20-pmc.txt
are modified as they both cover SoC generations for which these bindings
apply.

Add a header defining Tegra PMC pad voltage configurations.

Signed-off-by: Aapo Vienamo <[email protected]>
Acked-by: Jon Hunter <[email protected]>
---
.../bindings/arm/tegra/nvidia,tegra186-pmc.txt | 84 +++++++++++++++++++
.../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 95 ++++++++++++++++++++++
include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h | 18 ++++
3 files changed, 197 insertions(+)
create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h

diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
index 5a3bf7c..9528f41 100644
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
@@ -34,3 +34,87 @@ Board DTS:
pmc@c360000 {
nvidia,invert-interrupt;
};
+
+== Pad Control Nodes ==
+
+The PMC can be used to set pad power state and voltage configuration.
+The pad configuration is done via the pinctrl framework. The driver
+implements power-source, low-power-enable, and low-power-disable pinconf
+pin configuration node properties. Each pinctrl pin corresponds to a
+single Tegra PMC pad. Thus, in the following sections of this document
+pin refers to the pinctrl frameworks notion of a Tegra PMC pad.
+
+The pad configuration state nodes are placed under the pmc node and they
+are referred to by the pinctrl client device properties. For more
+information see the examples presented later and
+Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt.
+
+The values accepted by power-source property are
+TEGRA_IO_PAD_VOLTAGE_1V8 and TEGRA_IO_PAD_VOLTAGE_3V3, which are defined
+in dt-bindings/pinctrl/pinctrl-tegra-io-pad.h.
+
+Following pinctrl pin name strings are present on Tegra186:
+csia csib dsi mipi-bias
+pex-clk-bias pex-clk3 pex-clk2 pex-clk1
+usb0 usb1 usb2 usb-bias
+uart audio hsic dbg
+hdmi-dp0 hdmi-dp1 pex-cntrl sdmmc2-hv
+sdmmc4 cam dsib dsic
+dsid csic csid csie
+dsif spi ufs dmic-hv
+edp sdmmc1-hv sdmmc3-hv conn
+audio-hv ao-hv
+
+All of the listed Tegra186 pins except ao-hv support the
+low-power-enable and low-power-disable properties. The power-source
+property is supported following Tegra210 pins: sdmmc2-hv, dmic-hv,
+sdmmc1-hv, sdmmc3-hv, audio-hv, ao-hv.
+
+Pad configuration state example:
+ pmc: pmc@7000e400 {
+ compatible = "nvidia,tegra186-pmc";
+ reg = <0 0x0c360000 0 0x10000>,
+ <0 0x0c370000 0 0x10000>,
+ <0 0x0c380000 0 0x10000>,
+ <0 0x0c390000 0 0x10000>;
+ reg-names = "pmc", "wake", "aotag", "scratch";
+
+ ...
+
+ sdmmc1_3v3: sdmmc1-3v3 {
+ pins = "sdmmc1-hv";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>;
+ };
+
+ sdmmc1_1v8: sdmmc1-1v8 {
+ pins = "sdmmc1-hv";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>;
+ };
+
+ hdmi_off: hdmi-off {
+ pins = "hdmi";
+ low-power-enable;
+ }
+
+ hdmi_on: hdmi-on {
+ pins = "hdmi";
+ low-power-disable;
+ }
+ };
+
+Pinctrl client example:
+ sdmmc1: sdhci@3400000 {
+ ...
+ pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+ pinctrl-0 = <&sdmmc1_3v3>;
+ pinctrl-1 = <&sdmmc1_1v8>;
+ };
+
+ ...
+
+ sor0: sor@15540000 {
+ ...
+ pinctrl-0 = <&hdmi_off>;
+ pinctrl-1 = <&hdmi_on>;
+ pinctrl-names = "hdmi-on", "hdmi-off";
+ };
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
index a74b37b..d50a505 100644
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
@@ -195,3 +195,98 @@ Example:
power-domains = <&pd_audio>;
...
};
+
+== Pad Control Nodes ==
+
+The PMC can be used to set pad power state and voltage configuration.
+This functionality is present on SoCs from Tegra124 onwards. The pad
+configuration is done via the pinctrl framework. The driver implements
+power-source, low-power-enable, and low-power-disable pinconf pin
+configuration node properties. Each pinctrl pin corresponds to a single
+Tegra PMC pad. Thus, in the following sections of this document pin
+refers to the pinctrl frameworks notion of a Tegra PMC pad.
+
+The pad configuration state nodes are placed under the pmc node and they
+are referred to by the pinctrl client device properties. For more
+information see the examples presented later and
+Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt.
+
+The values accepted by power-source property are
+TEGRA_IO_PAD_VOLTAGE_1V8 and TEGRA_IO_PAD_VOLTAGE_3V3, which are defined
+in dt-bindings/pinctrl/pinctrl-tegra-io-pad.h.
+
+Following pinctrl pin name strings are present on Tegra124 and Tegra132:
+audio bb cam comp
+csia csb cse dsi
+dsib dsic dsid hdmi
+hsic hv lvds mipi-bias
+nand pex-bias pex-clk1 pex-clk2
+pex-cntrl sdmmc1 sdmmc3 sdmmc4
+sys_ddc uart usb0 usb1
+usb2 usb_bias
+
+All of the listed Tegra124 and Tegra132 pins support the
+low-power-enable and low-power-disable properties. None of the pins
+support the power-source property.
+
+Following pinctrl pin name strings are present on Tegra210:
+audio audio-hv cam csia
+csib csic csid csie
+csif dbg debug-nonao dmic
+dp dsi dsib dsic
+dsid emmc emmc2 gpio
+hdmi hsic lvds mipi-bias
+pex-bias pex-clk1 pex-clk2 pex-cntrl
+sdmmc1 sdmmc3 spi spi-hv
+uart usb0 usb1 usb2
+usb3 usb-bias
+
+All of the listed Tegra210 pins except pex-cntrl support the
+low-power-enable and low-power-disable properties. The power-source
+property is supported following Tegra210 pins: audio, audio-hv, cam,
+dbg, dmic, gpio, pex-cntrl, sdmmc1, sdmmc3, spi, spi-hv, and uart.
+
+Pad configuration state example:
+ pmc: pmc@7000e400 {
+ compatible = "nvidia,tegra210-pmc";
+ reg = <0x0 0x7000e400 0x0 0x400>;
+ clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
+ clock-names = "pclk", "clk32k_in";
+
+ ...
+
+ sdmmc1_3v3: sdmmc1-3v3 {
+ pins = "sdmmc1";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>;
+ };
+
+ sdmmc1_1v8: sdmmc1-1v8 {
+ pins = "sdmmc1";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>;
+ };
+
+ hdmi_off: hdmi-off {
+ pins = "hdmi";
+ low-power-enable;
+ }
+
+ hdmi_on: hdmi-on {
+ pins = "hdmi";
+ low-power-disable;
+ }
+ };
+
+Pinctrl client example:
+ sdmmc1: sdhci@700b0000 {
+ ...
+ pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+ pinctrl-0 = <&sdmmc1_3v3>;
+ pinctrl-1 = <&sdmmc1_1v8>;
+ };
+ ...
+ sor@54540000 {
+ ...
+ pinctrl-0 = <&hdmi_off>;
+ pinctrl-1 = <&hdmi_on>;
+ pinctrl-names = "hdmi-on", "hdmi-off";
+ };
diff --git a/include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h b/include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h
new file mode 100644
index 0000000..20f4340
--- /dev/null
+++ b/include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * pinctrl-tegra-io-pad.h: Tegra I/O pad source voltage configuration constants
+ * pinctrl bindings.
+ *
+ * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Author: Aapo Vienamo <[email protected]>
+ */
+
+#ifndef _DT_BINDINGS_PINCTRL_TEGRA_IO_PAD_H
+#define _DT_BINDINGS_PINCTRL_TEGRA_IO_PAD_H
+
+/* Voltage levels of the I/O pad's source rail */
+#define TEGRA_IO_PAD_VOLTAGE_1V8 0
+#define TEGRA_IO_PAD_VOLTAGE_3V3 1
+
+#endif
--
2.7.4


2018-07-12 12:02:06

by Aapo Vienamo

[permalink] [raw]
Subject: [PATCH v3 6/7] soc/tegra: pmc: Remove public pad voltage APIs

Make tegra_io_pad_set_voltage() and tegra_io_pad_get_voltage() static
and remove the prototypes from pmc.h. Remove enum tegra_io_pad_voltage
and use the defines from <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h>
instead.

These functions aren't used outside of the pmc driver and new use cases
should use the pinctrl interface instead.

Signed-off-by: Aapo Vienamo <[email protected]>
Acked-by: Jon Hunter <[email protected]>
---
drivers/soc/tegra/pmc.c | 17 ++++++++---------
include/soc/tegra/pmc.h | 19 -------------------
2 files changed, 8 insertions(+), 28 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 38cb915..7d3c3de 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -45,6 +45,8 @@
#include <soc/tegra/fuse.h>
#include <soc/tegra/pmc.h>

+#include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h>
+
#define PMC_CNTRL 0x0
#define PMC_CNTRL_INTR_POLARITY BIT(17) /* inverts INTR polarity */
#define PMC_CNTRL_CPU_PWRREQ_OE BIT(16) /* CPU pwr req enable */
@@ -1092,8 +1094,7 @@ static int tegra_io_pad_is_powered(enum tegra_io_pad id)
return !(value & mask);
}

-int tegra_io_pad_set_voltage(enum tegra_io_pad id,
- enum tegra_io_pad_voltage voltage)
+static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage)
{
const struct tegra_io_pad_soc *pad;
u32 value;
@@ -1109,7 +1110,7 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,

if (pmc->soc->has_impl_33v_pwr) {
value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR);
- if (voltage == TEGRA_IO_PAD_1800000UV)
+ if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
value &= ~BIT(pad->voltage);
else
value |= BIT(pad->voltage);
@@ -1123,7 +1124,7 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,
/* update I/O voltage */
value = tegra_pmc_readl(PMC_PWR_DET_VALUE);

- if (voltage == TEGRA_IO_PAD_1800000UV)
+ if (voltage == TEGRA_IO_PAD_VOLTAGE_3V3)
value &= ~BIT(pad->voltage);
else
value |= BIT(pad->voltage);
@@ -1137,9 +1138,8 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,

return 0;
}
-EXPORT_SYMBOL(tegra_io_pad_set_voltage);

-int tegra_io_pad_get_voltage(enum tegra_io_pad id)
+static int tegra_io_pad_get_voltage(enum tegra_io_pad id)
{
const struct tegra_io_pad_soc *pad;
u32 value;
@@ -1157,11 +1157,10 @@ int tegra_io_pad_get_voltage(enum tegra_io_pad id)
value = tegra_pmc_readl(PMC_PWR_DET_VALUE);

if ((value & BIT(pad->voltage)) == 0)
- return TEGRA_IO_PAD_1800000UV;
+ return TEGRA_IO_PAD_VOLTAGE_1V8;

- return TEGRA_IO_PAD_3300000UV;
+ return TEGRA_IO_PAD_VOLTAGE_3V3;
}
-EXPORT_SYMBOL(tegra_io_pad_get_voltage);

/**
* tegra_io_rail_power_on() - enable power to I/O rail
diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h
index 445aa66..5624268 100644
--- a/include/soc/tegra/pmc.h
+++ b/include/soc/tegra/pmc.h
@@ -141,16 +141,6 @@ enum tegra_io_pad {
#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_SOC_TEGRA_PMC
int tegra_powergate_is_powered(unsigned int id);
int tegra_powergate_power_on(unsigned int id);
@@ -163,9 +153,6 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,

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);
@@ -213,12 +200,6 @@ 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;
--
2.7.4


2018-07-12 12:02:20

by Aapo Vienamo

[permalink] [raw]
Subject: [PATCH v3 7/7] soc/tegra: pmc: Implement pad configuration via pinctrl

Register a pinctrl device and implement get and set functions for
PIN_CONFIG_LOW_POWER_MODE and PIN_CONFIG_POWER_SOURCE parameters.

Signed-off-by: Aapo Vienamo <[email protected]>
---
drivers/soc/tegra/pmc.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 185 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 7d3c3de..6bfd00d 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -33,6 +33,9 @@
#include <linux/of_address.h>
#include <linux/of_clk.h>
#include <linux/of_platform.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/reboot.h>
@@ -164,6 +167,9 @@ struct tegra_pmc_soc {
const struct tegra_io_pad_soc *io_pads;
unsigned int num_io_pads;

+ const struct pinctrl_pin_desc *pin_descs;
+ unsigned int num_pin_descs;
+
const struct tegra_pmc_regs *regs;
void (*init)(struct tegra_pmc *pmc);
void (*setup_irq_polarity)(struct tegra_pmc *pmc,
@@ -222,6 +228,8 @@ struct tegra_pmc {
DECLARE_BITMAP(powergates_available, TEGRA_POWERGATE_MAX);

struct mutex powergates_lock;
+
+ struct pinctrl_dev *pctl_dev;
};

static struct tegra_pmc *pmc = &(struct tegra_pmc) {
@@ -1398,6 +1406,142 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
of_node_put(np);
}

+static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev)
+{
+ return pmc->soc->num_io_pads;
+}
+
+static const char *tegra_io_pad_pinctrl_get_group_name(
+ struct pinctrl_dev *pctl, unsigned int group)
+{
+ return pmc->soc->io_pads[group].name;
+}
+
+static int tegra_io_pad_pinctrl_get_group_pins(struct pinctrl_dev *pctl_dev,
+ unsigned int group,
+ const unsigned int **pins,
+ unsigned int *num_pins)
+{
+ *pins = &pmc->soc->io_pads[group].id;
+ *num_pins = 1;
+ return 0;
+}
+
+static const struct pinctrl_ops tegra_io_pad_pinctrl_ops = {
+ .get_groups_count = tegra_io_pad_pinctrl_get_groups_count,
+ .get_group_name = tegra_io_pad_pinctrl_get_group_name,
+ .get_group_pins = tegra_io_pad_pinctrl_get_group_pins,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev,
+ unsigned int pin, unsigned long *config)
+{
+ const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
+ enum pin_config_param param = pinconf_to_config_param(*config);
+ int ret;
+ u32 arg;
+
+ if (!pad)
+ return -EINVAL;
+
+ switch (param) {
+ case PIN_CONFIG_POWER_SOURCE:
+ ret = tegra_io_pad_get_voltage(pad->id);
+ if (ret < 0)
+ return ret;
+ arg = ret;
+ break;
+ case PIN_CONFIG_LOW_POWER_MODE:
+ ret = tegra_io_pad_is_powered(pad->id);
+ if (ret < 0)
+ return ret;
+ arg = !ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+
+ return 0;
+}
+
+static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev,
+ unsigned int pin, unsigned long *configs,
+ unsigned int num_configs)
+{
+ const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
+ enum pin_config_param param;
+ unsigned int i;
+ int err;
+ u32 arg;
+
+ if (!pad)
+ return -EINVAL;
+
+ for (i = 0; i < num_configs; ++i) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_LOW_POWER_MODE:
+ if (arg)
+ err = tegra_io_pad_power_disable(pad->id);
+ else
+ err = tegra_io_pad_power_enable(pad->id);
+ if (err)
+ return err;
+ break;
+ case PIN_CONFIG_POWER_SOURCE:
+ if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 &&
+ arg != TEGRA_IO_PAD_VOLTAGE_3V3)
+ return -EINVAL;
+ err = tegra_io_pad_set_voltage(pad->id, arg);
+ if (err)
+ return err;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static const struct pinconf_ops tegra_io_pad_pinconf_ops = {
+ .pin_config_get = tegra_io_pad_pinconf_get,
+ .pin_config_set = tegra_io_pad_pinconf_set,
+ .is_generic = true,
+};
+
+static struct pinctrl_desc tegra_pmc_pctl_desc = {
+ .pctlops = &tegra_io_pad_pinctrl_ops,
+ .confops = &tegra_io_pad_pinconf_ops,
+};
+
+static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
+{
+ int err = 0;
+
+ if (!pmc->soc->num_pin_descs)
+ return 0;
+
+ tegra_pmc_pctl_desc.name = dev_name(pmc->dev);
+ tegra_pmc_pctl_desc.pins = pmc->soc->pin_descs;
+ tegra_pmc_pctl_desc.npins = pmc->soc->num_pin_descs;
+
+ pmc->pctl_dev = devm_pinctrl_register(pmc->dev, &tegra_pmc_pctl_desc,
+ pmc);
+ if (IS_ERR(pmc->pctl_dev)) {
+ err = PTR_ERR(pmc->pctl_dev);
+ dev_err(pmc->dev, "unable to register pinctrl, %d\n", err);
+ }
+
+ return err;
+}
+
static int tegra_pmc_probe(struct platform_device *pdev)
{
void __iomem *base;
@@ -1475,18 +1619,27 @@ static int tegra_pmc_probe(struct platform_device *pdev)

err = register_restart_handler(&tegra_pmc_restart_handler);
if (err) {
- debugfs_remove(pmc->debugfs);
dev_err(&pdev->dev, "unable to register restart handler, %d\n",
err);
- return err;
+ goto cleanup_debugfs;
}

+ err = tegra_pmc_pinctrl_init(pmc);
+ if (err)
+ goto cleanup_restart_handler;
+
mutex_lock(&pmc->powergates_lock);
iounmap(pmc->base);
pmc->base = base;
mutex_unlock(&pmc->powergates_lock);

return 0;
+
+cleanup_restart_handler:
+ unregister_restart_handler(&tegra_pmc_restart_handler);
+cleanup_debugfs:
+ debugfs_remove(pmc->debugfs);
+ return err;
}

#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
@@ -1576,6 +1729,8 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
.has_gpu_clamps = false,
.num_io_pads = 0,
.io_pads = NULL,
+ .num_pin_descs = 0,
+ .pin_descs = NULL,
.regs = &tegra20_pmc_regs,
.init = tegra20_pmc_init,
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
@@ -1615,6 +1770,8 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
.has_impl_33v_pwr = false,
.num_io_pads = 0,
.io_pads = NULL,
+ .num_pin_descs = 0,
+ .pin_descs = NULL,
.regs = &tegra20_pmc_regs,
.init = tegra20_pmc_init,
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
@@ -1658,6 +1815,8 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
.has_impl_33v_pwr = false,
.num_io_pads = 0,
.io_pads = NULL,
+ .num_pin_descs = 0,
+ .pin_descs = NULL,
.regs = &tegra20_pmc_regs,
.init = tegra20_pmc_init,
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
@@ -1704,6 +1863,12 @@ static const u8 tegra124_cpu_powergates[] = {
.name = (_name), \
})

+#define TEGRA_IO_PIN_DESC(_id, _dpd, _voltage, _name) \
+ ((struct pinctrl_pin_desc) { \
+ .number = (_id), \
+ .name = (_name) \
+ })
+
#define TEGRA124_IO_PAD_TABLE(_pad) \
/* .id .dpd .voltage .name */ \
_pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \
@@ -1741,6 +1906,10 @@ static const struct tegra_io_pad_soc tegra124_io_pads[] = {
TEGRA124_IO_PAD_TABLE(TEGRA_IO_PAD)
};

+static const struct pinctrl_pin_desc tegra124_pin_descs[] = {
+ TEGRA124_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
+};
+
static const struct tegra_pmc_soc tegra124_pmc_soc = {
.num_powergates = ARRAY_SIZE(tegra124_powergates),
.powergates = tegra124_powergates,
@@ -1751,6 +1920,8 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
.has_impl_33v_pwr = false,
.num_io_pads = ARRAY_SIZE(tegra124_io_pads),
.io_pads = tegra124_io_pads,
+ .num_pin_descs = ARRAY_SIZE(tegra124_pin_descs),
+ .pin_descs = tegra124_pin_descs,
.regs = &tegra20_pmc_regs,
.init = tegra20_pmc_init,
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
@@ -1835,6 +2006,10 @@ static const struct tegra_io_pad_soc tegra210_io_pads[] = {
TEGRA210_IO_PAD_TABLE(TEGRA_IO_PAD)
};

+static const struct pinctrl_pin_desc tegra210_pin_descs[] = {
+ TEGRA210_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
+};
+
static const struct tegra_pmc_soc tegra210_pmc_soc = {
.num_powergates = ARRAY_SIZE(tegra210_powergates),
.powergates = tegra210_powergates,
@@ -1846,6 +2021,8 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
.needs_mbist_war = true,
.num_io_pads = ARRAY_SIZE(tegra210_io_pads),
.io_pads = tegra210_io_pads,
+ .num_pin_descs = ARRAY_SIZE(tegra210_pin_descs),
+ .pin_descs = tegra210_pin_descs,
.regs = &tegra20_pmc_regs,
.init = tegra20_pmc_init,
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
@@ -1896,6 +2073,10 @@ static const struct tegra_io_pad_soc tegra186_io_pads[] = {
TEGRA186_IO_PAD_TABLE(TEGRA_IO_PAD)
};

+static const struct pinctrl_pin_desc tegra186_pin_descs[] = {
+ TEGRA186_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
+};
+
static const struct tegra_pmc_regs tegra186_pmc_regs = {
.scratch0 = 0x2000,
.dpd_req = 0x74,
@@ -1949,6 +2130,8 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
.has_impl_33v_pwr = true,
.num_io_pads = ARRAY_SIZE(tegra186_io_pads),
.io_pads = tegra186_io_pads,
+ .num_pin_descs = ARRAY_SIZE(tegra186_pin_descs),
+ .pin_descs = tegra186_pin_descs,
.regs = &tegra186_pmc_regs,
.init = NULL,
.setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
--
2.7.4


2018-07-12 12:02:47

by Aapo Vienamo

[permalink] [raw]
Subject: [PATCH v3 1/7] soc/tegra: pmc: Fix pad voltage configuration for Tegra186

Implement support for the PMC_IMPL_E_33V_PWR register which replaces
PMC_PWR_DET register interface of the SoC generations preceding
Tegra186. Also add the voltage bit offsets to the tegra186_io_pads[]
table and the AO_HV pad.

Signed-off-by: Aapo Vienamo <[email protected]>
Acked-by: Jon Hunter <[email protected]>
---
drivers/soc/tegra/pmc.c | 55 ++++++++++++++++++++++++++++++++++---------------
include/soc/tegra/pmc.h | 1 +
2 files changed, 39 insertions(+), 17 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 2d6f3fc..f926332 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -65,6 +65,8 @@

#define PWRGATE_STATUS 0x38

+#define PMC_IMPL_E_33V_PWR 0x40
+
#define PMC_PWR_DET 0x48

#define PMC_SCRATCH0_MODE_RECOVERY BIT(31)
@@ -154,6 +156,7 @@ struct tegra_pmc_soc {
bool has_tsense_reset;
bool has_gpu_clamps;
bool needs_mbist_war;
+ bool has_impl_33v_pwr;

const struct tegra_io_pad_soc *io_pads;
unsigned int num_io_pads;
@@ -1073,20 +1076,29 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,

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);
+ if (pmc->soc->has_impl_33v_pwr) {
+ value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR);
+ if (voltage == TEGRA_IO_PAD_1800000UV)
+ value &= ~BIT(pad->voltage);
+ else
+ value |= BIT(pad->voltage);
+ tegra_pmc_writel(value, PMC_IMPL_E_33V_PWR);
+ } else {
+ /* 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);
+ /* 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);
+ if (voltage == TEGRA_IO_PAD_1800000UV)
+ value &= ~BIT(pad->voltage);
+ else
+ value |= BIT(pad->voltage);

- tegra_pmc_writel(value, PMC_PWR_DET_VALUE);
+ tegra_pmc_writel(value, PMC_PWR_DET_VALUE);
+ }

mutex_unlock(&pmc->powergates_lock);

@@ -1108,7 +1120,10 @@ int tegra_io_pad_get_voltage(enum tegra_io_pad id)
if (pad->voltage == UINT_MAX)
return -ENOTSUPP;

- value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
+ if (pmc->soc->has_impl_33v_pwr)
+ value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR);
+ else
+ value = tegra_pmc_readl(PMC_PWR_DET_VALUE);

if ((value & BIT(pad->voltage)) == 0)
return TEGRA_IO_PAD_1800000UV;
@@ -1567,6 +1582,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
.cpu_powergates = tegra30_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = false,
+ .has_impl_33v_pwr = false,
.num_io_pads = 0,
.io_pads = NULL,
.regs = &tegra20_pmc_regs,
@@ -1609,6 +1625,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
.cpu_powergates = tegra114_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = false,
+ .has_impl_33v_pwr = false,
.num_io_pads = 0,
.io_pads = NULL,
.regs = &tegra20_pmc_regs,
@@ -1689,6 +1706,7 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
.cpu_powergates = tegra124_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = true,
+ .has_impl_33v_pwr = false,
.num_io_pads = ARRAY_SIZE(tegra124_io_pads),
.io_pads = tegra124_io_pads,
.regs = &tegra20_pmc_regs,
@@ -1778,6 +1796,7 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
.cpu_powergates = tegra210_cpu_powergates,
.has_tsense_reset = true,
.has_gpu_clamps = true,
+ .has_impl_33v_pwr = false,
.needs_mbist_war = true,
.num_io_pads = ARRAY_SIZE(tegra210_io_pads),
.io_pads = tegra210_io_pads,
@@ -1806,7 +1825,7 @@ static const struct tegra_io_pad_soc tegra186_io_pads[] = {
{ .id = TEGRA_IO_PAD_HDMI_DP0, .dpd = 28, .voltage = UINT_MAX },
{ .id = TEGRA_IO_PAD_HDMI_DP1, .dpd = 29, .voltage = UINT_MAX },
{ .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = 32, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_SDMMC2_HV, .dpd = 34, .voltage = UINT_MAX },
+ { .id = TEGRA_IO_PAD_SDMMC2_HV, .dpd = 34, .voltage = 5 },
{ .id = TEGRA_IO_PAD_SDMMC4, .dpd = 36, .voltage = UINT_MAX },
{ .id = TEGRA_IO_PAD_CAM, .dpd = 38, .voltage = UINT_MAX },
{ .id = TEGRA_IO_PAD_DSIB, .dpd = 40, .voltage = UINT_MAX },
@@ -1818,12 +1837,13 @@ static const struct tegra_io_pad_soc tegra186_io_pads[] = {
{ .id = TEGRA_IO_PAD_CSIF, .dpd = 46, .voltage = UINT_MAX },
{ .id = TEGRA_IO_PAD_SPI, .dpd = 47, .voltage = UINT_MAX },
{ .id = TEGRA_IO_PAD_UFS, .dpd = 49, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_DMIC_HV, .dpd = 52, .voltage = UINT_MAX },
+ { .id = TEGRA_IO_PAD_DMIC_HV, .dpd = 52, .voltage = 2 },
{ .id = TEGRA_IO_PAD_EDP, .dpd = 53, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_SDMMC1_HV, .dpd = 55, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_SDMMC3_HV, .dpd = 56, .voltage = UINT_MAX },
+ { .id = TEGRA_IO_PAD_SDMMC1_HV, .dpd = 55, .voltage = 4 },
+ { .id = TEGRA_IO_PAD_SDMMC3_HV, .dpd = 56, .voltage = 6 },
{ .id = TEGRA_IO_PAD_CONN, .dpd = 60, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_AUDIO_HV, .dpd = 61, .voltage = UINT_MAX },
+ { .id = TEGRA_IO_PAD_AUDIO_HV, .dpd = 61, .voltage = 1 },
+ { .id = TEGRA_IO_PAD_AO_HV, .dpd = UINT_MAX, .voltage = 0 },
};

static const struct tegra_pmc_regs tegra186_pmc_regs = {
@@ -1876,6 +1896,7 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
.cpu_powergates = NULL,
.has_tsense_reset = false,
.has_gpu_clamps = false,
+ .has_impl_33v_pwr = true,
.num_io_pads = ARRAY_SIZE(tegra186_io_pads),
.io_pads = tegra186_io_pads,
.regs = &tegra186_pmc_regs,
diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h
index c32bf91..445aa66 100644
--- a/include/soc/tegra/pmc.h
+++ b/include/soc/tegra/pmc.h
@@ -134,6 +134,7 @@ enum tegra_io_pad {
TEGRA_IO_PAD_USB2,
TEGRA_IO_PAD_USB3,
TEGRA_IO_PAD_USB_BIAS,
+ TEGRA_IO_PAD_AO_HV,
};

/* deprecated, use TEGRA_IO_PAD_{HDMI,LVDS} instead */
--
2.7.4


2018-07-12 13:03:08

by Jon Hunter

[permalink] [raw]
Subject: Re: [PATCH v3 7/7] soc/tegra: pmc: Implement pad configuration via pinctrl


On 12/07/18 13:00, Aapo Vienamo wrote:
> Register a pinctrl device and implement get and set functions for
> PIN_CONFIG_LOW_POWER_MODE and PIN_CONFIG_POWER_SOURCE parameters.
>
> Signed-off-by: Aapo Vienamo <[email protected]>
> ---
> drivers/soc/tegra/pmc.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 185 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
> index 7d3c3de..6bfd00d 100644
> --- a/drivers/soc/tegra/pmc.c
> +++ b/drivers/soc/tegra/pmc.c
> @@ -33,6 +33,9 @@
> #include <linux/of_address.h>
> #include <linux/of_clk.h>
> #include <linux/of_platform.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinconf.h>
> +#include <linux/pinctrl/pinconf-generic.h>
> #include <linux/platform_device.h>
> #include <linux/pm_domain.h>
> #include <linux/reboot.h>
> @@ -164,6 +167,9 @@ struct tegra_pmc_soc {
> const struct tegra_io_pad_soc *io_pads;
> unsigned int num_io_pads;
>
> + const struct pinctrl_pin_desc *pin_descs;
> + unsigned int num_pin_descs;
> +
> const struct tegra_pmc_regs *regs;
> void (*init)(struct tegra_pmc *pmc);
> void (*setup_irq_polarity)(struct tegra_pmc *pmc,
> @@ -222,6 +228,8 @@ struct tegra_pmc {
> DECLARE_BITMAP(powergates_available, TEGRA_POWERGATE_MAX);
>
> struct mutex powergates_lock;
> +
> + struct pinctrl_dev *pctl_dev;
> };
>
> static struct tegra_pmc *pmc = &(struct tegra_pmc) {
> @@ -1398,6 +1406,142 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
> of_node_put(np);
> }
>
> +static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev)
> +{
> + return pmc->soc->num_io_pads;
> +}
> +
> +static const char *tegra_io_pad_pinctrl_get_group_name(
> + struct pinctrl_dev *pctl, unsigned int group)
> +{
> + return pmc->soc->io_pads[group].name;
> +}
> +
> +static int tegra_io_pad_pinctrl_get_group_pins(struct pinctrl_dev *pctl_dev,
> + unsigned int group,
> + const unsigned int **pins,
> + unsigned int *num_pins)
> +{
> + *pins = &pmc->soc->io_pads[group].id;
> + *num_pins = 1;
> + return 0;
> +}
> +
> +static const struct pinctrl_ops tegra_io_pad_pinctrl_ops = {
> + .get_groups_count = tegra_io_pad_pinctrl_get_groups_count,
> + .get_group_name = tegra_io_pad_pinctrl_get_group_name,
> + .get_group_pins = tegra_io_pad_pinctrl_get_group_pins,
> + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
> + .dt_free_map = pinconf_generic_dt_free_map,
> +};
> +
> +static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev,
> + unsigned int pin, unsigned long *config)
> +{
> + const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
> + enum pin_config_param param = pinconf_to_config_param(*config);
> + int ret;
> + u32 arg;
> +
> + if (!pad)
> + return -EINVAL;
> +
> + switch (param) {
> + case PIN_CONFIG_POWER_SOURCE:
> + ret = tegra_io_pad_get_voltage(pad->id);
> + if (ret < 0)
> + return ret;
> + arg = ret;
> + break;
> + case PIN_CONFIG_LOW_POWER_MODE:
> + ret = tegra_io_pad_is_powered(pad->id);
> + if (ret < 0)
> + return ret;
> + arg = !ret;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + *config = pinconf_to_config_packed(param, arg);
> +
> + return 0;
> +}
> +
> +static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev,
> + unsigned int pin, unsigned long *configs,
> + unsigned int num_configs)
> +{
> + const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
> + enum pin_config_param param;
> + unsigned int i;
> + int err;
> + u32 arg;
> +
> + if (!pad)
> + return -EINVAL;
> +
> + for (i = 0; i < num_configs; ++i) {
> + param = pinconf_to_config_param(configs[i]);
> + arg = pinconf_to_config_argument(configs[i]);
> +
> + switch (param) {
> + case PIN_CONFIG_LOW_POWER_MODE:
> + if (arg)
> + err = tegra_io_pad_power_disable(pad->id);
> + else
> + err = tegra_io_pad_power_enable(pad->id);
> + if (err)
> + return err;
> + break;
> + case PIN_CONFIG_POWER_SOURCE:
> + if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 &&
> + arg != TEGRA_IO_PAD_VOLTAGE_3V3)
> + return -EINVAL;
> + err = tegra_io_pad_set_voltage(pad->id, arg);
> + if (err)
> + return err;
> + break;
> + default:
> + return -EINVAL;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static const struct pinconf_ops tegra_io_pad_pinconf_ops = {
> + .pin_config_get = tegra_io_pad_pinconf_get,
> + .pin_config_set = tegra_io_pad_pinconf_set,
> + .is_generic = true,
> +};
> +
> +static struct pinctrl_desc tegra_pmc_pctl_desc = {
> + .pctlops = &tegra_io_pad_pinctrl_ops,
> + .confops = &tegra_io_pad_pinconf_ops,
> +};
> +
> +static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
> +{
> + int err = 0;
> +
> + if (!pmc->soc->num_pin_descs)
> + return 0;
> +
> + tegra_pmc_pctl_desc.name = dev_name(pmc->dev);
> + tegra_pmc_pctl_desc.pins = pmc->soc->pin_descs;
> + tegra_pmc_pctl_desc.npins = pmc->soc->num_pin_descs;
> +
> + pmc->pctl_dev = devm_pinctrl_register(pmc->dev, &tegra_pmc_pctl_desc,
> + pmc);
> + if (IS_ERR(pmc->pctl_dev)) {
> + err = PTR_ERR(pmc->pctl_dev);
> + dev_err(pmc->dev, "unable to register pinctrl, %d\n", err);
> + }
> +
> + return err;
> +}
> +
> static int tegra_pmc_probe(struct platform_device *pdev)
> {
> void __iomem *base;
> @@ -1475,18 +1619,27 @@ static int tegra_pmc_probe(struct platform_device *pdev)
>
> err = register_restart_handler(&tegra_pmc_restart_handler);
> if (err) {
> - debugfs_remove(pmc->debugfs);
> dev_err(&pdev->dev, "unable to register restart handler, %d\n",
> err);
> - return err;
> + goto cleanup_debugfs;
> }
>
> + err = tegra_pmc_pinctrl_init(pmc);
> + if (err)
> + goto cleanup_restart_handler;
> +
> mutex_lock(&pmc->powergates_lock);
> iounmap(pmc->base);
> pmc->base = base;
> mutex_unlock(&pmc->powergates_lock);
>
> return 0;
> +
> +cleanup_restart_handler:
> + unregister_restart_handler(&tegra_pmc_restart_handler);
> +cleanup_debugfs:
> + debugfs_remove(pmc->debugfs);
> + return err;
> }
>
> #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
> @@ -1576,6 +1729,8 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
> .has_gpu_clamps = false,
> .num_io_pads = 0,
> .io_pads = NULL,
> + .num_pin_descs = 0,
> + .pin_descs = NULL,
> .regs = &tegra20_pmc_regs,
> .init = tegra20_pmc_init,
> .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
> @@ -1615,6 +1770,8 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
> .has_impl_33v_pwr = false,
> .num_io_pads = 0,
> .io_pads = NULL,
> + .num_pin_descs = 0,
> + .pin_descs = NULL,
> .regs = &tegra20_pmc_regs,
> .init = tegra20_pmc_init,
> .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
> @@ -1658,6 +1815,8 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
> .has_impl_33v_pwr = false,
> .num_io_pads = 0,
> .io_pads = NULL,
> + .num_pin_descs = 0,
> + .pin_descs = NULL,
> .regs = &tegra20_pmc_regs,
> .init = tegra20_pmc_init,
> .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
> @@ -1704,6 +1863,12 @@ static const u8 tegra124_cpu_powergates[] = {
> .name = (_name), \
> })
>
> +#define TEGRA_IO_PIN_DESC(_id, _dpd, _voltage, _name) \
> + ((struct pinctrl_pin_desc) { \
> + .number = (_id), \
> + .name = (_name) \
> + })
> +
> #define TEGRA124_IO_PAD_TABLE(_pad) \
> /* .id .dpd .voltage .name */ \
> _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \
> @@ -1741,6 +1906,10 @@ static const struct tegra_io_pad_soc tegra124_io_pads[] = {
> TEGRA124_IO_PAD_TABLE(TEGRA_IO_PAD)
> };
>
> +static const struct pinctrl_pin_desc tegra124_pin_descs[] = {
> + TEGRA124_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
> +};
> +
> static const struct tegra_pmc_soc tegra124_pmc_soc = {
> .num_powergates = ARRAY_SIZE(tegra124_powergates),
> .powergates = tegra124_powergates,
> @@ -1751,6 +1920,8 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
> .has_impl_33v_pwr = false,
> .num_io_pads = ARRAY_SIZE(tegra124_io_pads),
> .io_pads = tegra124_io_pads,
> + .num_pin_descs = ARRAY_SIZE(tegra124_pin_descs),
> + .pin_descs = tegra124_pin_descs,
> .regs = &tegra20_pmc_regs,
> .init = tegra20_pmc_init,
> .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
> @@ -1835,6 +2006,10 @@ static const struct tegra_io_pad_soc tegra210_io_pads[] = {
> TEGRA210_IO_PAD_TABLE(TEGRA_IO_PAD)
> };
>
> +static const struct pinctrl_pin_desc tegra210_pin_descs[] = {
> + TEGRA210_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
> +};
> +
> static const struct tegra_pmc_soc tegra210_pmc_soc = {
> .num_powergates = ARRAY_SIZE(tegra210_powergates),
> .powergates = tegra210_powergates,
> @@ -1846,6 +2021,8 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
> .needs_mbist_war = true,
> .num_io_pads = ARRAY_SIZE(tegra210_io_pads),
> .io_pads = tegra210_io_pads,
> + .num_pin_descs = ARRAY_SIZE(tegra210_pin_descs),
> + .pin_descs = tegra210_pin_descs,
> .regs = &tegra20_pmc_regs,
> .init = tegra20_pmc_init,
> .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
> @@ -1896,6 +2073,10 @@ static const struct tegra_io_pad_soc tegra186_io_pads[] = {
> TEGRA186_IO_PAD_TABLE(TEGRA_IO_PAD)
> };
>
> +static const struct pinctrl_pin_desc tegra186_pin_descs[] = {
> + TEGRA186_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
> +};
> +
> static const struct tegra_pmc_regs tegra186_pmc_regs = {
> .scratch0 = 0x2000,
> .dpd_req = 0x74,
> @@ -1949,6 +2130,8 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
> .has_impl_33v_pwr = true,
> .num_io_pads = ARRAY_SIZE(tegra186_io_pads),
> .io_pads = tegra186_io_pads,
> + .num_pin_descs = ARRAY_SIZE(tegra186_pin_descs),
> + .pin_descs = tegra186_pin_descs,
> .regs = &tegra186_pmc_regs,
> .init = NULL,
> .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
>

Acked-by: Jon Hunter <[email protected]>

Cheers
Jon

--
nvpublic

2018-07-16 15:45:21

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v3 5/7] dt-bindings: Add Tegra PMC pad configuration bindings

On Thu, Jul 12, 2018 at 03:00:11PM +0300, Aapo Vienamo wrote:
> Document the pinctrl bindings used by the PMC driver for performing pad
> configuration. Both nvidia,tegra186-pmc.txt and nvidia,tegra20-pmc.txt
> are modified as they both cover SoC generations for which these bindings
> apply.
>
> Add a header defining Tegra PMC pad voltage configurations.
>
> Signed-off-by: Aapo Vienamo <[email protected]>
> Acked-by: Jon Hunter <[email protected]>
> ---
> .../bindings/arm/tegra/nvidia,tegra186-pmc.txt | 84 +++++++++++++++++++
> .../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 95 ++++++++++++++++++++++
> include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h | 18 ++++
> 3 files changed, 197 insertions(+)
> create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h
>
> diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
> index 5a3bf7c..9528f41 100644
> --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
> +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
> @@ -34,3 +34,87 @@ Board DTS:
> pmc@c360000 {
> nvidia,invert-interrupt;
> };
> +
> +== Pad Control Nodes ==
> +
> +The PMC can be used to set pad power state and voltage configuration.
> +The pad configuration is done via the pinctrl framework. The driver
> +implements power-source, low-power-enable, and low-power-disable pinconf
> +pin configuration node properties. Each pinctrl pin corresponds to a
> +single Tegra PMC pad. Thus, in the following sections of this document
> +pin refers to the pinctrl frameworks notion of a Tegra PMC pad.

"pinctrl framework" is Linux specific and doesn't belong in the binding.
Neither does what a driver supports. Describe what the h/w supports.

> +
> +The pad configuration state nodes are placed under the pmc node and they
> +are referred to by the pinctrl client device properties. For more

Another driver detail not relevant.

> +information see the examples presented later and

examples don't document bindings. The documentation should be complete
without examples.

> +Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt.
> +
> +The values accepted by power-source property are
> +TEGRA_IO_PAD_VOLTAGE_1V8 and TEGRA_IO_PAD_VOLTAGE_3V3, which are defined
> +in dt-bindings/pinctrl/pinctrl-tegra-io-pad.h.

You need to list out what properties the child nodes can have.

power-source needs a vendor prefix.

> +
> +Following pinctrl pin name strings are present on Tegra186:
> +csia csib dsi mipi-bias
> +pex-clk-bias pex-clk3 pex-clk2 pex-clk1
> +usb0 usb1 usb2 usb-bias
> +uart audio hsic dbg
> +hdmi-dp0 hdmi-dp1 pex-cntrl sdmmc2-hv
> +sdmmc4 cam dsib dsic
> +dsid csic csid csie
> +dsif spi ufs dmic-hv
> +edp sdmmc1-hv sdmmc3-hv conn
> +audio-hv ao-hv
> +
> +All of the listed Tegra186 pins except ao-hv support the
> +low-power-enable and low-power-disable properties. The power-source
> +property is supported following Tegra210 pins: sdmmc2-hv, dmic-hv,
> +sdmmc1-hv, sdmmc3-hv, audio-hv, ao-hv.
> +
> +Pad configuration state example:
> + pmc: pmc@7000e400 {
> + compatible = "nvidia,tegra186-pmc";
> + reg = <0 0x0c360000 0 0x10000>,
> + <0 0x0c370000 0 0x10000>,
> + <0 0x0c380000 0 0x10000>,
> + <0 0x0c390000 0 0x10000>;
> + reg-names = "pmc", "wake", "aotag", "scratch";
> +
> + ...
> +
> + sdmmc1_3v3: sdmmc1-3v3 {
> + pins = "sdmmc1-hv";
> + power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>;
> + };
> +
> + sdmmc1_1v8: sdmmc1-1v8 {
> + pins = "sdmmc1-hv";
> + power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>;
> + };
> +
> + hdmi_off: hdmi-off {
> + pins = "hdmi";
> + low-power-enable;
> + }
> +
> + hdmi_on: hdmi-on {
> + pins = "hdmi";
> + low-power-disable;
> + }
> + };
> +
> +Pinctrl client example:
> + sdmmc1: sdhci@3400000 {
> + ...
> + pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
> + pinctrl-0 = <&sdmmc1_3v3>;
> + pinctrl-1 = <&sdmmc1_1v8>;
> + };
> +
> + ...
> +
> + sor0: sor@15540000 {
> + ...
> + pinctrl-0 = <&hdmi_off>;
> + pinctrl-1 = <&hdmi_on>;
> + pinctrl-names = "hdmi-on", "hdmi-off";
> + };
> diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
> index a74b37b..d50a505 100644
> --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
> +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
> @@ -195,3 +195,98 @@ Example:
> power-domains = <&pd_audio>;
> ...
> };
> +
> +== Pad Control Nodes ==

Similar comments in this file.

> +
> +The PMC can be used to set pad power state and voltage configuration.
> +This functionality is present on SoCs from Tegra124 onwards. The pad
> +configuration is done via the pinctrl framework. The driver implements
> +power-source, low-power-enable, and low-power-disable pinconf pin
> +configuration node properties. Each pinctrl pin corresponds to a single
> +Tegra PMC pad. Thus, in the following sections of this document pin
> +refers to the pinctrl frameworks notion of a Tegra PMC pad.
> +
> +The pad configuration state nodes are placed under the pmc node and they
> +are referred to by the pinctrl client device properties. For more
> +information see the examples presented later and
> +Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt.
> +
> +The values accepted by power-source property are
> +TEGRA_IO_PAD_VOLTAGE_1V8 and TEGRA_IO_PAD_VOLTAGE_3V3, which are defined
> +in dt-bindings/pinctrl/pinctrl-tegra-io-pad.h.
> +
> +Following pinctrl pin name strings are present on Tegra124 and Tegra132:
> +audio bb cam comp
> +csia csb cse dsi
> +dsib dsic dsid hdmi
> +hsic hv lvds mipi-bias
> +nand pex-bias pex-clk1 pex-clk2
> +pex-cntrl sdmmc1 sdmmc3 sdmmc4
> +sys_ddc uart usb0 usb1
> +usb2 usb_bias
> +
> +All of the listed Tegra124 and Tegra132 pins support the
> +low-power-enable and low-power-disable properties. None of the pins
> +support the power-source property.
> +
> +Following pinctrl pin name strings are present on Tegra210:
> +audio audio-hv cam csia
> +csib csic csid csie
> +csif dbg debug-nonao dmic
> +dp dsi dsib dsic
> +dsid emmc emmc2 gpio
> +hdmi hsic lvds mipi-bias
> +pex-bias pex-clk1 pex-clk2 pex-cntrl
> +sdmmc1 sdmmc3 spi spi-hv
> +uart usb0 usb1 usb2
> +usb3 usb-bias
> +
> +All of the listed Tegra210 pins except pex-cntrl support the
> +low-power-enable and low-power-disable properties. The power-source
> +property is supported following Tegra210 pins: audio, audio-hv, cam,
> +dbg, dmic, gpio, pex-cntrl, sdmmc1, sdmmc3, spi, spi-hv, and uart.
> +
> +Pad configuration state example:
> + pmc: pmc@7000e400 {
> + compatible = "nvidia,tegra210-pmc";
> + reg = <0x0 0x7000e400 0x0 0x400>;
> + clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
> + clock-names = "pclk", "clk32k_in";
> +
> + ...
> +
> + sdmmc1_3v3: sdmmc1-3v3 {
> + pins = "sdmmc1";
> + power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>;
> + };
> +
> + sdmmc1_1v8: sdmmc1-1v8 {
> + pins = "sdmmc1";
> + power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>;
> + };
> +
> + hdmi_off: hdmi-off {
> + pins = "hdmi";
> + low-power-enable;
> + }
> +
> + hdmi_on: hdmi-on {
> + pins = "hdmi";
> + low-power-disable;
> + }
> + };
> +
> +Pinctrl client example:
> + sdmmc1: sdhci@700b0000 {
> + ...
> + pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
> + pinctrl-0 = <&sdmmc1_3v3>;
> + pinctrl-1 = <&sdmmc1_1v8>;
> + };
> + ...
> + sor@54540000 {
> + ...
> + pinctrl-0 = <&hdmi_off>;
> + pinctrl-1 = <&hdmi_on>;
> + pinctrl-names = "hdmi-on", "hdmi-off";
> + };
> diff --git a/include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h b/include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h
> new file mode 100644
> index 0000000..20f4340
> --- /dev/null
> +++ b/include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * pinctrl-tegra-io-pad.h: Tegra I/O pad source voltage configuration constants
> + * pinctrl bindings.
> + *
> + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
> + *
> + * Author: Aapo Vienamo <[email protected]>
> + */
> +
> +#ifndef _DT_BINDINGS_PINCTRL_TEGRA_IO_PAD_H
> +#define _DT_BINDINGS_PINCTRL_TEGRA_IO_PAD_H
> +
> +/* Voltage levels of the I/O pad's source rail */
> +#define TEGRA_IO_PAD_VOLTAGE_1V8 0
> +#define TEGRA_IO_PAD_VOLTAGE_3V3 1
> +
> +#endif
> --
> 2.7.4
>

2018-07-17 12:24:23

by Aapo Vienamo

[permalink] [raw]
Subject: Re: [PATCH v3 5/7] dt-bindings: Add Tegra PMC pad configuration bindings

On Mon, 16 Jul 2018 09:43:09 -0600
Rob Herring <[email protected]> wrote:

> On Thu, Jul 12, 2018 at 03:00:11PM +0300, Aapo Vienamo wrote:
> > Document the pinctrl bindings used by the PMC driver for performing pad
> > configuration. Both nvidia,tegra186-pmc.txt and nvidia,tegra20-pmc.txt
> > are modified as they both cover SoC generations for which these bindings
> > apply.
> >
> > Add a header defining Tegra PMC pad voltage configurations.
> >
> > Signed-off-by: Aapo Vienamo <[email protected]>
> > Acked-by: Jon Hunter <[email protected]>
> > ---
> > .../bindings/arm/tegra/nvidia,tegra186-pmc.txt | 84 +++++++++++++++++++
> > .../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 95 ++++++++++++++++++++++
> > include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h | 18 ++++
> > 3 files changed, 197 insertions(+)
> > create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h
> >
> > diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
> > index 5a3bf7c..9528f41 100644
> > --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
> > +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
> > @@ -34,3 +34,87 @@ Board DTS:
> > pmc@c360000 {
> > nvidia,invert-interrupt;
> > };
> > +
> > +== Pad Control Nodes ==
> > +
> > +The PMC can be used to set pad power state and voltage configuration.
> > +The pad configuration is done via the pinctrl framework. The driver
> > +implements power-source, low-power-enable, and low-power-disable pinconf
> > +pin configuration node properties. Each pinctrl pin corresponds to a
> > +single Tegra PMC pad. Thus, in the following sections of this document
> > +pin refers to the pinctrl frameworks notion of a Tegra PMC pad.
>
> "pinctrl framework" is Linux specific and doesn't belong in the binding.
> Neither does what a driver supports. Describe what the h/w supports.
>
> > +
> > +The pad configuration state nodes are placed under the pmc node and they
> > +are referred to by the pinctrl client device properties. For more
>
> Another driver detail not relevant.
>
> > +information see the examples presented later and
>
> examples don't document bindings. The documentation should be complete
> without examples.
>
> > +Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt.
> > +
> > +The values accepted by power-source property are
> > +TEGRA_IO_PAD_VOLTAGE_1V8 and TEGRA_IO_PAD_VOLTAGE_3V3, which are defined
> > +in dt-bindings/pinctrl/pinctrl-tegra-io-pad.h.
>
> You need to list out what properties the child nodes can have.
>
> power-source needs a vendor prefix.

Isn't it a generic pinctrl property?

> > +
> > +Following pinctrl pin name strings are present on Tegra186:
> > +csia csib dsi mipi-bias
> > +pex-clk-bias pex-clk3 pex-clk2 pex-clk1
> > +usb0 usb1 usb2 usb-bias
> > +uart audio hsic dbg
> > +hdmi-dp0 hdmi-dp1 pex-cntrl sdmmc2-hv
> > +sdmmc4 cam dsib dsic
> > +dsid csic csid csie
> > +dsif spi ufs dmic-hv
> > +edp sdmmc1-hv sdmmc3-hv conn
> > +audio-hv ao-hv
> > +
> > +All of the listed Tegra186 pins except ao-hv support the
> > +low-power-enable and low-power-disable properties. The power-source
> > +property is supported following Tegra210 pins: sdmmc2-hv, dmic-hv,
> > +sdmmc1-hv, sdmmc3-hv, audio-hv, ao-hv.
> > +
> > +Pad configuration state example:
> > + pmc: pmc@7000e400 {
> > + compatible = "nvidia,tegra186-pmc";
> > + reg = <0 0x0c360000 0 0x10000>,
> > + <0 0x0c370000 0 0x10000>,
> > + <0 0x0c380000 0 0x10000>,
> > + <0 0x0c390000 0 0x10000>;
> > + reg-names = "pmc", "wake", "aotag", "scratch";
> > +
> > + ...
> > +
> > + sdmmc1_3v3: sdmmc1-3v3 {
> > + pins = "sdmmc1-hv";
> > + power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>;
> > + };
> > +
> > + sdmmc1_1v8: sdmmc1-1v8 {
> > + pins = "sdmmc1-hv";
> > + power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>;
> > + };
> > +
> > + hdmi_off: hdmi-off {
> > + pins = "hdmi";
> > + low-power-enable;
> > + }
> > +
> > + hdmi_on: hdmi-on {
> > + pins = "hdmi";
> > + low-power-disable;
> > + }
> > + };
> > +
> > +Pinctrl client example:
> > + sdmmc1: sdhci@3400000 {
> > + ...
> > + pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
> > + pinctrl-0 = <&sdmmc1_3v3>;
> > + pinctrl-1 = <&sdmmc1_1v8>;
> > + };
> > +
> > + ...
> > +
> > + sor0: sor@15540000 {
> > + ...
> > + pinctrl-0 = <&hdmi_off>;
> > + pinctrl-1 = <&hdmi_on>;
> > + pinctrl-names = "hdmi-on", "hdmi-off";
> > + };
> > diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
> > index a74b37b..d50a505 100644
> > --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
> > +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
> > @@ -195,3 +195,98 @@ Example:
> > power-domains = <&pd_audio>;
> > ...
> > };
> > +
> > +== Pad Control Nodes ==
>
> Similar comments in this file.
>
> > +
> > +The PMC can be used to set pad power state and voltage configuration.
> > +This functionality is present on SoCs from Tegra124 onwards. The pad
> > +configuration is done via the pinctrl framework. The driver implements
> > +power-source, low-power-enable, and low-power-disable pinconf pin
> > +configuration node properties. Each pinctrl pin corresponds to a single
> > +Tegra PMC pad. Thus, in the following sections of this document pin
> > +refers to the pinctrl frameworks notion of a Tegra PMC pad.
> > +
> > +The pad configuration state nodes are placed under the pmc node and they
> > +are referred to by the pinctrl client device properties. For more
> > +information see the examples presented later and
> > +Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt.
> > +
> > +The values accepted by power-source property are
> > +TEGRA_IO_PAD_VOLTAGE_1V8 and TEGRA_IO_PAD_VOLTAGE_3V3, which are defined
> > +in dt-bindings/pinctrl/pinctrl-tegra-io-pad.h.
> > +
> > +Following pinctrl pin name strings are present on Tegra124 and Tegra132:
> > +audio bb cam comp
> > +csia csb cse dsi
> > +dsib dsic dsid hdmi
> > +hsic hv lvds mipi-bias
> > +nand pex-bias pex-clk1 pex-clk2
> > +pex-cntrl sdmmc1 sdmmc3 sdmmc4
> > +sys_ddc uart usb0 usb1
> > +usb2 usb_bias
> > +
> > +All of the listed Tegra124 and Tegra132 pins support the
> > +low-power-enable and low-power-disable properties. None of the pins
> > +support the power-source property.
> > +
> > +Following pinctrl pin name strings are present on Tegra210:
> > +audio audio-hv cam csia
> > +csib csic csid csie
> > +csif dbg debug-nonao dmic
> > +dp dsi dsib dsic
> > +dsid emmc emmc2 gpio
> > +hdmi hsic lvds mipi-bias
> > +pex-bias pex-clk1 pex-clk2 pex-cntrl
> > +sdmmc1 sdmmc3 spi spi-hv
> > +uart usb0 usb1 usb2
> > +usb3 usb-bias
> > +
> > +All of the listed Tegra210 pins except pex-cntrl support the
> > +low-power-enable and low-power-disable properties. The power-source
> > +property is supported following Tegra210 pins: audio, audio-hv, cam,
> > +dbg, dmic, gpio, pex-cntrl, sdmmc1, sdmmc3, spi, spi-hv, and uart.
> > +
> > +Pad configuration state example:
> > + pmc: pmc@7000e400 {
> > + compatible = "nvidia,tegra210-pmc";
> > + reg = <0x0 0x7000e400 0x0 0x400>;
> > + clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
> > + clock-names = "pclk", "clk32k_in";
> > +
> > + ...
> > +
> > + sdmmc1_3v3: sdmmc1-3v3 {
> > + pins = "sdmmc1";
> > + power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>;
> > + };
> > +
> > + sdmmc1_1v8: sdmmc1-1v8 {
> > + pins = "sdmmc1";
> > + power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>;
> > + };
> > +
> > + hdmi_off: hdmi-off {
> > + pins = "hdmi";
> > + low-power-enable;
> > + }
> > +
> > + hdmi_on: hdmi-on {
> > + pins = "hdmi";
> > + low-power-disable;
> > + }
> > + };
> > +
> > +Pinctrl client example:
> > + sdmmc1: sdhci@700b0000 {
> > + ...
> > + pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
> > + pinctrl-0 = <&sdmmc1_3v3>;
> > + pinctrl-1 = <&sdmmc1_1v8>;
> > + };
> > + ...
> > + sor@54540000 {
> > + ...
> > + pinctrl-0 = <&hdmi_off>;
> > + pinctrl-1 = <&hdmi_on>;
> > + pinctrl-names = "hdmi-on", "hdmi-off";
> > + };
> > diff --git a/include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h b/include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h
> > new file mode 100644
> > index 0000000..20f4340
> > --- /dev/null
> > +++ b/include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h
> > @@ -0,0 +1,18 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * pinctrl-tegra-io-pad.h: Tegra I/O pad source voltage configuration constants
> > + * pinctrl bindings.
> > + *
> > + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
> > + *
> > + * Author: Aapo Vienamo <[email protected]>
> > + */
> > +
> > +#ifndef _DT_BINDINGS_PINCTRL_TEGRA_IO_PAD_H
> > +#define _DT_BINDINGS_PINCTRL_TEGRA_IO_PAD_H
> > +
> > +/* Voltage levels of the I/O pad's source rail */
> > +#define TEGRA_IO_PAD_VOLTAGE_1V8 0
> > +#define TEGRA_IO_PAD_VOLTAGE_3V3 1
> > +
> > +#endif
> > --
> > 2.7.4
> >

-Aapo

2018-07-17 14:24:18

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v3 5/7] dt-bindings: Add Tegra PMC pad configuration bindings

On Tue, Jul 17, 2018 at 6:23 AM Aapo Vienamo <[email protected]> wrote:
>
> On Mon, 16 Jul 2018 09:43:09 -0600
> Rob Herring <[email protected]> wrote:
>
> > On Thu, Jul 12, 2018 at 03:00:11PM +0300, Aapo Vienamo wrote:
> > > Document the pinctrl bindings used by the PMC driver for performing pad
> > > configuration. Both nvidia,tegra186-pmc.txt and nvidia,tegra20-pmc.txt
> > > are modified as they both cover SoC generations for which these bindings
> > > apply.
> > >
> > > Add a header defining Tegra PMC pad voltage configurations.
> > >
> > > Signed-off-by: Aapo Vienamo <[email protected]>
> > > Acked-by: Jon Hunter <[email protected]>
> > > ---
> > > .../bindings/arm/tegra/nvidia,tegra186-pmc.txt | 84 +++++++++++++++++++
> > > .../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 95 ++++++++++++++++++++++
> > > include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h | 18 ++++
> > > 3 files changed, 197 insertions(+)
> > > create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h
> > >
> > > diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
> > > index 5a3bf7c..9528f41 100644
> > > --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
> > > +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
> > > @@ -34,3 +34,87 @@ Board DTS:
> > > pmc@c360000 {
> > > nvidia,invert-interrupt;
> > > };
> > > +
> > > +== Pad Control Nodes ==
> > > +
> > > +The PMC can be used to set pad power state and voltage configuration.
> > > +The pad configuration is done via the pinctrl framework. The driver
> > > +implements power-source, low-power-enable, and low-power-disable pinconf
> > > +pin configuration node properties. Each pinctrl pin corresponds to a
> > > +single Tegra PMC pad. Thus, in the following sections of this document
> > > +pin refers to the pinctrl frameworks notion of a Tegra PMC pad.
> >
> > "pinctrl framework" is Linux specific and doesn't belong in the binding.
> > Neither does what a driver supports. Describe what the h/w supports.
> >
> > > +
> > > +The pad configuration state nodes are placed under the pmc node and they
> > > +are referred to by the pinctrl client device properties. For more
> >
> > Another driver detail not relevant.
> >
> > > +information see the examples presented later and
> >
> > examples don't document bindings. The documentation should be complete
> > without examples.
> >
> > > +Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt.
> > > +
> > > +The values accepted by power-source property are
> > > +TEGRA_IO_PAD_VOLTAGE_1V8 and TEGRA_IO_PAD_VOLTAGE_3V3, which are defined
> > > +in dt-bindings/pinctrl/pinctrl-tegra-io-pad.h.
> >
> > You need to list out what properties the child nodes can have.
> >
> > power-source needs a vendor prefix.
>
> Isn't it a generic pinctrl property?

I don't know offhand. Doesn't look like it if you have custom values.

Rob

2018-07-17 15:32:08

by Aapo Vienamo

[permalink] [raw]
Subject: Re: [PATCH v3 5/7] dt-bindings: Add Tegra PMC pad configuration bindings

On Tue, 17 Jul 2018 08:22:07 -0600
Rob Herring <[email protected]> wrote:

> On Tue, Jul 17, 2018 at 6:23 AM Aapo Vienamo <[email protected]> wrote:
> >
> > On Mon, 16 Jul 2018 09:43:09 -0600
> > Rob Herring <[email protected]> wrote:
> >
> > > On Thu, Jul 12, 2018 at 03:00:11PM +0300, Aapo Vienamo wrote:
> > > > Document the pinctrl bindings used by the PMC driver for performing pad
> > > > configuration. Both nvidia,tegra186-pmc.txt and nvidia,tegra20-pmc.txt
> > > > are modified as they both cover SoC generations for which these bindings
> > > > apply.
> > > >
> > > > Add a header defining Tegra PMC pad voltage configurations.
> > > >
> > > > Signed-off-by: Aapo Vienamo <[email protected]>
> > > > Acked-by: Jon Hunter <[email protected]>
> > > > ---
> > > > .../bindings/arm/tegra/nvidia,tegra186-pmc.txt | 84 +++++++++++++++++++
> > > > .../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 95 ++++++++++++++++++++++
> > > > include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h | 18 ++++
> > > > 3 files changed, 197 insertions(+)
> > > > create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
> > > > index 5a3bf7c..9528f41 100644
> > > > --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
> > > > +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
> > > > @@ -34,3 +34,87 @@ Board DTS:
> > > > pmc@c360000 {
> > > > nvidia,invert-interrupt;
> > > > };
> > > > +
> > > > +== Pad Control Nodes ==
> > > > +
> > > > +The PMC can be used to set pad power state and voltage configuration.
> > > > +The pad configuration is done via the pinctrl framework. The driver
> > > > +implements power-source, low-power-enable, and low-power-disable pinconf
> > > > +pin configuration node properties. Each pinctrl pin corresponds to a
> > > > +single Tegra PMC pad. Thus, in the following sections of this document
> > > > +pin refers to the pinctrl frameworks notion of a Tegra PMC pad.
> > >
> > > "pinctrl framework" is Linux specific and doesn't belong in the binding.
> > > Neither does what a driver supports. Describe what the h/w supports.
> > >
> > > > +
> > > > +The pad configuration state nodes are placed under the pmc node and they
> > > > +are referred to by the pinctrl client device properties. For more
> > >
> > > Another driver detail not relevant.
> > >
> > > > +information see the examples presented later and
> > >
> > > examples don't document bindings. The documentation should be complete
> > > without examples.
> > >
> > > > +Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt.
> > > > +
> > > > +The values accepted by power-source property are
> > > > +TEGRA_IO_PAD_VOLTAGE_1V8 and TEGRA_IO_PAD_VOLTAGE_3V3, which are defined
> > > > +in dt-bindings/pinctrl/pinctrl-tegra-io-pad.h.
> > >
> > > You need to list out what properties the child nodes can have.
> > >
> > > power-source needs a vendor prefix.
> >
> > Isn't it a generic pinctrl property?
>
> I don't know offhand. Doesn't look like it if you have custom values.

It's listed under "Supported generic properties" in
pinctrl-bindings.txt. The convention seems to be not to add a vendor
prefix even though such custom macro values are used. The property is
currently used by qcom,pmic-gpio, qcom,pmic-mpp, and renesas,pfc-pinctrl.
I could not find a bindings document describing it with a vendor prefix.

-Aapo

2018-07-20 11:17:05

by Jon Hunter

[permalink] [raw]
Subject: Re: [PATCH v3 5/7] dt-bindings: Add Tegra PMC pad configuration bindings

Adding Linus ...

On 17/07/18 16:30, Aapo Vienamo wrote:

...

>>>>> +Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt.
>>>>> +
>>>>> +The values accepted by power-source property are
>>>>> +TEGRA_IO_PAD_VOLTAGE_1V8 and TEGRA_IO_PAD_VOLTAGE_3V3, which are defined
>>>>> +in dt-bindings/pinctrl/pinctrl-tegra-io-pad.h.
>>>>
>>>> You need to list out what properties the child nodes can have.
>>>>
>>>> power-source needs a vendor prefix.
>>>
>>> Isn't it a generic pinctrl property?
>>
>> I don't know offhand. Doesn't look like it if you have custom values.
>
> It's listed under "Supported generic properties" in
> pinctrl-bindings.txt. The convention seems to be not to add a vendor
> prefix even though such custom macro values are used. The property is
> currently used by qcom,pmic-gpio, qcom,pmic-mpp, and renesas,pfc-pinctrl.
> I could not find a bindings document describing it with a vendor prefix.
Looking at other users of the 'power-source' property it is not clear to
me if the values should/can be vendor specific or not. I see cases where
some people use definitions and others use actual voltages.

Linus, any recommendations here?

Cheers
Jon

--
nvpublic

2018-07-29 21:15:21

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH v3 5/7] dt-bindings: Add Tegra PMC pad configuration bindings

On Fri, Jul 20, 2018 at 1:16 PM Jon Hunter <[email protected]> wrote:

> Adding Linus ...

OMG this sounds bad.

> >> I don't know offhand. Doesn't look like it if you have custom values.
> >
> > It's listed under "Supported generic properties" in
> > pinctrl-bindings.txt. The convention seems to be not to add a vendor
> > prefix even though such custom macro values are used. The property is
> > currently used by qcom,pmic-gpio, qcom,pmic-mpp, and renesas,pfc-pinctrl.
> > I could not find a bindings document describing it with a vendor prefix.
>
> Looking at other users of the 'power-source' property it is not clear to
> me if the values should/can be vendor specific or not. I see cases where
> some people use definitions and others use actual voltages.
>
> Linus, any recommendations here?

It's a bit of imperfect world here.

I always imagines it was some kind of enumerator
like source A, B or C... so 0, 1 defined in sime include/dt-bindings/*
would make most sense to me.

In general, use SI-units if you can, else use something that makes
sense for the people writing the device tree. These enumerators
seems to make sense.

If nothing makes any sense, maybe a custom property makes it
make sense.

Yours,
Linus Walleij