Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b029ffe0 authored by Olof Johansson's avatar Olof Johansson
Browse files

Merge tag 'tegra-for-4.10-soc' of...

Merge tag 'tegra-for-4.10-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into next/drivers

soc: tegra: Core SoC changes for v4.10-rc1

This contains mostly cleanup and new feature work on the power
management controller as well as the addition of a Kconfig symbol for
the new Tegra186 (Parker) SoC generation.

* tag 'tegra-for-4.10-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux

:
  soc/tegra: pmc: Use consistent naming for PM domains
  soc/tegra: pmc: Remove genpd when adding provider fails
  soc/tegra: pmc: Check return code for pm_genpd_init()
  soc/tegra: pmc: Clean-up I/O rail error messages
  soc/tegra: pmc: Simplify IO rail bit handling
  soc/tegra: pmc: Guard against uninitialised PMC clock
  soc/tegra: pmc: Add I/O pad voltage support
  soc/tegra: pmc: Use consistent ordering of bit definitions
  soc/tegra: pmc: Correct type of variable for tegra_pmc_readl()
  soc/tegra: pmc: Use BIT macro for register field definition

Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 84f1f0c1 45221120
Loading
Loading
Loading
Loading
+305 −93
Original line number Diff line number Diff line
@@ -45,29 +45,31 @@
#include <soc/tegra/pmc.h>

#define PMC_CNTRL			0x0
#define  PMC_CNTRL_SYSCLK_POLARITY	(1 << 10)  /* sys clk polarity */
#define  PMC_CNTRL_SYSCLK_OE		(1 << 11)  /* system clock enable */
#define  PMC_CNTRL_SIDE_EFFECT_LP0	(1 << 14)  /* LP0 when CPU pwr gated */
#define  PMC_CNTRL_CPU_PWRREQ_POLARITY	(1 << 15)  /* CPU pwr req polarity */
#define  PMC_CNTRL_CPU_PWRREQ_OE	(1 << 16)  /* CPU pwr req enable */
#define  PMC_CNTRL_INTR_POLARITY	(1 << 17)  /* inverts INTR polarity */
#define  PMC_CNTRL_MAIN_RST		(1 <<  4)
#define  PMC_CNTRL_INTR_POLARITY	BIT(17) /* inverts INTR polarity */
#define  PMC_CNTRL_CPU_PWRREQ_OE	BIT(16) /* CPU pwr req enable */
#define  PMC_CNTRL_CPU_PWRREQ_POLARITY	BIT(15) /* CPU pwr req polarity */
#define  PMC_CNTRL_SIDE_EFFECT_LP0	BIT(14) /* LP0 when CPU pwr gated */
#define  PMC_CNTRL_SYSCLK_OE		BIT(11) /* system clock enable */
#define  PMC_CNTRL_SYSCLK_POLARITY	BIT(10) /* sys clk polarity */
#define  PMC_CNTRL_MAIN_RST		BIT(4)

#define DPD_SAMPLE			0x020
#define  DPD_SAMPLE_ENABLE		(1 << 0)
#define  DPD_SAMPLE_ENABLE		BIT(0)
#define  DPD_SAMPLE_DISABLE		(0 << 0)

#define PWRGATE_TOGGLE			0x30
#define  PWRGATE_TOGGLE_START		(1 << 8)
#define  PWRGATE_TOGGLE_START		BIT(8)

#define REMOVE_CLAMPING			0x34

#define PWRGATE_STATUS			0x38

#define PMC_PWR_DET			0x48

#define PMC_SCRATCH0			0x50
#define  PMC_SCRATCH0_MODE_RECOVERY	(1 << 31)
#define  PMC_SCRATCH0_MODE_BOOTLOADER	(1 << 30)
#define  PMC_SCRATCH0_MODE_RCM		(1 << 1)
#define  PMC_SCRATCH0_MODE_RECOVERY	BIT(31)
#define  PMC_SCRATCH0_MODE_BOOTLOADER	BIT(30)
#define  PMC_SCRATCH0_MODE_RCM		BIT(1)
#define  PMC_SCRATCH0_MODE_MASK		(PMC_SCRATCH0_MODE_RECOVERY | \
					 PMC_SCRATCH0_MODE_BOOTLOADER | \
					 PMC_SCRATCH0_MODE_RCM)
@@ -75,11 +77,13 @@
#define PMC_CPUPWRGOOD_TIMER		0xc8
#define PMC_CPUPWROFF_TIMER		0xcc

#define PMC_PWR_DET_VALUE		0xe4

#define PMC_SCRATCH41			0x140

#define PMC_SENSOR_CTRL			0x1b0
#define PMC_SENSOR_CTRL_SCRATCH_WRITE	(1 << 2)
#define PMC_SENSOR_CTRL_ENABLE_RST	(1 << 1)
#define  PMC_SENSOR_CTRL_SCRATCH_WRITE	BIT(2)
#define  PMC_SENSOR_CTRL_ENABLE_RST	BIT(1)

#define PMC_RST_STATUS			0x1b4
#define  PMC_RST_STATUS_POR		0
@@ -90,10 +94,10 @@
#define  PMC_RST_STATUS_AOTAG		5

#define IO_DPD_REQ			0x1b8
#define  IO_DPD_REQ_CODE_IDLE		(0 << 30)
#define  IO_DPD_REQ_CODE_OFF		(1 << 30)
#define  IO_DPD_REQ_CODE_ON		(2 << 30)
#define  IO_DPD_REQ_CODE_MASK		(3 << 30)
#define  IO_DPD_REQ_CODE_IDLE		(0U << 30)
#define  IO_DPD_REQ_CODE_OFF		(1U << 30)
#define  IO_DPD_REQ_CODE_ON		(2U << 30)
#define  IO_DPD_REQ_CODE_MASK		(3U << 30)

#define IO_DPD_STATUS			0x1bc
#define IO_DPD2_REQ			0x1c0
@@ -105,10 +109,10 @@
#define  PMC_SCRATCH54_ADDR_SHIFT	0

#define PMC_SCRATCH55			0x25c
#define PMC_SCRATCH55_RESET_TEGRA	(1 << 31)
#define  PMC_SCRATCH55_RESET_TEGRA	BIT(31)
#define  PMC_SCRATCH55_CNTRL_ID_SHIFT	27
#define  PMC_SCRATCH55_PINMUX_SHIFT	24
#define PMC_SCRATCH55_16BITOP		(1 << 15)
#define  PMC_SCRATCH55_16BITOP		BIT(15)
#define  PMC_SCRATCH55_CHECKSUM_SHIFT	16
#define  PMC_SCRATCH55_I2CSLV1_SHIFT	0

@@ -124,6 +128,12 @@ struct tegra_powergate {
	unsigned int num_resets;
};

struct tegra_io_pad_soc {
	enum tegra_io_pad id;
	unsigned int dpd;
	unsigned int voltage;
};

struct tegra_pmc_soc {
	unsigned int num_powergates;
	const char *const *powergates;
@@ -132,6 +142,9 @@ struct tegra_pmc_soc {

	bool has_tsense_reset;
	bool has_gpu_clamps;

	const struct tegra_io_pad_soc *io_pads;
	unsigned int num_io_pads;
};

/**
@@ -238,8 +251,6 @@ static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name)
			return i;
	}

	dev_err(pmc->dev, "powergate %s not found\n", name);

	return -ENODEV;
}

@@ -456,13 +467,12 @@ static int tegra_powergate_power_down(struct tegra_powergate *pg)
static int tegra_genpd_power_on(struct generic_pm_domain *domain)
{
	struct tegra_powergate *pg = to_powergate(domain);
	struct tegra_pmc *pmc = pg->pmc;
	int err;

	err = tegra_powergate_power_up(pg, true);
	if (err)
		dev_err(pmc->dev, "failed to turn on PM domain %s: %d\n",
			pg->genpd.name, err);
		pr_err("failed to turn on PM domain %s: %d\n", pg->genpd.name,
		       err);

	return err;
}
@@ -470,12 +480,11 @@ static int tegra_genpd_power_on(struct generic_pm_domain *domain)
static int tegra_genpd_power_off(struct generic_pm_domain *domain)
{
	struct tegra_powergate *pg = to_powergate(domain);
	struct tegra_pmc *pmc = pg->pmc;
	int err;

	err = tegra_powergate_power_down(pg);
	if (err)
		dev_err(pmc->dev, "failed to turn off PM domain %s: %d\n",
		pr_err("failed to turn off PM domain %s: %d\n",
		       pg->genpd.name, err);

	return err;
@@ -801,8 +810,7 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)

	id = tegra_powergate_lookup(pmc, np->name);
	if (id < 0) {
		dev_err(pmc->dev, "powergate lookup failed for %s: %d\n",
			np->name, id);
		pr_err("powergate lookup failed for %s: %d\n", np->name, id);
		goto free_mem;
	}

@@ -822,20 +830,22 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)

	err = tegra_powergate_of_get_clks(pg, np);
	if (err < 0) {
		dev_err(pmc->dev, "failed to get clocks for %s: %d\n",
			np->name, err);
		pr_err("failed to get clocks for %s: %d\n", np->name, err);
		goto set_available;
	}

	err = tegra_powergate_of_get_resets(pg, np, off);
	if (err < 0) {
		dev_err(pmc->dev, "failed to get resets for %s: %d\n",
			np->name, err);
		pr_err("failed to get resets for %s: %d\n", np->name, err);
		goto remove_clks;
	}

	if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
		goto power_on_cleanup;
	if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
		if (off)
			WARN_ON(tegra_powergate_power_up(pg, true));

		goto remove_resets;
	}

	/*
	 * FIXME: If XHCI is enabled for Tegra, then power-up the XUSB
@@ -846,25 +856,33 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
	 * to be unused.
	 */
	if (IS_ENABLED(CONFIG_USB_XHCI_TEGRA) &&
	    (id == TEGRA_POWERGATE_XUSBA || id == TEGRA_POWERGATE_XUSBC))
		goto power_on_cleanup;
	    (id == TEGRA_POWERGATE_XUSBA || id == TEGRA_POWERGATE_XUSBC)) {
		if (off)
			WARN_ON(tegra_powergate_power_up(pg, true));

	pm_genpd_init(&pg->genpd, NULL, off);
		goto remove_resets;
	}

	err = pm_genpd_init(&pg->genpd, NULL, off);
	if (err < 0) {
		pr_err("failed to initialise PM domain %s: %d\n", np->name,
		       err);
		goto remove_resets;
	}

	err = of_genpd_add_provider_simple(np, &pg->genpd);
	if (err < 0) {
		dev_err(pmc->dev, "failed to add genpd provider for %s: %d\n",
		pr_err("failed to add PM domain provider for %s: %d\n",
		       np->name, err);
		goto remove_resets;
		goto remove_genpd;
	}

	dev_dbg(pmc->dev, "added power domain %s\n", pg->genpd.name);
	pr_debug("added PM domain %s\n", pg->genpd.name);

	return;

power_on_cleanup:
	if (off)
		WARN_ON(tegra_powergate_power_up(pg, true));
remove_genpd:
	pm_genpd_remove(&pg->genpd);

remove_resets:
	while (pg->num_resets--)
@@ -908,21 +926,36 @@ static void tegra_powergate_init(struct tegra_pmc *pmc,
	of_node_put(np);
}

static int tegra_io_rail_prepare(unsigned int id, unsigned long *request,
				 unsigned long *status, unsigned int *bit)
static const struct tegra_io_pad_soc *
tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id)
{
	unsigned int i;

	for (i = 0; i < pmc->soc->num_io_pads; i++)
		if (pmc->soc->io_pads[i].id == id)
			return &pmc->soc->io_pads[i];

	return NULL;
}

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

	*bit = id % 32;
	pad = tegra_io_pad_find(pmc, id);
	if (!pad) {
		pr_err("invalid I/O pad ID %u\n", id);
		return -ENOENT;
	}

	/*
	 * There are two sets of 30 bits to select IO rails, but bits 30 and
	 * 31 are control bits rather than IO rail selection bits.
	 */
	if (id > 63 || *bit == 30 || *bit == 31)
		return -EINVAL;
	if (pad->dpd == UINT_MAX)
		return -ENOTSUPP;

	if (id < 32) {
	*mask = BIT(pad->dpd % 32);

	if (pad->dpd < 32) {
		*status = IO_DPD_STATUS;
		*request = IO_DPD_REQ;
	} else {
@@ -931,6 +964,10 @@ static int tegra_io_rail_prepare(unsigned int id, unsigned long *request,
	}

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

	tegra_pmc_writel(DPD_SAMPLE_ENABLE, DPD_SAMPLE);

@@ -942,10 +979,10 @@ static int tegra_io_rail_prepare(unsigned int id, unsigned long *request,
	return 0;
}

static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
			      unsigned long val, unsigned long timeout)
static int tegra_io_pad_poll(unsigned long offset, u32 mask,
			     u32 val, unsigned long timeout)
{
	unsigned long value;
	u32 value;

	timeout = jiffies + msecs_to_jiffies(timeout);

@@ -960,67 +997,164 @@ static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
	return -ETIMEDOUT;
}

static void tegra_io_rail_unprepare(void)
static void tegra_io_pad_unprepare(void)
{
	tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
}

int tegra_io_rail_power_on(unsigned int id)
/**
 * tegra_io_pad_power_enable() - enable power to I/O pad
 * @id: Tegra I/O pad ID for which to enable power
 *
 * Returns: 0 on success or a negative error code on failure.
 */
int tegra_io_pad_power_enable(enum tegra_io_pad id)
{
	unsigned long request, status;
	unsigned int bit;
	u32 mask;
	int err;

	mutex_lock(&pmc->powergates_lock);

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

	tegra_pmc_writel(IO_DPD_REQ_CODE_OFF | BIT(bit), request);
	tegra_pmc_writel(IO_DPD_REQ_CODE_OFF | mask, request);

	err = tegra_io_rail_poll(status, BIT(bit), 0, 250);
	if (err) {
		pr_info("tegra_io_rail_poll() failed: %d\n", err);
		goto error;
	err = tegra_io_pad_poll(status, mask, 0, 250);
	if (err < 0) {
		pr_err("failed to enable I/O pad: %d\n", err);
		goto unlock;
	}

	tegra_io_rail_unprepare();
	tegra_io_pad_unprepare();

error:
unlock:
	mutex_unlock(&pmc->powergates_lock);

	return err;
}
EXPORT_SYMBOL(tegra_io_rail_power_on);
EXPORT_SYMBOL(tegra_io_pad_power_enable);

int tegra_io_rail_power_off(unsigned int id)
/**
 * tegra_io_pad_power_disable() - disable power to I/O pad
 * @id: Tegra I/O pad ID for which to disable power
 *
 * Returns: 0 on success or a negative error code on failure.
 */
int tegra_io_pad_power_disable(enum tegra_io_pad id)
{
	unsigned long request, status;
	unsigned int bit;
	u32 mask;
	int err;

	mutex_lock(&pmc->powergates_lock);

	err = tegra_io_rail_prepare(id, &request, &status, &bit);
	if (err) {
		pr_info("tegra_io_rail_prepare() failed: %d\n", err);
		goto error;
	err = tegra_io_pad_prepare(id, &request, &status, &mask);
	if (err < 0) {
		pr_err("failed to prepare I/O pad: %d\n", err);
		goto unlock;
	}

	tegra_pmc_writel(IO_DPD_REQ_CODE_ON | BIT(bit), request);
	tegra_pmc_writel(IO_DPD_REQ_CODE_ON | mask, request);

	err = tegra_io_rail_poll(status, BIT(bit), BIT(bit), 250);
	if (err)
		goto error;
	err = tegra_io_pad_poll(status, mask, mask, 250);
	if (err < 0) {
		pr_err("failed to disable I/O pad: %d\n", err);
		goto unlock;
	}

	tegra_io_rail_unprepare();
	tegra_io_pad_unprepare();

error:
unlock:
	mutex_unlock(&pmc->powergates_lock);

	return err;
}
EXPORT_SYMBOL(tegra_io_pad_power_disable);

int tegra_io_pad_set_voltage(enum tegra_io_pad id,
			     enum tegra_io_pad_voltage voltage)
{
	const struct tegra_io_pad_soc *pad;
	u32 value;

	pad = tegra_io_pad_find(pmc, id);
	if (!pad)
		return -ENOENT;

	if (pad->voltage == UINT_MAX)
		return -ENOTSUPP;

	mutex_lock(&pmc->powergates_lock);

	/* write-enable PMC_PWR_DET_VALUE[pad->voltage] */
	value = tegra_pmc_readl(PMC_PWR_DET);
	value |= BIT(pad->voltage);
	tegra_pmc_writel(value, PMC_PWR_DET);

	/* update I/O voltage */
	value = tegra_pmc_readl(PMC_PWR_DET_VALUE);

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

	tegra_pmc_writel(value, PMC_PWR_DET_VALUE);

	mutex_unlock(&pmc->powergates_lock);

	usleep_range(100, 250);

	return 0;
}
EXPORT_SYMBOL(tegra_io_pad_set_voltage);

int tegra_io_pad_get_voltage(enum tegra_io_pad id)
{
	const struct tegra_io_pad_soc *pad;
	u32 value;

	pad = tegra_io_pad_find(pmc, id);
	if (!pad)
		return -ENOENT;

	if (pad->voltage == UINT_MAX)
		return -ENOTSUPP;

	value = tegra_pmc_readl(PMC_PWR_DET_VALUE);

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

	return TEGRA_IO_PAD_3300000UV;
}
EXPORT_SYMBOL(tegra_io_pad_get_voltage);

/**
 * tegra_io_rail_power_on() - enable power to I/O rail
 * @id: Tegra I/O pad ID for which to enable power
 *
 * See also: tegra_io_pad_power_enable()
 */
int tegra_io_rail_power_on(unsigned int id)
{
	return tegra_io_pad_power_enable(id);
}
EXPORT_SYMBOL(tegra_io_rail_power_on);

/**
 * tegra_io_rail_power_off() - disable power to I/O rail
 * @id: Tegra I/O pad ID for which to disable power
 *
 * See also: tegra_io_pad_power_disable()
 */
int tegra_io_rail_power_off(unsigned int id)
{
	return tegra_io_pad_power_disable(id);
}
EXPORT_SYMBOL(tegra_io_rail_power_off);

#ifdef CONFIG_PM_SLEEP
@@ -1454,6 +1588,39 @@ static const u8 tegra124_cpu_powergates[] = {
	TEGRA_POWERGATE_CPU3,
};

static const struct tegra_io_pad_soc tegra124_io_pads[] = {
	{ .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_BB, .dpd = 15, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_CAM, .dpd = 36, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_COMP, .dpd = 22, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_CSIE, .dpd = 44, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_DSI, .dpd = 2, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_DSIB, .dpd = 39, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_DSIC, .dpd = 40, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_DSID, .dpd = 41, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_HDMI, .dpd = 28, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_HSIC, .dpd = 19, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_HV, .dpd = 38, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_LVDS, .dpd = 57, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_NAND, .dpd = 13, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_PEX_BIAS, .dpd = 4, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 5, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = 32, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_SDMMC1, .dpd = 33, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_SDMMC3, .dpd = 34, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_SDMMC4, .dpd = 35, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_SYS_DDC, .dpd = 58, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_USB0, .dpd = 9, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_USB1, .dpd = 10, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_USB2, .dpd = 11, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_USB_BIAS, .dpd = 12, .voltage = UINT_MAX },
};

static const struct tegra_pmc_soc tegra124_pmc_soc = {
	.num_powergates = ARRAY_SIZE(tegra124_powergates),
	.powergates = tegra124_powergates,
@@ -1461,6 +1628,8 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
	.cpu_powergates = tegra124_cpu_powergates,
	.has_tsense_reset = true,
	.has_gpu_clamps = true,
	.num_io_pads = ARRAY_SIZE(tegra124_io_pads),
	.io_pads = tegra124_io_pads,
};

static const char * const tegra210_powergates[] = {
@@ -1497,6 +1666,47 @@ static const u8 tegra210_cpu_powergates[] = {
	TEGRA_POWERGATE_CPU3,
};

static const struct tegra_io_pad_soc tegra210_io_pads[] = {
	{ .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = 5 },
	{ .id = TEGRA_IO_PAD_AUDIO_HV, .dpd = 61, .voltage = 18 },
	{ .id = TEGRA_IO_PAD_CAM, .dpd = 36, .voltage = 10 },
	{ .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_CSIC, .dpd = 42, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_CSID, .dpd = 43, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_CSIE, .dpd = 44, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_CSIF, .dpd = 45, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_DBG, .dpd = 25, .voltage = 19 },
	{ .id = TEGRA_IO_PAD_DEBUG_NONAO, .dpd = 26, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_DMIC, .dpd = 50, .voltage = 20 },
	{ .id = TEGRA_IO_PAD_DP, .dpd = 51, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_DSI, .dpd = 2, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_DSIB, .dpd = 39, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_DSIC, .dpd = 40, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_DSID, .dpd = 41, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_EMMC, .dpd = 35, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_EMMC2, .dpd = 37, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_GPIO, .dpd = 27, .voltage = 21 },
	{ .id = TEGRA_IO_PAD_HDMI, .dpd = 28, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_HSIC, .dpd = 19, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_LVDS, .dpd = 57, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_PEX_BIAS, .dpd = 4, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 5, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = UINT_MAX, .voltage = 11 },
	{ .id = TEGRA_IO_PAD_SDMMC1, .dpd = 33, .voltage = 12 },
	{ .id = TEGRA_IO_PAD_SDMMC3, .dpd = 34, .voltage = 13 },
	{ .id = TEGRA_IO_PAD_SPI, .dpd = 46, .voltage = 22 },
	{ .id = TEGRA_IO_PAD_SPI_HV, .dpd = 47, .voltage = 23 },
	{ .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = 2 },
	{ .id = TEGRA_IO_PAD_USB0, .dpd = 9, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_USB1, .dpd = 10, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_USB2, .dpd = 11, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_USB3, .dpd = 18, .voltage = UINT_MAX },
	{ .id = TEGRA_IO_PAD_USB_BIAS, .dpd = 12, .voltage = UINT_MAX },
};

static const struct tegra_pmc_soc tegra210_pmc_soc = {
	.num_powergates = ARRAY_SIZE(tegra210_powergates),
	.powergates = tegra210_powergates,
@@ -1504,6 +1714,8 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
	.cpu_powergates = tegra210_cpu_powergates,
	.has_tsense_reset = true,
	.has_gpu_clamps = true,
	.num_io_pads = ARRAY_SIZE(tegra210_io_pads),
	.io_pads = tegra210_io_pads,
};

static const struct of_device_id tegra_pmc_match[] = {
+95 −31
Original line number Diff line number Diff line
@@ -76,37 +76,73 @@ int tegra_pmc_cpu_remove_clamping(unsigned int cpuid);

#define TEGRA_POWERGATE_3D0	TEGRA_POWERGATE_3D

#define TEGRA_IO_RAIL_CSIA	0
#define TEGRA_IO_RAIL_CSIB	1
#define TEGRA_IO_RAIL_DSI	2
#define TEGRA_IO_RAIL_MIPI_BIAS	3
#define TEGRA_IO_RAIL_PEX_BIAS	4
#define TEGRA_IO_RAIL_PEX_CLK1	5
#define TEGRA_IO_RAIL_PEX_CLK2	6
#define TEGRA_IO_RAIL_USB0	9
#define TEGRA_IO_RAIL_USB1	10
#define TEGRA_IO_RAIL_USB2	11
#define TEGRA_IO_RAIL_USB_BIAS	12
#define TEGRA_IO_RAIL_NAND	13
#define TEGRA_IO_RAIL_UART	14
#define TEGRA_IO_RAIL_BB	15
#define TEGRA_IO_RAIL_AUDIO	17
#define TEGRA_IO_RAIL_HSIC	19
#define TEGRA_IO_RAIL_COMP	22
#define TEGRA_IO_RAIL_HDMI	28
#define TEGRA_IO_RAIL_PEX_CNTRL	32
#define TEGRA_IO_RAIL_SDMMC1	33
#define TEGRA_IO_RAIL_SDMMC3	34
#define TEGRA_IO_RAIL_SDMMC4	35
#define TEGRA_IO_RAIL_CAM	36
#define TEGRA_IO_RAIL_RES	37
#define TEGRA_IO_RAIL_HV	38
#define TEGRA_IO_RAIL_DSIB	39
#define TEGRA_IO_RAIL_DSIC	40
#define TEGRA_IO_RAIL_DSID	41
#define TEGRA_IO_RAIL_CSIE	44
#define TEGRA_IO_RAIL_LVDS	57
#define TEGRA_IO_RAIL_SYS_DDC	58
/**
 * enum tegra_io_pad - I/O pad group identifier
 *
 * I/O pins on Tegra SoCs are grouped into so-called I/O pads. Each such pad
 * can be used to control the common voltage signal level and power state of
 * the pins of the given pad.
 */
enum tegra_io_pad {
	TEGRA_IO_PAD_AUDIO,
	TEGRA_IO_PAD_AUDIO_HV,
	TEGRA_IO_PAD_BB,
	TEGRA_IO_PAD_CAM,
	TEGRA_IO_PAD_COMP,
	TEGRA_IO_PAD_CSIA,
	TEGRA_IO_PAD_CSIB,
	TEGRA_IO_PAD_CSIC,
	TEGRA_IO_PAD_CSID,
	TEGRA_IO_PAD_CSIE,
	TEGRA_IO_PAD_CSIF,
	TEGRA_IO_PAD_DBG,
	TEGRA_IO_PAD_DEBUG_NONAO,
	TEGRA_IO_PAD_DMIC,
	TEGRA_IO_PAD_DP,
	TEGRA_IO_PAD_DSI,
	TEGRA_IO_PAD_DSIB,
	TEGRA_IO_PAD_DSIC,
	TEGRA_IO_PAD_DSID,
	TEGRA_IO_PAD_EMMC,
	TEGRA_IO_PAD_EMMC2,
	TEGRA_IO_PAD_GPIO,
	TEGRA_IO_PAD_HDMI,
	TEGRA_IO_PAD_HSIC,
	TEGRA_IO_PAD_HV,
	TEGRA_IO_PAD_LVDS,
	TEGRA_IO_PAD_MIPI_BIAS,
	TEGRA_IO_PAD_NAND,
	TEGRA_IO_PAD_PEX_BIAS,
	TEGRA_IO_PAD_PEX_CLK1,
	TEGRA_IO_PAD_PEX_CLK2,
	TEGRA_IO_PAD_PEX_CNTRL,
	TEGRA_IO_PAD_SDMMC1,
	TEGRA_IO_PAD_SDMMC3,
	TEGRA_IO_PAD_SDMMC4,
	TEGRA_IO_PAD_SPI,
	TEGRA_IO_PAD_SPI_HV,
	TEGRA_IO_PAD_SYS_DDC,
	TEGRA_IO_PAD_UART,
	TEGRA_IO_PAD_USB0,
	TEGRA_IO_PAD_USB1,
	TEGRA_IO_PAD_USB2,
	TEGRA_IO_PAD_USB3,
	TEGRA_IO_PAD_USB_BIAS,
};

/* deprecated, use TEGRA_IO_PAD_{HDMI,LVDS} instead */
#define TEGRA_IO_RAIL_HDMI	TEGRA_IO_PAD_HDMI
#define TEGRA_IO_RAIL_LVDS	TEGRA_IO_PAD_LVDS

/**
 * enum tegra_io_pad_voltage - voltage level of the I/O pad's source rail
 * @TEGRA_IO_PAD_1800000UV: 1.8 V
 * @TEGRA_IO_PAD_3300000UV: 3.3 V
 */
enum tegra_io_pad_voltage {
	TEGRA_IO_PAD_1800000UV,
	TEGRA_IO_PAD_3300000UV,
};

#ifdef CONFIG_ARCH_TEGRA
int tegra_powergate_is_powered(unsigned int id);
@@ -118,6 +154,13 @@ int tegra_powergate_remove_clamping(unsigned int id);
int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
				      struct reset_control *rst);

int tegra_io_pad_power_enable(enum tegra_io_pad id);
int tegra_io_pad_power_disable(enum tegra_io_pad id);
int tegra_io_pad_set_voltage(enum tegra_io_pad id,
			     enum tegra_io_pad_voltage voltage);
int tegra_io_pad_get_voltage(enum tegra_io_pad id);

/* deprecated, use tegra_io_pad_power_{enable,disable}() instead */
int tegra_io_rail_power_on(unsigned int id);
int tegra_io_rail_power_off(unsigned int id);
#else
@@ -148,6 +191,27 @@ static inline int tegra_powergate_sequence_power_up(unsigned int id,
	return -ENOSYS;
}

static inline int tegra_io_pad_power_enable(enum tegra_io_pad id)
{
	return -ENOSYS;
}

static inline int tegra_io_pad_power_disable(enum tegra_io_pad id)
{
	return -ENOSYS;
}

static inline int tegra_io_pad_set_voltage(enum tegra_io_pad id,
					   enum tegra_io_pad_voltage voltage)
{
	return -ENOSYS;
}

static inline int tegra_io_pad_get_voltage(enum tegra_io_pad id)
{
	return -ENOSYS;
}

static inline int tegra_io_rail_power_on(unsigned int id)
{
	return -ENOSYS;