2018-08-02 12:03:35

by Venkat Reddy Talla

[permalink] [raw]
Subject: [PATCH 1/3] soc/tegra: pmc: set IO pad power state and voltage via pinctrl fw

The IO pins of Tegra SoCs are grouped for common control
of IO interface like setting voltage signal levels and
power state of the interface. These groups are referred
to as IO pads.The power state and voltage control of IO pins
can be done at IO pads level.

Tegra SoCs support powering down IO pads when they are
not used even in the active state of system.
This saves power from that IO interface. Also it supports
multiple voltage level in IO pins for interfacing on
some of pads. The IO pad voltage is automatically detected
till Tegra124, hence SW need not to configure this.
But from Tegra210, the automatic detection logic has been
removed, hence SW need to explicitly set the IO pad
voltage into IO pad configuration registers.

Add support to configure the power state and voltage level
of the IO pads from client driver via pincontrol framework.

Signed-off-by: Venkat Reddy Talla <[email protected]>
---
drivers/soc/tegra/pmc.c | 891 +++++++++++++++++++++++++++++++++++++-----------
include/soc/tegra/pmc.h | 21 +-
2 files changed, 701 insertions(+), 211 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 2d6f3fc..af69f42 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-generic.h>
+#include <linux/pinctrl/pinconf.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/reboot.h>
@@ -45,6 +48,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 */
@@ -118,6 +123,17 @@

#define GPU_RG_CNTRL 0x2d4

+#define TEGRA_PMC_SEL_DPD_TIM 0x1c8
+#define TEGRA_PMC_IO_DPD_SAMPLE 0x20
+#define TEGRA_PMC_PWR_DET_ENABLE 0x48
+#define TEGRA_PMC_PWR_DET_VAL 0xe4
+#define TEGRA_PMC_IO_DPD_REQ 0x74
+#define TEGRA_PMC_IO_DPD_STATUS 0x78
+#define TEGRA_PMC_IO_DPD2_REQ 0x7C
+#define TEGRA_PMC_IO_DPD2_STATUS 0x80
+#define TEGRA_PMC_E_18V_PWR 0x3C
+#define TEGRA_PMC_E_33V_PWR 0x40
+
/* Tegra186 and later */
#define WAKE_AOWAKE_CTRL 0x4f4
#define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0)
@@ -132,9 +148,21 @@ struct tegra_powergate {
};

struct tegra_io_pad_soc {
- enum tegra_io_pad id;
+ const char *name;
+ const unsigned int pins[1];
+ unsigned int npins;
unsigned int dpd;
unsigned int voltage;
+ unsigned int io_power;
+ unsigned int dpd_req_reg;
+ unsigned int dpd_status_reg;
+ unsigned int dpd_timer_reg;
+ unsigned int dpd_sample_reg;
+ unsigned int pwr_det_enable_reg;
+ unsigned int pwr_det_val_reg;
+ unsigned int pad_uv_0;
+ unsigned int pad_uv_1;
+ bool bdsdmem_cfc;
};

struct tegra_pmc_regs {
@@ -157,6 +185,8 @@ struct tegra_pmc_soc {

const struct tegra_io_pad_soc *io_pads;
unsigned int num_io_pads;
+ const struct pinctrl_pin_desc *descs;
+ unsigned int num_descs;

const struct tegra_pmc_regs *regs;
void (*init)(struct tegra_pmc *pmc);
@@ -187,6 +217,10 @@ struct tegra_pmc_soc {
* @lp0_vec_size: size of the LP0 warm boot code
* @powergates_available: Bitmap of available power gates
* @powergates_lock: mutex for power gate register access
+ * @pctl: pinctrl handle which is returned after registering pinctrl
+ * @pinctrl_desc: Pincontrol descriptor for IO pads
+ * @allow_dynamic_switch: restrict the voltage change for each io pad
+ * @voltage_switch_restriction_enabled: restrict voltage switch for all io pads
*/
struct tegra_pmc {
struct device *dev;
@@ -216,6 +250,15 @@ struct tegra_pmc {
DECLARE_BITMAP(powergates_available, TEGRA_POWERGATE_MAX);

struct mutex powergates_lock;
+ struct pinctrl_dev *pctl;
+ struct pinctrl_desc pinctrl_desc;
+ bool *allow_dynamic_switch;
+ bool voltage_switch_restriction_enabled;
+};
+
+static const char * const tegra_sor_pad_names[] = {
+ [TEGRA_IO_RAIL_HDMI] = "hdmi",
+ [TEGRA_IO_RAIL_LVDS] = "lvds",
};

static struct tegra_pmc *pmc = &(struct tegra_pmc) {
@@ -907,70 +950,42 @@ static void tegra_powergate_init(struct tegra_pmc *pmc,
of_node_put(np);
}

-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, u32 *mask)
+static int tegra_io_pad_prepare(const struct tegra_io_pad_soc *pad)
{
- const struct tegra_io_pad_soc *pad;
unsigned long rate, value;

- pad = tegra_io_pad_find(pmc, id);
- if (!pad) {
- pr_err("invalid I/O pad ID %u\n", id);
- return -ENOENT;
- }
-
if (pad->dpd == UINT_MAX)
return -ENOTSUPP;

- *mask = BIT(pad->dpd % 32);
+ if (!pmc->clk)
+ return 0;

- if (pad->dpd < 32) {
- *status = pmc->soc->regs->dpd_status;
- *request = pmc->soc->regs->dpd_req;
- } else {
- *status = pmc->soc->regs->dpd2_status;
- *request = pmc->soc->regs->dpd2_req;
+ rate = clk_get_rate(pmc->clk);
+ if (!rate) {
+ dev_err(pmc->dev, "Failed to get clock rate\n");
+ return -ENODEV;
}

- if (pmc->clk) {
- rate = clk_get_rate(pmc->clk);
- if (!rate) {
- pr_err("failed to get clock rate\n");
- return -ENODEV;
- }
+ tegra_pmc_writel(DPD_SAMPLE_ENABLE, pad->dpd_sample_reg);

- tegra_pmc_writel(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
-
- /* must be at least 200 ns, in APB (PCLK) clock cycles */
- value = DIV_ROUND_UP(1000000000, rate);
- value = DIV_ROUND_UP(200, value);
- tegra_pmc_writel(value, SEL_DPD_TIM);
- }
+ /* must be at least 200 ns, in APB (PCLK) clock cycles */
+ value = DIV_ROUND_UP(1000000000, rate);
+ value = DIV_ROUND_UP(200, value);
+ tegra_pmc_writel(value, pad->dpd_timer_reg);

return 0;
}

-static int tegra_io_pad_poll(unsigned long offset, u32 mask,
+static int tegra_io_pad_poll(const struct tegra_io_pad_soc *pad,
u32 val, unsigned long timeout)
{
u32 value;
+ u32 mask = BIT(pad->dpd);

timeout = jiffies + msecs_to_jiffies(timeout);

while (time_after(timeout, jiffies)) {
- value = tegra_pmc_readl(offset);
+ value = tegra_pmc_readl(pad->dpd_status_reg);
if ((value & mask) == val)
return 0;

@@ -980,10 +995,22 @@ static int tegra_io_pad_poll(unsigned long offset, u32 mask,
return -ETIMEDOUT;
}

-static void tegra_io_pad_unprepare(void)
+static void tegra_io_pad_unprepare(const struct tegra_io_pad_soc *pad)
{
if (pmc->clk)
- tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
+ tegra_pmc_writel(DPD_SAMPLE_DISABLE, pad->dpd_sample_reg);
+}
+
+static const struct tegra_io_pad_soc *tegra_get_pad_by_name(const char *pname)
+{
+ unsigned int i;
+
+ for (i = 0; i < pmc->soc->num_io_pads; ++i) {
+ if (!strcmp(pname, pmc->soc->io_pads[i].name))
+ return &pmc->soc->io_pads[i];
+ }
+
+ return NULL;
}

/**
@@ -992,35 +1019,33 @@ static void tegra_io_pad_unprepare(void)
*
* Returns: 0 on success or a negative error code on failure.
*/
-int tegra_io_pad_power_enable(enum tegra_io_pad id)
+static int tegra_io_pad_power_enable(const struct tegra_io_pad_soc *pad)
{
- unsigned long request, status;
- u32 mask;
int err;

mutex_lock(&pmc->powergates_lock);

- err = tegra_io_pad_prepare(id, &request, &status, &mask);
+ err = tegra_io_pad_prepare(pad);
if (err < 0) {
- pr_err("failed to prepare I/O pad: %d\n", err);
+ pr_err("failed to prepare I/O pad %s: %d\n", pad->name, err);
goto unlock;
}

- tegra_pmc_writel(IO_DPD_REQ_CODE_OFF | mask, request);
+ tegra_pmc_writel(IO_DPD_REQ_CODE_OFF | BIT(pad->dpd),
+ pad->dpd_req_reg);

- err = tegra_io_pad_poll(status, mask, 0, 250);
+ err = tegra_io_pad_poll(pad, 0, 250);
if (err < 0) {
- pr_err("failed to enable I/O pad: %d\n", err);
+ pr_err("failed to enable I/O pad %s: %d\n", pad->name, err);
goto unlock;
}

- tegra_io_pad_unprepare();
+ tegra_io_pad_unprepare(pad);

unlock:
mutex_unlock(&pmc->powergates_lock);
return err;
}
-EXPORT_SYMBOL(tegra_io_pad_power_enable);

/**
* tegra_io_pad_power_disable() - disable power to I/O pad
@@ -1028,65 +1053,63 @@ EXPORT_SYMBOL(tegra_io_pad_power_enable);
*
* Returns: 0 on success or a negative error code on failure.
*/
-int tegra_io_pad_power_disable(enum tegra_io_pad id)
+static int tegra_io_pad_power_disable(const struct tegra_io_pad_soc *pad)
{
- unsigned long request, status;
- u32 mask;
int err;

mutex_lock(&pmc->powergates_lock);

- err = tegra_io_pad_prepare(id, &request, &status, &mask);
+ err = tegra_io_pad_prepare(pad);
if (err < 0) {
- pr_err("failed to prepare I/O pad: %d\n", err);
+ pr_err("failed to prepare I/O pad %s: %d\n", pad->name, err);
goto unlock;
}

- tegra_pmc_writel(IO_DPD_REQ_CODE_ON | mask, request);
+ tegra_pmc_writel(IO_DPD_REQ_CODE_ON | BIT(pad->dpd),
+ pad->dpd_req_reg);

- err = tegra_io_pad_poll(status, mask, mask, 250);
+ err = tegra_io_pad_poll(pad, BIT(pad->dpd), 250);
if (err < 0) {
- pr_err("failed to disable I/O pad: %d\n", err);
+ pr_err("failed to disable I/O pad %s: %d\n", pad->name, err);
goto unlock;
}

- tegra_io_pad_unprepare();
+ tegra_io_pad_unprepare(pad);

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)
+static int tegra_io_pad_set_voltage(const struct tegra_io_pad_soc *pad,
+ int io_pad_uv)
{
- 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;

+ if (io_pad_uv != pad->pad_uv_0 && io_pad_uv != pad->pad_uv_1)
+ return -EINVAL;
+
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 (pad->pwr_det_enable_reg != UINT_MAX) {
+ value = tegra_pmc_readl(pad->pwr_det_enable_reg);
+ value |= BIT(pad->voltage);
+ tegra_pmc_writel(value, pad->pwr_det_enable_reg);
+ }

/* update I/O voltage */
- value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
+ value = tegra_pmc_readl(pad->pwr_det_val_reg);

- if (voltage == TEGRA_IO_PAD_1800000UV)
+ if (io_pad_uv == pad->pad_uv_0)
value &= ~BIT(pad->voltage);
else
value |= BIT(pad->voltage);

- tegra_pmc_writel(value, PMC_PWR_DET_VALUE);
+ tegra_pmc_writel(value, pad->pwr_det_val_reg);

mutex_unlock(&pmc->powergates_lock);

@@ -1094,28 +1117,289 @@ 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(const struct tegra_io_pad_soc *pad)
{
- 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);
+ value = tegra_pmc_readl(pad->pwr_det_val_reg);

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

- return TEGRA_IO_PAD_3300000UV;
+ return pad->pad_uv_1;
+}
+
+/**
+ * tegra_io_pad_is_powered() - check if IO pad is powered
+ * @pad: Tegra I/O pad SOC data for which power status need to check
+ *
+ * Return 1 if power-ON, 0 if power OFF and error number in
+ * negative if pad ID is not valid or power down not supported
+ * on given IO pad.
+ */
+static int tegra_io_pad_is_powered(const struct tegra_io_pad_soc *pad)
+{
+ u32 value;
+
+ if (pad->dpd == UINT_MAX)
+ return -ENOTSUPP;
+
+ value = tegra_pmc_readl(pad->dpd_status_reg);
+
+ return !(value & BIT(pad->dpd));
+}
+
+static int tegra_io_pads_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct tegra_pmc *tpmc = pinctrl_dev_get_drvdata(pctldev);
+
+ return tpmc->soc->num_io_pads;
+}
+
+static const char *tegra_io_pads_pinctrl_get_group_name(
+ struct pinctrl_dev *pctldev, unsigned int group)
+{
+ struct tegra_pmc *tpmc = pinctrl_dev_get_drvdata(pctldev);
+
+ return tpmc->soc->io_pads[group].name;
+}
+
+static int tegra_io_pads_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned int group,
+ const unsigned int **pins,
+ unsigned int *num_pins)
+{
+ struct tegra_pmc *tpmc = pinctrl_dev_get_drvdata(pctldev);
+
+ *pins = tpmc->soc->io_pads[group].pins;
+ *num_pins = tpmc->soc->io_pads[group].npins;
+
+ return 0;
+}
+
+enum tegra_io_rail_pads_params {
+ TEGRA_IO_PAD_POWER_SOURCE_VOLTAGE = PIN_CONFIG_END + 1,
+ TEGRA_IO_PAD_DYNAMIC_VOLTAGE_SWITCH = PIN_CONFIG_END + 2,
+};
+
+static const struct pinconf_generic_params tegra_io_pads_cfg_params[] = {
+ {
+ .property = "nvidia,power-source-voltage",
+ .param = TEGRA_IO_PAD_POWER_SOURCE_VOLTAGE,
+ }, {
+ .property = "nvidia,enable-voltage-switching",
+ .param = TEGRA_IO_PAD_DYNAMIC_VOLTAGE_SWITCH,
+ },
+};
+
+static const struct pinctrl_ops tegra_io_pads_pinctrl_ops = {
+ .get_groups_count = tegra_io_pads_pinctrl_get_groups_count,
+ .get_group_name = tegra_io_pads_pinctrl_get_group_name,
+ .get_group_pins = tegra_io_pads_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_pads_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int pin,
+ unsigned long *config)
+{
+ struct tegra_pmc *tpmc = pinctrl_dev_get_drvdata(pctldev);
+ u16 param = pinconf_to_config_param(*config);
+ const struct tegra_io_pad_soc *pad = &tpmc->soc->io_pads[pin];
+ u16 arg = 0;
+ int ret;
+
+ switch (param) {
+ case PIN_CONFIG_LOW_POWER_MODE:
+ ret = tegra_io_pad_is_powered(pad);
+ if (ret < 0)
+ return ret;
+ arg = !ret;
+ break;
+ case TEGRA_IO_PAD_POWER_SOURCE_VOLTAGE:
+ if (pmc->soc->io_pads[pin].voltage == UINT_MAX)
+ return -EINVAL;
+
+ ret = tegra_io_pad_get_voltage(pad);
+ if (ret < 0)
+ return ret;
+ arg = ret;
+ break;
+ case TEGRA_IO_PAD_DYNAMIC_VOLTAGE_SWITCH:
+ if (pmc->soc->io_pads[pin].voltage == UINT_MAX)
+ return -EINVAL;
+
+ if (pmc->voltage_switch_restriction_enabled &&
+ pmc->allow_dynamic_switch[pin])
+ arg = 1;
+ else
+ arg = 0;
+ break;
+ default:
+ dev_dbg(tpmc->dev, "I/O pad %s does not support param %d\n",
+ pad->name, param);
+ return -EINVAL;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+
+ return 0;
+}
+
+static int tegra_io_pads_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct tegra_pmc *tpmc = pinctrl_dev_get_drvdata(pctldev);
+ const struct tegra_io_pad_soc *pad = &tpmc->soc->io_pads[pin];
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < num_configs; i++) {
+ u16 param_val = pinconf_to_config_argument(configs[i]);
+ u16 param = pinconf_to_config_param(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_LOW_POWER_MODE:
+ if (param_val)
+ ret = tegra_io_pad_power_disable(pad);
+ else
+ ret = tegra_io_pad_power_enable(pad);
+ if (ret < 0) {
+ dev_err(tpmc->dev,
+ "Failed to set low power %s of I/O pad %s: %d\n",
+ (param_val) ? "disable" : "enable",
+ pad->name, ret);
+ return ret;
+ }
+ break;
+ case TEGRA_IO_PAD_POWER_SOURCE_VOLTAGE:
+ if (pmc->soc->io_pads[pin].voltage == UINT_MAX)
+ return -EINVAL;
+
+ if (pmc->voltage_switch_restriction_enabled &&
+ !pmc->allow_dynamic_switch[pin]) {
+ dev_err(tpmc->dev,
+ "IO Pad %s: Dynamic voltage switching not allowed\n",
+ pad->name);
+ return -EINVAL;
+ }
+
+ ret = tegra_io_pad_set_voltage(pad, param_val);
+ if (ret < 0) {
+ dev_err(tpmc->dev,
+ "Failed to set voltage %d of pin %u: %d\n",
+ param_val, pin, ret);
+ return ret;
+ }
+ break;
+ case TEGRA_IO_PAD_DYNAMIC_VOLTAGE_SWITCH:
+ if (pmc->soc->io_pads[pin].voltage == UINT_MAX)
+ return -EINVAL;
+
+ pmc->allow_dynamic_switch[pin] = true;
+ break;
+ default:
+ dev_err(tpmc->dev, "I/O pad %s does not support param %d\n",
+ pad->name, param);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void tegra_io_pads_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned int pin)
+{
+ struct tegra_pmc *tpmc = pinctrl_dev_get_drvdata(pctldev);
+ unsigned long config = 0;
+ u16 param, param_val;
+ int ret;
+ int i;
+
+ for (i = 0; i < tpmc->pinctrl_desc.num_custom_params; ++i) {
+ param = tpmc->pinctrl_desc.custom_params[i].param;
+ config = pinconf_to_config_packed(param, 0);
+ ret = tegra_io_pads_pinconf_get(pctldev, pin, &config);
+ if (ret < 0)
+ continue;
+ param_val = pinconf_to_config_argument(config);
+ switch (param) {
+ case TEGRA_IO_PAD_POWER_SOURCE_VOLTAGE:
+ if (param_val == TEGRA_IO_PAD_VOLTAGE_1200000UV)
+ seq_puts(s, "\n\t\tPad voltage 1200000uV");
+ else if (param_val == TEGRA_IO_PAD_VOLTAGE_1800000UV)
+ seq_puts(s, "\n\t\tPad voltage 1800000uV");
+ else
+ seq_puts(s, "\n\t\tPad voltage 3300000uV");
+ break;
+ case TEGRA_IO_PAD_DYNAMIC_VOLTAGE_SWITCH:
+ seq_printf(s, "\n\t\tSwitching voltage: %s",
+ (param_val) ? "Enable" : "Disable");
+ break;
+ default:
+ break;
+ }
+ }
+}
+#else
+static void tegra_io_pads_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned int pin)
+{
+}
+#endif
+
+static const struct pinconf_ops tegra_io_pads_pinconf_ops = {
+ .pin_config_get = tegra_io_pads_pinconf_get,
+ .pin_config_set = tegra_io_pads_pinconf_set,
+ .pin_config_dbg_show = tegra_io_pads_pinconf_dbg_show,
+ .is_generic = true,
+};
+
+static int tegra_io_pads_pinctrl_init(struct tegra_pmc *pmc)
+{
+ if (!pmc->soc->num_descs)
+ return 0;
+
+ pmc->allow_dynamic_switch = devm_kzalloc(pmc->dev, pmc->soc->num_descs *
+ sizeof(*pmc->allow_dynamic_switch),
+ GFP_KERNEL);
+ if (!pmc->allow_dynamic_switch) {
+ pr_err("failed to allocate allow_dynamic_switch\n");
+ return 0;
+ }
+
+ pmc->voltage_switch_restriction_enabled = false;
+ pmc->pinctrl_desc.name = "pinctrl-pmc-io-pads";
+ pmc->pinctrl_desc.pctlops = &tegra_io_pads_pinctrl_ops;
+ pmc->pinctrl_desc.confops = &tegra_io_pads_pinconf_ops;
+ pmc->pinctrl_desc.pins = pmc->soc->descs;
+ pmc->pinctrl_desc.npins = pmc->soc->num_descs;
+ pmc->pinctrl_desc.custom_params = tegra_io_pads_cfg_params;
+ pmc->pinctrl_desc.num_custom_params =
+ ARRAY_SIZE(tegra_io_pads_cfg_params);
+
+ pmc->pctl = devm_pinctrl_register(pmc->dev, &pmc->pinctrl_desc, pmc);
+ if (IS_ERR(pmc->pctl)) {
+ int ret = PTR_ERR(pmc->pctl);
+
+ pr_err("failed to register pinctrl-io-pad: %d\n", ret);
+ return ret;
+ }
+
+ pmc->voltage_switch_restriction_enabled =
+ of_property_read_bool(pmc->dev->of_node,
+ "nvidia,restrict-voltage-switch");
+
+ return 0;
}
-EXPORT_SYMBOL(tegra_io_pad_get_voltage);

/**
* tegra_io_rail_power_on() - enable power to I/O rail
@@ -1125,7 +1409,20 @@ EXPORT_SYMBOL(tegra_io_pad_get_voltage);
*/
int tegra_io_rail_power_on(unsigned int id)
{
- return tegra_io_pad_power_enable(id);
+ const struct tegra_io_pad_soc *pad;
+
+ if (id != TEGRA_IO_RAIL_LVDS && id != TEGRA_IO_RAIL_HDMI) {
+ dev_err(pmc->dev, "invalid pad id\n");
+ return -EINVAL;
+ }
+
+ pad = tegra_get_pad_by_name(tegra_sor_pad_names[id]);
+ if (!pad) {
+ dev_err(pmc->dev, "IO Pad not found\n");
+ return -EINVAL;
+ }
+
+ return tegra_io_pad_power_enable(pad);
}
EXPORT_SYMBOL(tegra_io_rail_power_on);

@@ -1137,7 +1434,20 @@ EXPORT_SYMBOL(tegra_io_rail_power_on);
*/
int tegra_io_rail_power_off(unsigned int id)
{
- return tegra_io_pad_power_disable(id);
+ const struct tegra_io_pad_soc *pad;
+
+ if (id != TEGRA_IO_RAIL_LVDS && id != TEGRA_IO_RAIL_HDMI) {
+ dev_err(pmc->dev, "invalid pad id\n");
+ return -EINVAL;
+ }
+
+ pad = tegra_get_pad_by_name(tegra_sor_pad_names[id]);
+ if (!pad) {
+ dev_err(pmc->dev, "IO Pad not found\n");
+ return -EINVAL;
+ }
+
+ return tegra_io_pad_power_disable(pad);
}
EXPORT_SYMBOL(tegra_io_rail_power_off);

@@ -1436,6 +1746,10 @@ static int tegra_pmc_probe(struct platform_device *pdev)
return err;
}

+ err = tegra_io_pads_pinctrl_init(pmc);
+ if (err < 0)
+ return err;
+
mutex_lock(&pmc->powergates_lock);
iounmap(pmc->base);
pmc->base = base;
@@ -1649,37 +1963,77 @@ static const u8 tegra124_cpu_powergates[] = {
TEGRA_POWERGATE_CPU3,
};

+#define TEGRA124_IO_PAD_CONFIG(_pin, _npins, _name, _dpd, \
+ _vbit, _iopower, _reg) \
+ { \
+ .name = #_name, \
+ .pins = {(_pin)}, \
+ .npins = _npins, \
+ .dpd = _dpd, \
+ .voltage = _vbit, \
+ .io_power = _iopower, \
+ .dpd_req_reg = TEGRA_PMC_IO_##_reg##_REQ, \
+ .dpd_status_reg = TEGRA_PMC_IO_##_reg##_STATUS, \
+ .dpd_timer_reg = TEGRA_PMC_SEL_DPD_TIM, \
+ .dpd_sample_reg = TEGRA_PMC_IO_DPD_SAMPLE, \
+ .pwr_det_enable_reg = TEGRA_PMC_PWR_DET_ENABLE, \
+ .pwr_det_val_reg = TEGRA_PMC_PWR_DET_VAL, \
+ },
+
+/**
+ * All IO pads of Tegra SoCs do not support the low power and multi level
+ * voltage configurations for its pads.
+ * Defining macros for different cases as follows:
+ * TEGRA_IO_PAD_LPONLY : IO pad which support low power state but
+ * operate in single level of IO voltage.
+ */
+#define TEGRA124_IO_PAD_LPONLY(_pin, _name, _dpd, _reg) \
+ TEGRA124_IO_PAD_CONFIG(_pin, 1, _name, _dpd, UINT_MAX, UINT_MAX, _reg)
+
+#define TEGRA124_IO_PAD_DESC_LP(_pin, _name, _dpd, _reg) \
+ { \
+ .number = _pin, \
+ .name = #_name, \
+ },
+
+#define TEGRA124_IO_PAD_TABLE(_lponly_, _pvonly_, _lp_n_pv_) \
+ _lponly_(0, audio, 17, DPD) \
+ _lponly_(1, bb, 15, DPD) \
+ _lponly_(2, cam, 4, DPD2) \
+ _lponly_(3, comp, 22, DPD) \
+ _lponly_(4, csia, 0, DPD2) \
+ _lponly_(5, csib, 1, DPD2) \
+ _lponly_(6, csie, 12, DPD2) \
+ _lponly_(7, dp, 19, DPD2) \
+ _lponly_(8, dsi, 2, DPD) \
+ _lponly_(9, dsib, 7, DPD2) \
+ _lponly_(10, dsic, 8, DPD2) \
+ _lponly_(11, dsid, 9, DPD2) \
+ _lponly_(12, hdmi, 28, DPD) \
+ _lponly_(13, hsic, 19, DPD) \
+ _lponly_(14, lvds, 25, DPD2) \
+ _lponly_(15, mipi-bias, 3, DPD) \
+ _lponly_(16, nand, 13, DPD) \
+ _lponly_(17, pex-bias, 4, DPD) \
+ _lponly_(18, pex-clk1, 5, DPD) \
+ _lponly_(19, pex-clk2, 6, DPD) \
+ _lponly_(20, pex-ctrl, 0, DPD2) \
+ _lponly_(21, sdmmc1, 1, DPD2) \
+ _lponly_(22, sdmmc3, 2, DPD2) \
+ _lponly_(23, sdmmc4, 3, DPD2) \
+ _lponly_(24, sys-ddc, 26, DPD) \
+ _lponly_(25, uart, 14, DPD) \
+ _lponly_(26, usb0, 9, DPD) \
+ _lponly_(27, usb1, 10, DPD) \
+ _lponly_(28, usb2, 11, DPD) \
+ _lponly_(29, usb-bias, 12, DPD) \
+
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(TEGRA124_IO_PAD_LPONLY, NULL, NULL)
+};
+
+static const struct pinctrl_pin_desc tegra124_io_pads_pinctrl_desc[] = {
+ TEGRA124_IO_PAD_TABLE(TEGRA124_IO_PAD_DESC_LP, NULL, NULL)
};

static const struct tegra_pmc_soc tegra124_pmc_soc = {
@@ -1694,6 +2048,8 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
.regs = &tegra20_pmc_regs,
.init = tegra20_pmc_init,
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
+ .num_descs = ARRAY_SIZE(tegra124_io_pads_pinctrl_desc),
+ .descs = tegra124_io_pads_pinctrl_desc,
};

static const char * const tegra210_powergates[] = {
@@ -1730,45 +2086,111 @@ static const u8 tegra210_cpu_powergates[] = {
TEGRA_POWERGATE_CPU3,
};

+#define TEGRA210X_IO_PAD_CONFIG(_pin, _npins, _name, _dpd, \
+ _vbit, _iopower, _reg, _bds) \
+ { \
+ .name = #_name, \
+ .pins = {(_pin)}, \
+ .npins = _npins, \
+ .dpd = _dpd, \
+ .voltage = _vbit, \
+ .io_power = _iopower, \
+ .dpd_req_reg = TEGRA_PMC_IO_##_reg##_REQ, \
+ .dpd_status_reg = TEGRA_PMC_IO_##_reg##_STATUS, \
+ .dpd_timer_reg = TEGRA_PMC_SEL_DPD_TIM, \
+ .dpd_sample_reg = TEGRA_PMC_IO_DPD_SAMPLE, \
+ .bdsdmem_cfc = _bds, \
+ .pwr_det_enable_reg = TEGRA_PMC_PWR_DET_ENABLE, \
+ .pwr_det_val_reg = TEGRA_PMC_PWR_DET_VAL, \
+ .pad_uv_0 = TEGRA_IO_PAD_VOLTAGE_1800000UV, \
+ .pad_uv_1 = TEGRA_IO_PAD_VOLTAGE_3300000UV, \
+ },
+
+#define TEGRA210_IO_PAD_CONFIG(_pin, _npins, _name, _dpd, \
+ _vbit, _iopower, _reg) \
+ TEGRA210X_IO_PAD_CONFIG(_pin, _npins, _name, _dpd, \
+ _vbit, _iopower, _reg, false)
+
+/**
+ * All IO pads of Tegra SoCs do not support the low power and multi level
+ * voltage configurations for its pads.
+ * Defining macros for different cases as follows:
+ * TEGRA_IO_PAD_LPONLY : IO pad which support low power state but
+ * operate in single level of IO voltage.
+ * TEGRA_IO_PAD_LP_N_PV: IO pad which support low power state as well as
+ * it can operate in multi-level voltages.
+ * TEGRA_IO_PAD_PVONLY: IO pad which does not support low power state but
+ * it can operate in multi-level voltages.
+ */
+#define TEGRA210_IO_PAD_LPONLY(_pin, _name, _dpd, _reg) \
+ TEGRA210_IO_PAD_CONFIG(_pin, 1, _name, _dpd, UINT_MAX, UINT_MAX, _reg)
+
+#define TEGRA210_IO_PAD_LP_N_PV(_pin, _name, _dpd, _vbit, _io, _reg) \
+ TEGRA210_IO_PAD_CONFIG(_pin, 1, _name, _dpd, _vbit, _io, _reg)
+
+#define TEGRA210_IO_PAD_PVONLY(_pin, _name, _vbit, _io, _reg) \
+ TEGRA210_IO_PAD_CONFIG(_pin, 0, _name, UINT_MAX, _vbit, _io, _reg)
+
+#define TEGRA210_IO_PAD_DESC_LP(_pin, _name, _dpd, _reg) \
+ { \
+ .number = _pin, \
+ .name = #_name, \
+ },
+#define TEGRA210_IO_PAD_DESC_LP_N_PV(_pin, _name, _dpd, _vbit, _io, _reg) \
+ TEGRA210_IO_PAD_DESC_LP(_pin, _name, _dpd, _reg)
+
+#define TEGRA210_IO_PAD_DESC_PV(_pin, _name, _vbit, _io, _reg) \
+ TEGRA210_IO_PAD_DESC_LP(_pin, _name, UINT_MAX, _reg)
+
+#define TEGRA210_IO_PAD_TABLE(_lponly_, _pvonly_, _lp_n_pv_) \
+ _lp_n_pv_(0, audio, 17, 5, 5, DPD) \
+ _lp_n_pv_(1, audio-hv, 29, 18, 18, DPD2) \
+ _lp_n_pv_(2, cam, 4, 10, 10, DPD2) \
+ _lponly_(3, csia, 0, DPD) \
+ _lponly_(4, csib, 1, DPD) \
+ _lponly_(5, csic, 10, DPD2) \
+ _lponly_(6, csid, 11, DPD2) \
+ _lponly_(7, csie, 12, DPD2) \
+ _lponly_(8, csif, 13, DPD2) \
+ _lp_n_pv_(9, dbg, 25, 19, 19, DPD) \
+ _lponly_(10, debug-nonao, 26, DPD) \
+ _lp_n_pv_(11, dmic, 18, 20, 20, DPD2) \
+ _lponly_(12, dp, 19, DPD2) \
+ _lponly_(13, dsi, 2, DPD) \
+ _lponly_(14, dsib, 7, DPD2) \
+ _lponly_(15, dsic, 8, DPD2) \
+ _lponly_(16, dsid, 9, DPD2) \
+ _lponly_(17, emmc, 3, DPD2) \
+ _lponly_(18, emmc2, 5, DPD2) \
+ _lp_n_pv_(19, gpio, 27, 21, 21, DPD) \
+ _lponly_(20, hdmi, 28, DPD) \
+ _lponly_(21, hsic, 19, DPD) \
+ _lponly_(22, lvds, 25, DPD2) \
+ _lponly_(23, mipi-bias, 3, DPD) \
+ _lponly_(24, pex-bias, 4, DPD) \
+ _lponly_(25, pex-clk1, 5, DPD) \
+ _lponly_(26, pex-clk2, 6, DPD) \
+ _pvonly_(27, pex-ctrl, 11, 11, DPD2) \
+ _lp_n_pv_(28, sdmmc1, 1, 12, 12, DPD2) \
+ _lp_n_pv_(29, sdmmc3, 2, 13, 13, DPD2) \
+ _lp_n_pv_(30, spi, 14, 22, 22, DPD2) \
+ _lp_n_pv_(31, spi-hv, 15, 23, 23, DPD2) \
+ _lp_n_pv_(32, uart, 14, 2, 2, DPD) \
+ _lponly_(33, usb0, 9, DPD) \
+ _lponly_(34, usb1, 10, DPD) \
+ _lponly_(35, usb2, 11, DPD) \
+ _lponly_(36, usb3, 18, DPD) \
+ _lponly_(37, usb-bias, 12, DPD) \
+ _pvonly_(38, sys, 12, UINT_MAX, DPD)
+
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(TEGRA210_IO_PAD_LPONLY, TEGRA210_IO_PAD_PVONLY,
+ TEGRA210_IO_PAD_LP_N_PV)
+};
+
+static const struct pinctrl_pin_desc tegra210_io_pads_pinctrl_desc[] = {
+ TEGRA210_IO_PAD_TABLE(TEGRA210_IO_PAD_DESC_LP, TEGRA210_IO_PAD_DESC_PV,
+ TEGRA210_IO_PAD_DESC_LP_N_PV)
};

static const struct tegra_pmc_soc tegra210_pmc_soc = {
@@ -1782,50 +2204,12 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
.num_io_pads = ARRAY_SIZE(tegra210_io_pads),
.io_pads = tegra210_io_pads,
.regs = &tegra20_pmc_regs,
+ .num_descs = ARRAY_SIZE(tegra210_io_pads_pinctrl_desc),
+ .descs = tegra210_io_pads_pinctrl_desc,
.init = tegra20_pmc_init,
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
};

-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 = UINT_MAX },
- { .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 = UINT_MAX },
- { .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_CONN, .dpd = 60, .voltage = UINT_MAX },
- { .id = TEGRA_IO_PAD_AUDIO_HV, .dpd = 61, .voltage = UINT_MAX },
-};
-
static const struct tegra_pmc_regs tegra186_pmc_regs = {
.scratch0 = 0x2000,
.dpd_req = 0x74,
@@ -1869,6 +2253,111 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
iounmap(wake);
}

+#define TEGRA186_IO_PAD_CONFIG(_pin, _npins, _name, _dpd_reg, _dpd_bit, \
+ _padv_reg, _padv_bit, _v0, _v1, _iopwr_bit, \
+ _bds) \
+ { \
+ .name = #_name, \
+ .pins = {(_pin)}, \
+ .npins = _npins, \
+ .dpd_req_reg = TEGRA_PMC_IO_##_dpd_reg##_REQ, \
+ .dpd_status_reg = TEGRA_PMC_IO_##_dpd_reg##_STATUS, \
+ .dpd_timer_reg = TEGRA_PMC_SEL_DPD_TIM, \
+ .dpd_sample_reg = TEGRA_PMC_IO_DPD_SAMPLE, \
+ .dpd = _dpd_bit, \
+ .pwr_det_val_reg = TEGRA_PMC_##_padv_reg##_PWR, \
+ .pwr_det_enable_reg = UINT_MAX, \
+ .pad_uv_0 = TEGRA_IO_PAD_VOLTAGE_##_v0##000UV, \
+ .pad_uv_1 = TEGRA_IO_PAD_VOLTAGE_##_v1##000UV, \
+ .voltage = _padv_bit, \
+ .io_power = _iopwr_bit, \
+ .bdsdmem_cfc = _bds, \
+ },
+
+#define TEGRA186_IO_PAD_LPONLY(_pin, _name, _dpd_reg, _dpd_bit, _iopwr_bit, \
+ _bds) \
+ TEGRA186_IO_PAD_CONFIG(_pin, 1, _name, _dpd_reg, _dpd_bit, \
+ E_33V, UINT_MAX, 1200, 1200, _iopwr_bit, _bds)
+
+#define TEGRA186_IO_PAD_LP_N_PV(_pin, _name, _dpd_reg, _dpd_bit, _padv_reg, \
+ _padv_bit, _v0, _v1, _iopwr_bit, _bds) \
+ TEGRA186_IO_PAD_CONFIG(_pin, 1, _name, _dpd_reg, _dpd_bit, \
+ _padv_reg, _padv_bit, _v0, _v1, _iopwr_bit, \
+ _bds)
+
+#define TEGRA186_IO_PAD_PVONLY(_pin, _name, _padv_reg, _padv_bit, _v0, _v1, \
+ _iopwr_bit, _bds) \
+ TEGRA186_IO_PAD_CONFIG(_pin, 1, _name, DPD, UINT_MAX, _padv_reg, \
+ _padv_bit, _v0, _v1, _iopwr_bit, _bds)
+
+#define TEGRA186_IO_PAD_DESC_LP(_pin, _name, _dpd_reg, _dpd_bit, _iopwr_bit, \
+ _bds) \
+ { \
+ .number = _pin, \
+ .name = #_name, \
+ },
+
+#define TEGRA186_IO_PAD_DESC_LP_N_PV(_pin, _name, _dpd_reg, _dpd_bit, \
+ _padv_reg, _padv_bit, _v0, _v1, \
+ _iopwr_bit, _bds) \
+ TEGRA186_IO_PAD_DESC_LP(_pin, _name, _dpd_reg, _dpd_bit, \
+ _iopwr_bit, _bds)
+
+#define TEGRA186_IO_PAD_DESC_PV(_pin, _name, _padv_reg, _padv_bit, _v0, _v1, \
+ _iopwr_bit, _bds) \
+ TEGRA186_IO_PAD_DESC_LP(_pin, _name, UINT_MAX, UINT_MAX, \
+ UINT_MAX, UINT_MAX)
+
+#define TEGRA186_IO_PAD_TABLE(_lponly_, _pvonly_, _lp_n_pv_) \
+ _lponly_(0, csia, DPD, 0, UINT_MAX, false) \
+ _lponly_(1, csib, DPD, 1, UINT_MAX, false) \
+ _lponly_(2, dsi, DPD, 2, UINT_MAX, false) \
+ _lponly_(3, mipi-bias, DPD, 3, 9, false) \
+ _lponly_(4, pex-clk_bias, DPD, 4, UINT_MAX, false) \
+ _lponly_(5, pex-clk3, DPD, 5, UINT_MAX, false) \
+ _lponly_(6, pex-clk2, DPD, 6, UINT_MAX, false) \
+ _lponly_(7, pex-clk1, DPD, 7, UINT_MAX, false) \
+ _lponly_(8, usb0, DPD, 9, UINT_MAX, false) \
+ _lponly_(9, usb1, DPD, 10, UINT_MAX, false) \
+ _lponly_(10, usb2, DPD, 11, UINT_MAX, false) \
+ _lponly_(11, usb-bias, DPD, 12, UINT_MAX, false) \
+ _lponly_(12, uart, DPD, 14, 2, false) \
+ _lponly_(13, audio, DPD, 17, 5, false) \
+ _lponly_(14, hsic, DPD, 19, UINT_MAX, false) \
+ _lp_n_pv_(15, dbg, DPD, 25, E_18V, 4, 1200, 1800, 19, false) \
+ _lponly_(16, hdmi-dp0, DPD, 28, UINT_MAX, false) \
+ _lponly_(17, hdmi-dp1, DPD, 29, UINT_MAX, false) \
+ _lponly_(18, pex-ctrl, DPD2, 0, 11, false) \
+ _lp_n_pv_(19, sdmmc2-hv, DPD2, 2, E_33V, 5, 1800, 3300, 30, true) \
+ _lponly_(20, sdmmc4, DPD2, 4, 14, false) \
+ _lponly_(21, cam, DPD2, 6, 10, false) \
+ _lponly_(22, dsib, DPD2, 8, UINT_MAX, false) \
+ _lponly_(23, dsic, DPD2, 9, UINT_MAX, false) \
+ _lponly_(24, dsid, DPD2, 10, UINT_MAX, false) \
+ _lponly_(25, csic, DPD2, 11, UINT_MAX, false) \
+ _lponly_(26, csid, DPD2, 12, UINT_MAX, false) \
+ _lponly_(27, csie, DPD2, 13, UINT_MAX, false) \
+ _lponly_(28, csif, DPD2, 14, UINT_MAX, false) \
+ _lp_n_pv_(29, spi, DPD2, 15, E_18V, 5, 1200, 1800, 22, false) \
+ _lp_n_pv_(30, ufs, DPD2, 17, E_18V, 0, 1200, 1800, 6, false) \
+ _lp_n_pv_(31, dmic-hv, DPD2, 20, E_33V, 2, 1800, 3300, 28, true) \
+ _lponly_(32, edp, DPD2, 21, 4, false) \
+ _lp_n_pv_(33, sdmmc1-hv, DPD2, 23, E_33V, 4, 1800, 3300, 15, true) \
+ _lp_n_pv_(34, sdmmc3-hv, DPD2, 24, E_33V, 6, 1800, 3300, 31, true) \
+ _lponly_(35, conn, DPD2, 28, 3, false) \
+ _lp_n_pv_(36, audio-hv, DPD2, 29, E_33V, 1, 1800, 3300, 18, true) \
+ _pvonly_(37, ao-hv, E_33V, 0, 1800, 3300, 27, true)
+
+static const struct tegra_io_pad_soc tegra186_io_pads[] = {
+ TEGRA186_IO_PAD_TABLE(TEGRA186_IO_PAD_LPONLY, TEGRA186_IO_PAD_PVONLY,
+ TEGRA186_IO_PAD_LP_N_PV)
+};
+
+static const struct pinctrl_pin_desc tegra186_io_pads_pinctrl_desc[] = {
+ TEGRA186_IO_PAD_TABLE(TEGRA186_IO_PAD_DESC_LP, TEGRA186_IO_PAD_DESC_PV,
+ TEGRA186_IO_PAD_DESC_LP_N_PV)
+};
+
static const struct tegra_pmc_soc tegra186_pmc_soc = {
.num_powergates = 0,
.powergates = NULL,
@@ -1878,6 +2367,8 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
.has_gpu_clamps = false,
.num_io_pads = ARRAY_SIZE(tegra186_io_pads),
.io_pads = tegra186_io_pads,
+ .num_descs = ARRAY_SIZE(tegra186_io_pads_pinctrl_desc),
+ .descs = tegra186_io_pads_pinctrl_desc,
.regs = &tegra186_pmc_regs,
.init = NULL,
.setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h
index c32bf91..c3acc2e 100644
--- a/include/soc/tegra/pmc.h
+++ b/include/soc/tegra/pmc.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2010 Google, Inc
- * Copyright (c) 2014 NVIDIA Corporation
+ * Copyright (c) 2014-2018 NVIDIA Corporation
*
* Author:
* Colin Cross <[email protected]>
@@ -160,11 +160,10 @@ 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);
+int tegra_pmc_io_pad_low_power_enable(const char *pad_name);
+int tegra_pmc_io_pad_low_power_disable(const char *pad_name);
+int tegra_pmc_io_pad_set_voltage(const char *pad_name, unsigned int pad_uv);
+int tegra_pmc_io_pad_get_voltage(const char *pad_name);

/* deprecated, use tegra_io_pad_power_{enable,disable}() instead */
int tegra_io_rail_power_on(unsigned int id);
@@ -202,23 +201,23 @@ 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)
+static inline int tegra_pmc_io_pad_low_power_enable(const char *pad_name)
{
return -ENOSYS;
}

-static inline int tegra_io_pad_power_disable(enum tegra_io_pad id)
+static inline int tegra_pmc_io_pad_low_power_disable(const char *pad_name)
{
return -ENOSYS;
}

-static inline int tegra_io_pad_set_voltage(enum tegra_io_pad id,
- enum tegra_io_pad_voltage voltage)
+static inline int tegra_pmc_io_pad_set_voltage(const char *pad_name,
+ unsigned int pad_uv)
{
return -ENOSYS;
}

-static inline int tegra_io_pad_get_voltage(enum tegra_io_pad id)
+static inline int tegra_pmc_io_pad_get_voltage(const char *pad_name)
{
return -ENOSYS;
}
--
2.1.4



2018-08-02 12:05:42

by Venkat Reddy Talla

[permalink] [raw]
Subject: [PATCH 2/3] dt-bindings: tegra: update PMC DT binding with io pads control

NVIDIA Tegra124 and later SoCs support the multi-voltage level
and low power state of some of its IO pads. The IO pads can work
in the voltage of the 1.8V and 3.3V of IO voltage from IO power
rail sources. When IO interfaces are not used then IO pads
can be configure in low power state to reduce the power
consumption from that IO pads.

On Tegra124, the voltage level of IO power rail source is auto
detected by hardware(SoC) and hence it is only require to
configure in low power mode if IO pads are not used.

On T210 onwards, the auto-detection of voltage level from
IO power rail is removed from SoC and hence SW need to configure
the PMC register explicitly to set proper voltage in IO pads
based on IO rail power source voltage.

Updating PMC DT binding document for detailing the DT properties
for configuring IO pads voltage levels and its power state.

Signed-off-by: Venkat Reddy Talla <[email protected]>
---
.../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 125 ++++++++++++++++++++-
1 file changed, 124 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
index a74b37b..1166373 100644
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
@@ -6,6 +6,35 @@ The PMC block interacts with an external Power Management Unit. The PMC
mostly controls the entry and exit of the system from different sleep
modes. It provides power-gating controllers for SoC and CPU power-islands.

+NVIDIA Tegra124 and later SoCs support the multi-voltage level and low power
+state of some of its IO pads. When IO interface are not used then IO pads can
+be configure in low power state to reduce the power from that IO pads. The IO
+pads can operate at the nominal IO voltage of eother 1.8V or 3.3V.
+
+On Tegra124, the voltage of IO power rail source is auto detected by SoC and
+hence it is only require to configure in low power mode if IO pads are not
+used.
+
+On T210 onwards, the HW based auto-detection for IO voltage is removed and
+hence SW need to configure the PMC register explicitly, to set proper voltage
+in IO pads, based on IO rail power source voltage.
+
+The voltage configurations and low power state of IO pads should be done in
+boot if it is not going to change otherwise dynamically based on IO rail
+voltage on that IO pads and usage of IO pads.
+
+The DT property of the IO pads must be under the node of pmc i.e.
+pmc@7000e400 for Tegra124 onwards.
+
+Please refer to <pinctrl-bindings.txt> in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+Tegra's pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for an
+IO pads, or a list of IO pads. This configuration can include the voltage and
+power enable/disable control.
+
Required properties:
- name : Should be pmc
- compatible : Should contain one of the following:
@@ -13,7 +42,7 @@ Required properties:
For Tegra30 must contain "nvidia,tegra30-pmc".
For Tegra114 must contain "nvidia,tegra114-pmc"
For Tegra124 must contain "nvidia,tegra124-pmc"
- For Tegra132 must contain "nvidia,tegra124-pmc"
+ For Tegra132 must contain "nvidia,tegra132-pmc"
For Tegra210 must contain "nvidia,tegra210-pmc"
- reg : Offset and length of the register set for the device
- clocks : Must contain an entry for each entry in clock-names.
@@ -77,6 +106,56 @@ Optional nodes:
should match the powergates on the Tegra SoC. See "Powergate
Nodes" below.

+Required subnode-properties:
+==========================
+- pins : An array of strings. Each string contains the name of an IO pad. Valid
+ values for these names are listed below.
+
+Optional subnode-properties:
+==========================
+Following properties are supported from generic pin configuration explained
+in <dt-bindings/pinctrl/pinctrl-binding.txt>.
+low-power-enable: enable low power mode
+low-power-disable: disable low power mode
+nvidia,restrict-voltage-switch: restrict io pad voltage switch for all pads
+nvidia,enable-voltage-switching: enable voltage switch for io pad
+
+Valid values for pin for T124 SOC are:
+ audio, bb, cam, comp, csia, csib, csie, dsi, dsib, dsic, dsid, hdmi,
+ hsic, hv, lvds, mipi-bias, nand, pex-bias, pex-clk1, pex-clk2,
+ pex-ctrl, sdmmc1, sdmmc3, sdmmc4, sys-ddc, uart, usb0, usb1, usb2,
+ usb-bias
+
+Valid values for pin for T210 SOC are:
+ 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-ctrl, sdmmc1, sdmmc3, spi, spi-hv, uart, usb-bias, usb0,
+ usb1, usb2, usb3.
+
+To find out the IO rail voltage for setting the voltage of IO pad by SW,
+the regulator supply handle must be provided from the DT and it is explained
+in the regulator DT binding document
+ <devicetree/bindings/regulator/regulator.txt>.
+For example, for GPIO rail the supply name is vddio-gpio and regulator
+handle is supplied from DT as
+ vddio-gpio-supply = <&regulator_xyz>;
+
+For T210, following IO pads support the 1.8V/3.3V and the corresponding
+IO voltage pin names are as follows:
+ audio -> vddio_audio
+ audio-hv -> vddio_audio_hv
+ cam ->vddio_cam
+ dbg -> vddio_dbg
+ dmic -> vddio_dmic
+ gpio -> vddio_gpio
+ pex-ctrl -> vddio_pex_ctrl
+ sdmmc1 -> vddio_sdmmc1
+ sdmmc3 -> vddio_sdmmc3
+ spi -> vddio_spi
+ spi-hv -> vddio_spi_hv
+ uart -> vddio_uart
+
Example:

/ SoC dts including file
@@ -123,6 +202,50 @@ pmc@7000f400 {
...
};

+== PMC Nodes for IO pad power state/voltage configuration ==
+ i2c@7000d000 {
+ pmic@3c {
+ regulators {
+ vddio_sdmmc1: ldo2 {
+ /* Regulator entries for LDO2 */
+ };
+
+ vdd_cam: ldo3 {
+ /* Regulator entries for LDO3 */
+ };
+ };
+ };
+ };
+
+ pmc@7000e400 {
+ vddio-cam-supply = <&vdd_cam>;
+ vddio-sdmmc1-supply = <&vddio_sdmmc1>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&tegra_io_pad_volt_default>;
+ nvidia,restrict-voltage-switch;
+ tegra_io_pad_volt_default: common {
+ audio-hv {
+ pins = "audio-hv";
+ low-power-disable;
+ };
+
+ gpio {
+ pins = "gpio";
+ low-power-disable;
+ };
+
+ audio {
+ pins = "audio", "dmic", "sdmmc3";
+ low-power-enable;
+ };
+
+ sdmmc-io-pads {
+ pins = "sdmmc1-hv", "sdmmc3-hv";
+ nvidia,enable-voltage-switching;
+ };
+ };
+ };

== Powergate Nodes ==

--
2.1.4


2018-08-02 12:06:05

by Venkat Reddy Talla

[permalink] [raw]
Subject: [PATCH 3/3] drm/tegra: sor: change io pad power state using new pmc api

Added support in PMC driver to configure the power state and voltage level
of the IO pads from client driver via pincontrol framework, because of this
tegra_io_pad_power_disable() and tegra_io_pad_power_enable() deprecated,
to change power state of SOR io pads using new pmc apis.

Signed-off-by: Venkat Reddy Talla <[email protected]>
---
drivers/gpu/drm/tegra/sor.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index d7fe9f1..6ede923 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 NVIDIA Corporation
+ * Copyright (C) 2013-2018, NVIDIA Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -342,7 +342,6 @@ struct tegra_sor {
struct drm_info_list *debugfs_files;

const struct tegra_sor_ops *ops;
- enum tegra_io_pad pad;

/* for HDMI 2.0 */
struct tegra_sor_hdmi_settings *settings;
@@ -1547,7 +1546,7 @@ static void tegra_sor_edp_disable(struct drm_encoder *encoder)
dev_err(sor->dev, "failed to disable DP: %d\n", err);
}

- err = tegra_io_pad_power_disable(sor->pad);
+ err = tegra_io_rail_power_off(TEGRA_IO_RAIL_LVDS);
if (err < 0)
dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);

@@ -1707,7 +1706,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);

/* step 2 */
- err = tegra_io_pad_power_enable(sor->pad);
+ err = tegra_io_rail_power_on(TEGRA_IO_RAIL_LVDS);
if (err < 0)
dev_err(sor->dev, "failed to power on I/O pad: %d\n", err);

@@ -2189,7 +2188,7 @@ static void tegra_sor_hdmi_disable(struct drm_encoder *encoder)
if (err < 0)
dev_err(sor->dev, "failed to power down SOR: %d\n", err);

- err = tegra_io_pad_power_disable(sor->pad);
+ err = tegra_io_rail_power_off(TEGRA_IO_RAIL_HDMI);
if (err < 0)
dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);

@@ -2225,7 +2224,7 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)

div = clk_get_rate(sor->clk) / 1000000 * 4;

- err = tegra_io_pad_power_enable(sor->pad);
+ err = tegra_io_rail_power_on(TEGRA_IO_RAIL_HDMI);
if (err < 0)
dev_err(sor->dev, "failed to power on I/O pad: %d\n", err);

@@ -2921,7 +2920,6 @@ static int tegra_sor_parse_dt(struct tegra_sor *sor)
* override the default that we already set for Tegra210 and
* earlier
*/
- sor->pad = TEGRA_IO_PAD_HDMI_DP0 + sor->index;
}

return 0;
@@ -2962,7 +2960,6 @@ static int tegra_sor_probe(struct platform_device *pdev)
if (!sor->aux) {
if (sor->soc->supports_hdmi) {
sor->ops = &tegra_sor_hdmi_ops;
- sor->pad = TEGRA_IO_PAD_HDMI;
} else if (sor->soc->supports_lvds) {
dev_err(&pdev->dev, "LVDS not supported yet\n");
return -ENODEV;
@@ -2973,7 +2970,6 @@ static int tegra_sor_probe(struct platform_device *pdev)
} else {
if (sor->soc->supports_edp) {
sor->ops = &tegra_sor_edp_ops;
- sor->pad = TEGRA_IO_PAD_LVDS;
} else if (sor->soc->supports_dp) {
dev_err(&pdev->dev, "DisplayPort not supported yet\n");
return -ENODEV;
--
2.1.4


2018-08-02 13:44:55

by Jon Hunter

[permalink] [raw]
Subject: Re: [PATCH 1/3] soc/tegra: pmc: set IO pad power state and voltage via pinctrl fw


On 02/08/18 12:59, Venkat Reddy Talla wrote:
> The IO pins of Tegra SoCs are grouped for common control
> of IO interface like setting voltage signal levels and
> power state of the interface. These groups are referred
> to as IO pads.The power state and voltage control of IO pins
> can be done at IO pads level.
>
> Tegra SoCs support powering down IO pads when they are
> not used even in the active state of system.
> This saves power from that IO interface. Also it supports
> multiple voltage level in IO pins for interfacing on
> some of pads. The IO pad voltage is automatically detected
> till Tegra124, hence SW need not to configure this.
> But from Tegra210, the automatic detection logic has been
> removed, hence SW need to explicitly set the IO pad
> voltage into IO pad configuration registers.
>
> Add support to configure the power state and voltage level
> of the IO pads from client driver via pincontrol framework.
>
> Signed-off-by: Venkat Reddy Talla <[email protected]>

This appears to be a duplicate effort of the following which we have
been reviewing ...

https://marc.info/?l=linux-tegra&m=153295930808915&w=2

Cheers
Jon

--
nvpublic

2018-08-02 22:23:28

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 1/3] soc/tegra: pmc: set IO pad power state and voltage via pinctrl fw

Hi Venkat,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on tegra/for-next]
[also build test ERROR on v4.18-rc7 next-20180802]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Venkat-Reddy-Talla/soc-tegra-pmc-set-IO-pad-power-state-and-voltage-via-pinctrl-fw/20180803-043413
base: https://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git for-next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.2.0 make.cross ARCH=arm64

All errors (new ones prefixed by >>):

>> drivers/soc/tegra/pmc.c:51:10: fatal error: dt-bindings/pinctrl/pinctrl-tegra-io-pad.h: No such file or directory
#include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

vim +51 drivers/soc/tegra/pmc.c

50
> 51 #include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h>
52

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (1.42 kB)
.config.gz (37.96 kB)
Download all attachments

2018-08-02 22:47:18

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 1/3] soc/tegra: pmc: set IO pad power state and voltage via pinctrl fw

Hi Venkat,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on tegra/for-next]
[also build test ERROR on v4.18-rc7 next-20180802]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Venkat-Reddy-Talla/soc-tegra-pmc-set-IO-pad-power-state-and-voltage-via-pinctrl-fw/20180803-043413
base: https://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git for-next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.2.0 make.cross ARCH=arm64

Note: the linux-review/Venkat-Reddy-Talla/soc-tegra-pmc-set-IO-pad-power-state-and-voltage-via-pinctrl-fw/20180803-043413 HEAD ab02915682b2d61932e12e719422af7bc05b1eef builds fine.
It only hurts bisectibility.

All errors (new ones prefixed by >>):

drivers/gpu//drm/tegra/sor.c: In function 'tegra_sor_edp_disable':
>> drivers/gpu//drm/tegra/sor.c:1550:8: error: implicit declaration of function 'tegra_io_pad_power_disable'; did you mean 'tegra_pmc_io_pad_low_power_disable'? [-Werror=implicit-function-declaration]
err = tegra_io_pad_power_disable(sor->pad);
^~~~~~~~~~~~~~~~~~~~~~~~~~
tegra_pmc_io_pad_low_power_disable
drivers/gpu//drm/tegra/sor.c: In function 'tegra_sor_edp_enable':
>> drivers/gpu//drm/tegra/sor.c:1710:8: error: implicit declaration of function 'tegra_io_pad_power_enable'; did you mean 'tegra_io_rail_power_on'? [-Werror=implicit-function-declaration]
err = tegra_io_pad_power_enable(sor->pad);
^~~~~~~~~~~~~~~~~~~~~~~~~
tegra_io_rail_power_on
cc1: some warnings being treated as errors

vim +1550 drivers/gpu//drm/tegra/sor.c

6fad8f66d Thierry Reding 2014-11-28 1509
850bab448 Thierry Reding 2015-07-29 1510 static void tegra_sor_edp_disable(struct drm_encoder *encoder)
6fad8f66d Thierry Reding 2014-11-28 1511 {
850bab448 Thierry Reding 2015-07-29 1512 struct tegra_output *output = encoder_to_output(encoder);
850bab448 Thierry Reding 2015-07-29 1513 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
850bab448 Thierry Reding 2015-07-29 1514 struct tegra_sor *sor = to_sor(output);
850bab448 Thierry Reding 2015-07-29 1515 u32 value;
850bab448 Thierry Reding 2015-07-29 1516 int err;
850bab448 Thierry Reding 2015-07-29 1517
850bab448 Thierry Reding 2015-07-29 1518 if (output->panel)
850bab448 Thierry Reding 2015-07-29 1519 drm_panel_disable(output->panel);
850bab448 Thierry Reding 2015-07-29 1520
850bab448 Thierry Reding 2015-07-29 1521 err = tegra_sor_detach(sor);
850bab448 Thierry Reding 2015-07-29 1522 if (err < 0)
850bab448 Thierry Reding 2015-07-29 1523 dev_err(sor->dev, "failed to detach SOR: %d\n", err);
850bab448 Thierry Reding 2015-07-29 1524
850bab448 Thierry Reding 2015-07-29 1525 tegra_sor_writel(sor, 0, SOR_STATE1);
850bab448 Thierry Reding 2015-07-29 1526 tegra_sor_update(sor);
850bab448 Thierry Reding 2015-07-29 1527
850bab448 Thierry Reding 2015-07-29 1528 /*
850bab448 Thierry Reding 2015-07-29 1529 * The following accesses registers of the display controller, so make
850bab448 Thierry Reding 2015-07-29 1530 * sure it's only executed when the output is attached to one.
850bab448 Thierry Reding 2015-07-29 1531 */
850bab448 Thierry Reding 2015-07-29 1532 if (dc) {
850bab448 Thierry Reding 2015-07-29 1533 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
c57997bce Thierry Reding 2017-10-12 1534 value &= ~SOR_ENABLE(0);
850bab448 Thierry Reding 2015-07-29 1535 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
850bab448 Thierry Reding 2015-07-29 1536
850bab448 Thierry Reding 2015-07-29 1537 tegra_dc_commit(dc);
6fad8f66d Thierry Reding 2014-11-28 1538 }
6fad8f66d Thierry Reding 2014-11-28 1539
850bab448 Thierry Reding 2015-07-29 1540 err = tegra_sor_power_down(sor);
850bab448 Thierry Reding 2015-07-29 1541 if (err < 0)
850bab448 Thierry Reding 2015-07-29 1542 dev_err(sor->dev, "failed to power down SOR: %d\n", err);
850bab448 Thierry Reding 2015-07-29 1543
9542c2376 Thierry Reding 2015-07-08 1544 if (sor->aux) {
9542c2376 Thierry Reding 2015-07-08 1545 err = drm_dp_aux_disable(sor->aux);
850bab448 Thierry Reding 2015-07-29 1546 if (err < 0)
850bab448 Thierry Reding 2015-07-29 1547 dev_err(sor->dev, "failed to disable DP: %d\n", err);
6fad8f66d Thierry Reding 2014-11-28 1548 }
6fad8f66d Thierry Reding 2014-11-28 1549
c57997bce Thierry Reding 2017-10-12 @1550 err = tegra_io_pad_power_disable(sor->pad);
850bab448 Thierry Reding 2015-07-29 1551 if (err < 0)
c57997bce Thierry Reding 2017-10-12 1552 dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);
850bab448 Thierry Reding 2015-07-29 1553
850bab448 Thierry Reding 2015-07-29 1554 if (output->panel)
850bab448 Thierry Reding 2015-07-29 1555 drm_panel_unprepare(output->panel);
850bab448 Thierry Reding 2015-07-29 1556
aaff8bd2e Thierry Reding 2015-08-07 1557 pm_runtime_put(sor->dev);
6fad8f66d Thierry Reding 2014-11-28 1558 }
6fad8f66d Thierry Reding 2014-11-28 1559
459cc2c68 Thierry Reding 2015-07-30 1560 #if 0
459cc2c68 Thierry Reding 2015-07-30 1561 static int calc_h_ref_to_sync(const struct drm_display_mode *mode,
459cc2c68 Thierry Reding 2015-07-30 1562 unsigned int *value)
459cc2c68 Thierry Reding 2015-07-30 1563 {
459cc2c68 Thierry Reding 2015-07-30 1564 unsigned int hfp, hsw, hbp, a = 0, b;
459cc2c68 Thierry Reding 2015-07-30 1565
459cc2c68 Thierry Reding 2015-07-30 1566 hfp = mode->hsync_start - mode->hdisplay;
459cc2c68 Thierry Reding 2015-07-30 1567 hsw = mode->hsync_end - mode->hsync_start;
459cc2c68 Thierry Reding 2015-07-30 1568 hbp = mode->htotal - mode->hsync_end;
459cc2c68 Thierry Reding 2015-07-30 1569
459cc2c68 Thierry Reding 2015-07-30 1570 pr_info("hfp: %u, hsw: %u, hbp: %u\n", hfp, hsw, hbp);
459cc2c68 Thierry Reding 2015-07-30 1571
459cc2c68 Thierry Reding 2015-07-30 1572 b = hfp - 1;
459cc2c68 Thierry Reding 2015-07-30 1573
459cc2c68 Thierry Reding 2015-07-30 1574 pr_info("a: %u, b: %u\n", a, b);
459cc2c68 Thierry Reding 2015-07-30 1575 pr_info("a + hsw + hbp = %u\n", a + hsw + hbp);
459cc2c68 Thierry Reding 2015-07-30 1576
459cc2c68 Thierry Reding 2015-07-30 1577 if (a + hsw + hbp <= 11) {
459cc2c68 Thierry Reding 2015-07-30 1578 a = 1 + 11 - hsw - hbp;
459cc2c68 Thierry Reding 2015-07-30 1579 pr_info("a: %u\n", a);
459cc2c68 Thierry Reding 2015-07-30 1580 }
459cc2c68 Thierry Reding 2015-07-30 1581
459cc2c68 Thierry Reding 2015-07-30 1582 if (a > b)
459cc2c68 Thierry Reding 2015-07-30 1583 return -EINVAL;
459cc2c68 Thierry Reding 2015-07-30 1584
459cc2c68 Thierry Reding 2015-07-30 1585 if (hsw < 1)
459cc2c68 Thierry Reding 2015-07-30 1586 return -EINVAL;
459cc2c68 Thierry Reding 2015-07-30 1587
459cc2c68 Thierry Reding 2015-07-30 1588 if (mode->hdisplay < 16)
459cc2c68 Thierry Reding 2015-07-30 1589 return -EINVAL;
459cc2c68 Thierry Reding 2015-07-30 1590
459cc2c68 Thierry Reding 2015-07-30 1591 if (value) {
459cc2c68 Thierry Reding 2015-07-30 1592 if (b > a && a % 2)
459cc2c68 Thierry Reding 2015-07-30 1593 *value = a + 1;
459cc2c68 Thierry Reding 2015-07-30 1594 else
459cc2c68 Thierry Reding 2015-07-30 1595 *value = a;
459cc2c68 Thierry Reding 2015-07-30 1596 }
459cc2c68 Thierry Reding 2015-07-30 1597
459cc2c68 Thierry Reding 2015-07-30 1598 return 0;
459cc2c68 Thierry Reding 2015-07-30 1599 }
459cc2c68 Thierry Reding 2015-07-30 1600 #endif
459cc2c68 Thierry Reding 2015-07-30 1601
850bab448 Thierry Reding 2015-07-29 1602 static void tegra_sor_edp_enable(struct drm_encoder *encoder)
6fad8f66d Thierry Reding 2014-11-28 1603 {
850bab448 Thierry Reding 2015-07-29 1604 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
6fad8f66d Thierry Reding 2014-11-28 1605 struct tegra_output *output = encoder_to_output(encoder);
6fad8f66d Thierry Reding 2014-11-28 1606 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
6b6b60421 Thierry Reding 2013-11-15 1607 struct tegra_sor *sor = to_sor(output);
34fa183ba Thierry Reding 2014-06-05 1608 struct tegra_sor_config config;
c31efa7a3 Thierry Reding 2015-09-08 1609 struct tegra_sor_state *state;
34fa183ba Thierry Reding 2014-06-05 1610 struct drm_dp_link link;
01b9bea0c Thierry Reding 2015-11-11 1611 u8 rate, lanes;
2bd1dd399 Thierry Reding 2015-08-03 1612 unsigned int i;
86f5c52dc Thierry Reding 2014-03-26 1613 int err = 0;
28fe20760 Thierry Reding 2015-01-26 1614 u32 value;
86f5c52dc Thierry Reding 2014-03-26 1615
c31efa7a3 Thierry Reding 2015-09-08 1616 state = to_sor_state(output->connector.state);
6b6b60421 Thierry Reding 2013-11-15 1617
aaff8bd2e Thierry Reding 2015-08-07 1618 pm_runtime_get_sync(sor->dev);
6b6b60421 Thierry Reding 2013-11-15 1619
6fad8f66d Thierry Reding 2014-11-28 1620 if (output->panel)
6fad8f66d Thierry Reding 2014-11-28 1621 drm_panel_prepare(output->panel);
6fad8f66d Thierry Reding 2014-11-28 1622
9542c2376 Thierry Reding 2015-07-08 1623 err = drm_dp_aux_enable(sor->aux);
6b6b60421 Thierry Reding 2013-11-15 1624 if (err < 0)
6b6b60421 Thierry Reding 2013-11-15 1625 dev_err(sor->dev, "failed to enable DP: %d\n", err);
34fa183ba Thierry Reding 2014-06-05 1626
9542c2376 Thierry Reding 2015-07-08 1627 err = drm_dp_link_probe(sor->aux, &link);
34fa183ba Thierry Reding 2014-06-05 1628 if (err < 0) {
01b9bea0c Thierry Reding 2015-11-11 1629 dev_err(sor->dev, "failed to probe eDP link: %d\n", err);
850bab448 Thierry Reding 2015-07-29 1630 return;
34fa183ba Thierry Reding 2014-06-05 1631 }
6b6b60421 Thierry Reding 2013-11-15 1632
25bb2cec8 Thierry Reding 2015-08-03 1633 /* switch to safe parent clock */
25bb2cec8 Thierry Reding 2015-08-03 1634 err = tegra_sor_set_parent_clock(sor, sor->clk_safe);
6b6b60421 Thierry Reding 2013-11-15 1635 if (err < 0)
6b6b60421 Thierry Reding 2013-11-15 1636 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
6b6b60421 Thierry Reding 2013-11-15 1637
34fa183ba Thierry Reding 2014-06-05 1638 memset(&config, 0, sizeof(config));
c31efa7a3 Thierry Reding 2015-09-08 1639 config.bits_per_pixel = state->bpc * 3;
34fa183ba Thierry Reding 2014-06-05 1640
a198359e3 Thierry Reding 2015-07-21 1641 err = tegra_sor_compute_config(sor, mode, &config, &link);
34fa183ba Thierry Reding 2014-06-05 1642 if (err < 0)
a198359e3 Thierry Reding 2015-07-21 1643 dev_err(sor->dev, "failed to compute configuration: %d\n", err);
34fa183ba Thierry Reding 2014-06-05 1644
6b6b60421 Thierry Reding 2013-11-15 1645 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
6b6b60421 Thierry Reding 2013-11-15 1646 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
6b6b60421 Thierry Reding 2013-11-15 1647 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
6b6b60421 Thierry Reding 2013-11-15 1648 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
6b6b60421 Thierry Reding 2013-11-15 1649
880cee0b7 Thierry Reding 2017-10-12 1650 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
a9a9e4fd7 Thierry Reding 2015-04-27 1651 value &= ~SOR_PLL2_BANDGAP_POWERDOWN;
880cee0b7 Thierry Reding 2017-10-12 1652 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
6b6b60421 Thierry Reding 2013-11-15 1653 usleep_range(20, 100);
6b6b60421 Thierry Reding 2013-11-15 1654
880cee0b7 Thierry Reding 2017-10-12 1655 value = tegra_sor_readl(sor, sor->soc->regs->pll3);
a9a9e4fd7 Thierry Reding 2015-04-27 1656 value |= SOR_PLL3_PLL_VDD_MODE_3V3;
880cee0b7 Thierry Reding 2017-10-12 1657 tegra_sor_writel(sor, value, sor->soc->regs->pll3);
6b6b60421 Thierry Reding 2013-11-15 1658
a9a9e4fd7 Thierry Reding 2015-04-27 1659 value = SOR_PLL0_ICHPMP(0xf) | SOR_PLL0_VCOCAP_RST |
a9a9e4fd7 Thierry Reding 2015-04-27 1660 SOR_PLL0_PLLREG_LEVEL_V45 | SOR_PLL0_RESISTOR_EXT;
880cee0b7 Thierry Reding 2017-10-12 1661 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
6b6b60421 Thierry Reding 2013-11-15 1662
880cee0b7 Thierry Reding 2017-10-12 1663 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
a9a9e4fd7 Thierry Reding 2015-04-27 1664 value |= SOR_PLL2_SEQ_PLLCAPPD;
a9a9e4fd7 Thierry Reding 2015-04-27 1665 value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
a9a9e4fd7 Thierry Reding 2015-04-27 1666 value |= SOR_PLL2_LVDS_ENABLE;
880cee0b7 Thierry Reding 2017-10-12 1667 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
6b6b60421 Thierry Reding 2013-11-15 1668
a9a9e4fd7 Thierry Reding 2015-04-27 1669 value = SOR_PLL1_TERM_COMPOUT | SOR_PLL1_TMDS_TERM;
880cee0b7 Thierry Reding 2017-10-12 1670 tegra_sor_writel(sor, value, sor->soc->regs->pll1);
6b6b60421 Thierry Reding 2013-11-15 1671
6b6b60421 Thierry Reding 2013-11-15 1672 while (true) {
880cee0b7 Thierry Reding 2017-10-12 1673 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
a9a9e4fd7 Thierry Reding 2015-04-27 1674 if ((value & SOR_PLL2_SEQ_PLLCAPPD_ENFORCE) == 0)
6b6b60421 Thierry Reding 2013-11-15 1675 break;
6b6b60421 Thierry Reding 2013-11-15 1676
6b6b60421 Thierry Reding 2013-11-15 1677 usleep_range(250, 1000);
6b6b60421 Thierry Reding 2013-11-15 1678 }
6b6b60421 Thierry Reding 2013-11-15 1679
880cee0b7 Thierry Reding 2017-10-12 1680 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
a9a9e4fd7 Thierry Reding 2015-04-27 1681 value &= ~SOR_PLL2_POWERDOWN_OVERRIDE;
a9a9e4fd7 Thierry Reding 2015-04-27 1682 value &= ~SOR_PLL2_PORT_POWERDOWN;
880cee0b7 Thierry Reding 2017-10-12 1683 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
6b6b60421 Thierry Reding 2013-11-15 1684
6b6b60421 Thierry Reding 2013-11-15 1685 /*
6b6b60421 Thierry Reding 2013-11-15 1686 * power up
6b6b60421 Thierry Reding 2013-11-15 1687 */
6b6b60421 Thierry Reding 2013-11-15 1688
6b6b60421 Thierry Reding 2013-11-15 1689 /* set safe link bandwidth (1.62 Gbps) */
6b6b60421 Thierry Reding 2013-11-15 1690 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
6b6b60421 Thierry Reding 2013-11-15 1691 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
6b6b60421 Thierry Reding 2013-11-15 1692 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62;
6b6b60421 Thierry Reding 2013-11-15 1693 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
6b6b60421 Thierry Reding 2013-11-15 1694
6b6b60421 Thierry Reding 2013-11-15 1695 /* step 1 */
880cee0b7 Thierry Reding 2017-10-12 1696 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
a9a9e4fd7 Thierry Reding 2015-04-27 1697 value |= SOR_PLL2_SEQ_PLLCAPPD_ENFORCE | SOR_PLL2_PORT_POWERDOWN |
a9a9e4fd7 Thierry Reding 2015-04-27 1698 SOR_PLL2_BANDGAP_POWERDOWN;
880cee0b7 Thierry Reding 2017-10-12 1699 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
6b6b60421 Thierry Reding 2013-11-15 1700
880cee0b7 Thierry Reding 2017-10-12 1701 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
a9a9e4fd7 Thierry Reding 2015-04-27 1702 value |= SOR_PLL0_VCOPD | SOR_PLL0_PWR;
880cee0b7 Thierry Reding 2017-10-12 1703 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
6b6b60421 Thierry Reding 2013-11-15 1704
880cee0b7 Thierry Reding 2017-10-12 1705 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
6b6b60421 Thierry Reding 2013-11-15 1706 value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
880cee0b7 Thierry Reding 2017-10-12 1707 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
6b6b60421 Thierry Reding 2013-11-15 1708
6b6b60421 Thierry Reding 2013-11-15 1709 /* step 2 */
c57997bce Thierry Reding 2017-10-12 @1710 err = tegra_io_pad_power_enable(sor->pad);
850bab448 Thierry Reding 2015-07-29 1711 if (err < 0)
c57997bce Thierry Reding 2017-10-12 1712 dev_err(sor->dev, "failed to power on I/O pad: %d\n", err);
6b6b60421 Thierry Reding 2013-11-15 1713
6b6b60421 Thierry Reding 2013-11-15 1714 usleep_range(5, 100);
6b6b60421 Thierry Reding 2013-11-15 1715
6b6b60421 Thierry Reding 2013-11-15 1716 /* step 3 */
880cee0b7 Thierry Reding 2017-10-12 1717 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
a9a9e4fd7 Thierry Reding 2015-04-27 1718 value &= ~SOR_PLL2_BANDGAP_POWERDOWN;
880cee0b7 Thierry Reding 2017-10-12 1719 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
6b6b60421 Thierry Reding 2013-11-15 1720
6b6b60421 Thierry Reding 2013-11-15 1721 usleep_range(20, 100);
6b6b60421 Thierry Reding 2013-11-15 1722
6b6b60421 Thierry Reding 2013-11-15 1723 /* step 4 */
880cee0b7 Thierry Reding 2017-10-12 1724 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
a9a9e4fd7 Thierry Reding 2015-04-27 1725 value &= ~SOR_PLL0_VCOPD;
a9a9e4fd7 Thierry Reding 2015-04-27 1726 value &= ~SOR_PLL0_PWR;
880cee0b7 Thierry Reding 2017-10-12 1727 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
6b6b60421 Thierry Reding 2013-11-15 1728
880cee0b7 Thierry Reding 2017-10-12 1729 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
a9a9e4fd7 Thierry Reding 2015-04-27 1730 value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
880cee0b7 Thierry Reding 2017-10-12 1731 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
6b6b60421 Thierry Reding 2013-11-15 1732
6b6b60421 Thierry Reding 2013-11-15 1733 usleep_range(200, 1000);
6b6b60421 Thierry Reding 2013-11-15 1734
6b6b60421 Thierry Reding 2013-11-15 1735 /* step 5 */
880cee0b7 Thierry Reding 2017-10-12 1736 value = tegra_sor_readl(sor, sor->soc->regs->pll2);
a9a9e4fd7 Thierry Reding 2015-04-27 1737 value &= ~SOR_PLL2_PORT_POWERDOWN;
880cee0b7 Thierry Reding 2017-10-12 1738 tegra_sor_writel(sor, value, sor->soc->regs->pll2);
6b6b60421 Thierry Reding 2013-11-15 1739
30b494355 Thierry Reding 2015-08-03 1740 /* XXX not in TRM */
30b494355 Thierry Reding 2015-08-03 1741 for (value = 0, i = 0; i < 5; i++)
30b494355 Thierry Reding 2015-08-03 1742 value |= SOR_XBAR_CTRL_LINK0_XSEL(i, sor->soc->xbar_cfg[i]) |
30b494355 Thierry Reding 2015-08-03 1743 SOR_XBAR_CTRL_LINK1_XSEL(i, i);
30b494355 Thierry Reding 2015-08-03 1744
30b494355 Thierry Reding 2015-08-03 1745 tegra_sor_writel(sor, 0x00000000, SOR_XBAR_POL);
30b494355 Thierry Reding 2015-08-03 1746 tegra_sor_writel(sor, value, SOR_XBAR_CTRL);
30b494355 Thierry Reding 2015-08-03 1747
25bb2cec8 Thierry Reding 2015-08-03 1748 /* switch to DP parent clock */
25bb2cec8 Thierry Reding 2015-08-03 1749 err = tegra_sor_set_parent_clock(sor, sor->clk_dp);
6b6b60421 Thierry Reding 2013-11-15 1750 if (err < 0)
25bb2cec8 Thierry Reding 2015-08-03 1751 dev_err(sor->dev, "failed to set parent clock: %d\n", err);
6b6b60421 Thierry Reding 2013-11-15 1752
899451b78 Thierry Reding 2014-06-05 1753 /* power DP lanes */
880cee0b7 Thierry Reding 2017-10-12 1754 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
899451b78 Thierry Reding 2014-06-05 1755
899451b78 Thierry Reding 2014-06-05 1756 if (link.num_lanes <= 2)
899451b78 Thierry Reding 2014-06-05 1757 value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2);
899451b78 Thierry Reding 2014-06-05 1758 else
899451b78 Thierry Reding 2014-06-05 1759 value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2;
899451b78 Thierry Reding 2014-06-05 1760
899451b78 Thierry Reding 2014-06-05 1761 if (link.num_lanes <= 1)
899451b78 Thierry Reding 2014-06-05 1762 value &= ~SOR_DP_PADCTL_PD_TXD_1;
899451b78 Thierry Reding 2014-06-05 1763 else
899451b78 Thierry Reding 2014-06-05 1764 value |= SOR_DP_PADCTL_PD_TXD_1;
899451b78 Thierry Reding 2014-06-05 1765
899451b78 Thierry Reding 2014-06-05 1766 if (link.num_lanes == 0)
899451b78 Thierry Reding 2014-06-05 1767 value &= ~SOR_DP_PADCTL_PD_TXD_0;
899451b78 Thierry Reding 2014-06-05 1768 else
899451b78 Thierry Reding 2014-06-05 1769 value |= SOR_DP_PADCTL_PD_TXD_0;
899451b78 Thierry Reding 2014-06-05 1770
880cee0b7 Thierry Reding 2017-10-12 1771 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
6b6b60421 Thierry Reding 2013-11-15 1772
a9a9e4fd7 Thierry Reding 2015-04-27 1773 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
6b6b60421 Thierry Reding 2013-11-15 1774 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
0c90a1846 Thierry Reding 2014-06-05 1775 value |= SOR_DP_LINKCTL_LANE_COUNT(link.num_lanes);
a9a9e4fd7 Thierry Reding 2015-04-27 1776 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
6b6b60421 Thierry Reding 2013-11-15 1777
6b6b60421 Thierry Reding 2013-11-15 1778 /* start lane sequencer */
6b6b60421 Thierry Reding 2013-11-15 1779 value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
6b6b60421 Thierry Reding 2013-11-15 1780 SOR_LANE_SEQ_CTL_POWER_STATE_UP;
6b6b60421 Thierry Reding 2013-11-15 1781 tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
6b6b60421 Thierry Reding 2013-11-15 1782
6b6b60421 Thierry Reding 2013-11-15 1783 while (true) {
6b6b60421 Thierry Reding 2013-11-15 1784 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
6b6b60421 Thierry Reding 2013-11-15 1785 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
6b6b60421 Thierry Reding 2013-11-15 1786 break;
6b6b60421 Thierry Reding 2013-11-15 1787
6b6b60421 Thierry Reding 2013-11-15 1788 usleep_range(250, 1000);
6b6b60421 Thierry Reding 2013-11-15 1789 }
6b6b60421 Thierry Reding 2013-11-15 1790
a4263fed2 Thierry Reding 2014-06-05 1791 /* set link bandwidth */
6b6b60421 Thierry Reding 2013-11-15 1792 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
6b6b60421 Thierry Reding 2013-11-15 1793 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
a4263fed2 Thierry Reding 2014-06-05 1794 value |= drm_dp_link_rate_to_bw_code(link.rate) << 2;
6b6b60421 Thierry Reding 2013-11-15 1795 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
6b6b60421 Thierry Reding 2013-11-15 1796
402f6bcd9 Thierry Reding 2015-07-21 1797 tegra_sor_apply_config(sor, &config);
402f6bcd9 Thierry Reding 2015-07-21 1798
402f6bcd9 Thierry Reding 2015-07-21 1799 /* enable link */
a9a9e4fd7 Thierry Reding 2015-04-27 1800 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
6b6b60421 Thierry Reding 2013-11-15 1801 value |= SOR_DP_LINKCTL_ENABLE;
6b6b60421 Thierry Reding 2013-11-15 1802 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
a9a9e4fd7 Thierry Reding 2015-04-27 1803 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
6b6b60421 Thierry Reding 2013-11-15 1804
6b6b60421 Thierry Reding 2013-11-15 1805 for (i = 0, value = 0; i < 4; i++) {
6b6b60421 Thierry Reding 2013-11-15 1806 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
6b6b60421 Thierry Reding 2013-11-15 1807 SOR_DP_TPG_SCRAMBLER_GALIOS |
6b6b60421 Thierry Reding 2013-11-15 1808 SOR_DP_TPG_PATTERN_NONE;
6b6b60421 Thierry Reding 2013-11-15 1809 value = (value << 8) | lane;
6b6b60421 Thierry Reding 2013-11-15 1810 }
6b6b60421 Thierry Reding 2013-11-15 1811
6b6b60421 Thierry Reding 2013-11-15 1812 tegra_sor_writel(sor, value, SOR_DP_TPG);
6b6b60421 Thierry Reding 2013-11-15 1813
6b6b60421 Thierry Reding 2013-11-15 1814 /* enable pad calibration logic */
880cee0b7 Thierry Reding 2017-10-12 1815 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
6b6b60421 Thierry Reding 2013-11-15 1816 value |= SOR_DP_PADCTL_PAD_CAL_PD;
880cee0b7 Thierry Reding 2017-10-12 1817 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
6b6b60421 Thierry Reding 2013-11-15 1818
9542c2376 Thierry Reding 2015-07-08 1819 err = drm_dp_link_probe(sor->aux, &link);
850bab448 Thierry Reding 2015-07-29 1820 if (err < 0)
01b9bea0c Thierry Reding 2015-11-11 1821 dev_err(sor->dev, "failed to probe eDP link: %d\n", err);
6b6b60421 Thierry Reding 2013-11-15 1822
9542c2376 Thierry Reding 2015-07-08 1823 err = drm_dp_link_power_up(sor->aux, &link);
850bab448 Thierry Reding 2015-07-29 1824 if (err < 0)
01b9bea0c Thierry Reding 2015-11-11 1825 dev_err(sor->dev, "failed to power up eDP link: %d\n", err);
6b6b60421 Thierry Reding 2013-11-15 1826
9542c2376 Thierry Reding 2015-07-08 1827 err = drm_dp_link_configure(sor->aux, &link);
850bab448 Thierry Reding 2015-07-29 1828 if (err < 0)
01b9bea0c Thierry Reding 2015-11-11 1829 dev_err(sor->dev, "failed to configure eDP link: %d\n", err);
6b6b60421 Thierry Reding 2013-11-15 1830
6b6b60421 Thierry Reding 2013-11-15 1831 rate = drm_dp_link_rate_to_bw_code(link.rate);
6b6b60421 Thierry Reding 2013-11-15 1832 lanes = link.num_lanes;
6b6b60421 Thierry Reding 2013-11-15 1833
6b6b60421 Thierry Reding 2013-11-15 1834 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
6b6b60421 Thierry Reding 2013-11-15 1835 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
6b6b60421 Thierry Reding 2013-11-15 1836 value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate);
6b6b60421 Thierry Reding 2013-11-15 1837 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
6b6b60421 Thierry Reding 2013-11-15 1838
a9a9e4fd7 Thierry Reding 2015-04-27 1839 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
6b6b60421 Thierry Reding 2013-11-15 1840 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
6b6b60421 Thierry Reding 2013-11-15 1841 value |= SOR_DP_LINKCTL_LANE_COUNT(lanes);
6b6b60421 Thierry Reding 2013-11-15 1842
6b6b60421 Thierry Reding 2013-11-15 1843 if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
6b6b60421 Thierry Reding 2013-11-15 1844 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
6b6b60421 Thierry Reding 2013-11-15 1845
a9a9e4fd7 Thierry Reding 2015-04-27 1846 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
6b6b60421 Thierry Reding 2013-11-15 1847
6b6b60421 Thierry Reding 2013-11-15 1848 /* disable training pattern generator */
6b6b60421 Thierry Reding 2013-11-15 1849
6b6b60421 Thierry Reding 2013-11-15 1850 for (i = 0; i < link.num_lanes; i++) {
6b6b60421 Thierry Reding 2013-11-15 1851 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
6b6b60421 Thierry Reding 2013-11-15 1852 SOR_DP_TPG_SCRAMBLER_GALIOS |
6b6b60421 Thierry Reding 2013-11-15 1853 SOR_DP_TPG_PATTERN_NONE;
6b6b60421 Thierry Reding 2013-11-15 1854 value = (value << 8) | lane;
6b6b60421 Thierry Reding 2013-11-15 1855 }
6b6b60421 Thierry Reding 2013-11-15 1856
6b6b60421 Thierry Reding 2013-11-15 1857 tegra_sor_writel(sor, value, SOR_DP_TPG);
6b6b60421 Thierry Reding 2013-11-15 1858
6b6b60421 Thierry Reding 2013-11-15 1859 err = tegra_sor_dp_train_fast(sor, &link);
01b9bea0c Thierry Reding 2015-11-11 1860 if (err < 0)
01b9bea0c Thierry Reding 2015-11-11 1861 dev_err(sor->dev, "DP fast link training failed: %d\n", err);
6b6b60421 Thierry Reding 2013-11-15 1862
6b6b60421 Thierry Reding 2013-11-15 1863 dev_dbg(sor->dev, "fast link training succeeded\n");
6b6b60421 Thierry Reding 2013-11-15 1864
6b6b60421 Thierry Reding 2013-11-15 1865 err = tegra_sor_power_up(sor, 250);
850bab448 Thierry Reding 2015-07-29 1866 if (err < 0)
6b6b60421 Thierry Reding 2013-11-15 1867 dev_err(sor->dev, "failed to power up SOR: %d\n", err);
6b6b60421 Thierry Reding 2013-11-15 1868
6b6b60421 Thierry Reding 2013-11-15 1869 /* CSTM (LVDS, link A/B, upper) */
143b1df23 St?phane Marchesin 2014-05-22 1870 value = SOR_CSTM_LVDS | SOR_CSTM_LINK_ACT_A | SOR_CSTM_LINK_ACT_B |
6b6b60421 Thierry Reding 2013-11-15 1871 SOR_CSTM_UPPER;
6b6b60421 Thierry Reding 2013-11-15 1872 tegra_sor_writel(sor, value, SOR_CSTM);
6b6b60421 Thierry Reding 2013-11-15 1873
2bd1dd399 Thierry Reding 2015-08-03 1874 /* use DP-A protocol */
2bd1dd399 Thierry Reding 2015-08-03 1875 value = tegra_sor_readl(sor, SOR_STATE1);
2bd1dd399 Thierry Reding 2015-08-03 1876 value &= ~SOR_STATE_ASY_PROTOCOL_MASK;
2bd1dd399 Thierry Reding 2015-08-03 1877 value |= SOR_STATE_ASY_PROTOCOL_DP_A;
2bd1dd399 Thierry Reding 2015-08-03 1878 tegra_sor_writel(sor, value, SOR_STATE1);
2bd1dd399 Thierry Reding 2015-08-03 1879
c31efa7a3 Thierry Reding 2015-09-08 1880 tegra_sor_mode_set(sor, mode, state);
2bd1dd399 Thierry Reding 2015-08-03 1881
6fad8f66d Thierry Reding 2014-11-28 1882 /* PWM setup */
6fad8f66d Thierry Reding 2014-11-28 1883 err = tegra_sor_setup_pwm(sor, 250);
850bab448 Thierry Reding 2015-07-29 1884 if (err < 0)
6fad8f66d Thierry Reding 2014-11-28 1885 dev_err(sor->dev, "failed to setup PWM: %d\n", err);
6b6b60421 Thierry Reding 2013-11-15 1886
666cb8733 Thierry Reding 2014-12-08 1887 tegra_sor_update(sor);
666cb8733 Thierry Reding 2014-12-08 1888
6fad8f66d Thierry Reding 2014-11-28 1889 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
c57997bce Thierry Reding 2017-10-12 1890 value |= SOR_ENABLE(0);
6fad8f66d Thierry Reding 2014-11-28 1891 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
6b6b60421 Thierry Reding 2013-11-15 1892
666cb8733 Thierry Reding 2014-12-08 1893 tegra_dc_commit(dc);
6b6b60421 Thierry Reding 2013-11-15 1894
6fad8f66d Thierry Reding 2014-11-28 1895 err = tegra_sor_attach(sor);
850bab448 Thierry Reding 2015-07-29 1896 if (err < 0)
6fad8f66d Thierry Reding 2014-11-28 1897 dev_err(sor->dev, "failed to attach SOR: %d\n", err);
6b6b60421 Thierry Reding 2013-11-15 1898
6fad8f66d Thierry Reding 2014-11-28 1899 err = tegra_sor_wakeup(sor);
850bab448 Thierry Reding 2015-07-29 1900 if (err < 0)
6fad8f66d Thierry Reding 2014-11-28 1901 dev_err(sor->dev, "failed to enable DC: %d\n", err);
6b6b60421 Thierry Reding 2013-11-15 1902
6fad8f66d Thierry Reding 2014-11-28 1903 if (output->panel)
6fad8f66d Thierry Reding 2014-11-28 1904 drm_panel_enable(output->panel);
a82752e19 Thierry Reding 2014-01-31 1905 }
a82752e19 Thierry Reding 2014-01-31 1906

:::::: The code at line 1550 was first introduced by commit
:::::: c57997bce423fb71334a1fefa524569e48a1718f drm/tegra: sor: Add Tegra186 support

:::::: TO: Thierry Reding <[email protected]>
:::::: CC: Thierry Reding <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (31.66 kB)
.config.gz (37.97 kB)
Download all attachments