mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-12 08:09:56 +00:00
soc/tegra: pmc: Pass struct tegra_pmc * where possible
Instead of using the global pmc variable, pass around a pointer where possible. Also, replace most occurrences of pr_*() functions by their equivalent dev_*() functions, reusing the pmc->dev pointer. It's not possible to get completely rid of the global variable because some of the public API that this driver exposes still relies on it. Signed-off-by: Thierry Reding <treding@nvidia.com> Acked-by: Jon Hunter <jonathanh@nvidia.com>
This commit is contained in:
parent
d32dde2c5a
commit
589997a157
@ -344,30 +344,36 @@ to_powergate(struct generic_pm_domain *domain)
|
|||||||
return container_of(domain, struct tegra_powergate, genpd);
|
return container_of(domain, struct tegra_powergate, genpd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 tegra_pmc_readl(unsigned long offset)
|
static u32 tegra_pmc_readl(struct tegra_pmc *pmc, unsigned long offset)
|
||||||
{
|
{
|
||||||
return readl(pmc->base + offset);
|
return readl(pmc->base + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra_pmc_writel(u32 value, unsigned long offset)
|
static void tegra_pmc_writel(struct tegra_pmc *pmc, u32 value,
|
||||||
|
unsigned long offset)
|
||||||
{
|
{
|
||||||
writel(value, pmc->base + offset);
|
writel(value, pmc->base + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO Figure out a way to call this with the struct tegra_pmc * passed in.
|
||||||
|
* This currently doesn't work because readx_poll_timeout() can only operate
|
||||||
|
* on functions that take a single argument.
|
||||||
|
*/
|
||||||
static inline bool tegra_powergate_state(int id)
|
static inline bool tegra_powergate_state(int id)
|
||||||
{
|
{
|
||||||
if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps)
|
if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps)
|
||||||
return (tegra_pmc_readl(GPU_RG_CNTRL) & 0x1) == 0;
|
return (tegra_pmc_readl(pmc, GPU_RG_CNTRL) & 0x1) == 0;
|
||||||
else
|
else
|
||||||
return (tegra_pmc_readl(PWRGATE_STATUS) & BIT(id)) != 0;
|
return (tegra_pmc_readl(pmc, PWRGATE_STATUS) & BIT(id)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool tegra_powergate_is_valid(int id)
|
static inline bool tegra_powergate_is_valid(struct tegra_pmc *pmc, int id)
|
||||||
{
|
{
|
||||||
return (pmc->soc && pmc->soc->powergates[id]);
|
return (pmc->soc && pmc->soc->powergates[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool tegra_powergate_is_available(int id)
|
static inline bool tegra_powergate_is_available(struct tegra_pmc *pmc, int id)
|
||||||
{
|
{
|
||||||
return test_bit(id, pmc->powergates_available);
|
return test_bit(id, pmc->powergates_available);
|
||||||
}
|
}
|
||||||
@ -380,7 +386,7 @@ static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < pmc->soc->num_powergates; i++) {
|
for (i = 0; i < pmc->soc->num_powergates; i++) {
|
||||||
if (!tegra_powergate_is_valid(i))
|
if (!tegra_powergate_is_valid(pmc, i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!strcmp(name, pmc->soc->powergates[i]))
|
if (!strcmp(name, pmc->soc->powergates[i]))
|
||||||
@ -392,10 +398,12 @@ static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* tegra_powergate_set() - set the state of a partition
|
* tegra_powergate_set() - set the state of a partition
|
||||||
|
* @pmc: power management controller
|
||||||
* @id: partition ID
|
* @id: partition ID
|
||||||
* @new_state: new state of the partition
|
* @new_state: new state of the partition
|
||||||
*/
|
*/
|
||||||
static int tegra_powergate_set(unsigned int id, bool new_state)
|
static int tegra_powergate_set(struct tegra_pmc *pmc, unsigned int id,
|
||||||
|
bool new_state)
|
||||||
{
|
{
|
||||||
bool status;
|
bool status;
|
||||||
int err;
|
int err;
|
||||||
@ -410,7 +418,7 @@ static int tegra_powergate_set(unsigned int id, bool new_state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
|
tegra_pmc_writel(pmc, PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
|
||||||
|
|
||||||
err = readx_poll_timeout(tegra_powergate_state, id, status,
|
err = readx_poll_timeout(tegra_powergate_state, id, status,
|
||||||
status == new_state, 10, 100000);
|
status == new_state, 10, 100000);
|
||||||
@ -420,7 +428,8 @@ static int tegra_powergate_set(unsigned int id, bool new_state)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __tegra_powergate_remove_clamping(unsigned int id)
|
static int __tegra_powergate_remove_clamping(struct tegra_pmc *pmc,
|
||||||
|
unsigned int id)
|
||||||
{
|
{
|
||||||
u32 mask;
|
u32 mask;
|
||||||
|
|
||||||
@ -432,7 +441,7 @@ static int __tegra_powergate_remove_clamping(unsigned int id)
|
|||||||
*/
|
*/
|
||||||
if (id == TEGRA_POWERGATE_3D) {
|
if (id == TEGRA_POWERGATE_3D) {
|
||||||
if (pmc->soc->has_gpu_clamps) {
|
if (pmc->soc->has_gpu_clamps) {
|
||||||
tegra_pmc_writel(0, GPU_RG_CNTRL);
|
tegra_pmc_writel(pmc, 0, GPU_RG_CNTRL);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -448,7 +457,7 @@ static int __tegra_powergate_remove_clamping(unsigned int id)
|
|||||||
else
|
else
|
||||||
mask = (1 << id);
|
mask = (1 << id);
|
||||||
|
|
||||||
tegra_pmc_writel(mask, REMOVE_CLAMPING);
|
tegra_pmc_writel(pmc, mask, REMOVE_CLAMPING);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&pmc->powergates_lock);
|
mutex_unlock(&pmc->powergates_lock);
|
||||||
@ -500,7 +509,7 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg,
|
|||||||
|
|
||||||
usleep_range(10, 20);
|
usleep_range(10, 20);
|
||||||
|
|
||||||
err = tegra_powergate_set(pg->id, true);
|
err = tegra_powergate_set(pg->pmc, pg->id, true);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -512,7 +521,7 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg,
|
|||||||
|
|
||||||
usleep_range(10, 20);
|
usleep_range(10, 20);
|
||||||
|
|
||||||
err = __tegra_powergate_remove_clamping(pg->id);
|
err = __tegra_powergate_remove_clamping(pg->pmc, pg->id);
|
||||||
if (err)
|
if (err)
|
||||||
goto disable_clks;
|
goto disable_clks;
|
||||||
|
|
||||||
@ -539,7 +548,7 @@ disable_clks:
|
|||||||
usleep_range(10, 20);
|
usleep_range(10, 20);
|
||||||
|
|
||||||
powergate_off:
|
powergate_off:
|
||||||
tegra_powergate_set(pg->id, false);
|
tegra_powergate_set(pg->pmc, pg->id, false);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -564,7 +573,7 @@ static int tegra_powergate_power_down(struct tegra_powergate *pg)
|
|||||||
|
|
||||||
usleep_range(10, 20);
|
usleep_range(10, 20);
|
||||||
|
|
||||||
err = tegra_powergate_set(pg->id, false);
|
err = tegra_powergate_set(pg->pmc, pg->id, false);
|
||||||
if (err)
|
if (err)
|
||||||
goto assert_resets;
|
goto assert_resets;
|
||||||
|
|
||||||
@ -585,12 +594,13 @@ disable_clks:
|
|||||||
static int tegra_genpd_power_on(struct generic_pm_domain *domain)
|
static int tegra_genpd_power_on(struct generic_pm_domain *domain)
|
||||||
{
|
{
|
||||||
struct tegra_powergate *pg = to_powergate(domain);
|
struct tegra_powergate *pg = to_powergate(domain);
|
||||||
|
struct device *dev = pg->pmc->dev;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = tegra_powergate_power_up(pg, true);
|
err = tegra_powergate_power_up(pg, true);
|
||||||
if (err)
|
if (err)
|
||||||
pr_err("failed to turn on PM domain %s: %d\n", pg->genpd.name,
|
dev_err(dev, "failed to turn on PM domain %s: %d\n",
|
||||||
err);
|
pg->genpd.name, err);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -598,12 +608,13 @@ static int tegra_genpd_power_on(struct generic_pm_domain *domain)
|
|||||||
static int tegra_genpd_power_off(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_powergate *pg = to_powergate(domain);
|
||||||
|
struct device *dev = pg->pmc->dev;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = tegra_powergate_power_down(pg);
|
err = tegra_powergate_power_down(pg);
|
||||||
if (err)
|
if (err)
|
||||||
pr_err("failed to turn off PM domain %s: %d\n",
|
dev_err(dev, "failed to turn off PM domain %s: %d\n",
|
||||||
pg->genpd.name, err);
|
pg->genpd.name, err);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -614,10 +625,10 @@ static int tegra_genpd_power_off(struct generic_pm_domain *domain)
|
|||||||
*/
|
*/
|
||||||
int tegra_powergate_power_on(unsigned int id)
|
int tegra_powergate_power_on(unsigned int id)
|
||||||
{
|
{
|
||||||
if (!tegra_powergate_is_available(id))
|
if (!tegra_powergate_is_available(pmc, id))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return tegra_powergate_set(id, true);
|
return tegra_powergate_set(pmc, id, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -626,20 +637,21 @@ int tegra_powergate_power_on(unsigned int id)
|
|||||||
*/
|
*/
|
||||||
int tegra_powergate_power_off(unsigned int id)
|
int tegra_powergate_power_off(unsigned int id)
|
||||||
{
|
{
|
||||||
if (!tegra_powergate_is_available(id))
|
if (!tegra_powergate_is_available(pmc, id))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return tegra_powergate_set(id, false);
|
return tegra_powergate_set(pmc, id, false);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tegra_powergate_power_off);
|
EXPORT_SYMBOL(tegra_powergate_power_off);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tegra_powergate_is_powered() - check if partition is powered
|
* tegra_powergate_is_powered() - check if partition is powered
|
||||||
|
* @pmc: power management controller
|
||||||
* @id: partition ID
|
* @id: partition ID
|
||||||
*/
|
*/
|
||||||
static int tegra_powergate_is_powered(unsigned int id)
|
static int tegra_powergate_is_powered(struct tegra_pmc *pmc, unsigned int id)
|
||||||
{
|
{
|
||||||
if (!tegra_powergate_is_valid(id))
|
if (!tegra_powergate_is_valid(pmc, id))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return tegra_powergate_state(id);
|
return tegra_powergate_state(id);
|
||||||
@ -651,10 +663,10 @@ static int tegra_powergate_is_powered(unsigned int id)
|
|||||||
*/
|
*/
|
||||||
int tegra_powergate_remove_clamping(unsigned int id)
|
int tegra_powergate_remove_clamping(unsigned int id)
|
||||||
{
|
{
|
||||||
if (!tegra_powergate_is_available(id))
|
if (!tegra_powergate_is_available(pmc, id))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return __tegra_powergate_remove_clamping(id);
|
return __tegra_powergate_remove_clamping(pmc, id);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tegra_powergate_remove_clamping);
|
EXPORT_SYMBOL(tegra_powergate_remove_clamping);
|
||||||
|
|
||||||
@ -672,7 +684,7 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
|
|||||||
struct tegra_powergate *pg;
|
struct tegra_powergate *pg;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!tegra_powergate_is_available(id))
|
if (!tegra_powergate_is_available(pmc, id))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
pg = kzalloc(sizeof(*pg), GFP_KERNEL);
|
pg = kzalloc(sizeof(*pg), GFP_KERNEL);
|
||||||
@ -687,7 +699,8 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
|
|||||||
|
|
||||||
err = tegra_powergate_power_up(pg, false);
|
err = tegra_powergate_power_up(pg, false);
|
||||||
if (err)
|
if (err)
|
||||||
pr_err("failed to turn on partition %d: %d\n", id, err);
|
dev_err(pmc->dev, "failed to turn on partition %d: %d\n", id,
|
||||||
|
err);
|
||||||
|
|
||||||
kfree(pg);
|
kfree(pg);
|
||||||
|
|
||||||
@ -697,12 +710,14 @@ EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* tegra_get_cpu_powergate_id() - convert from CPU ID to partition ID
|
* tegra_get_cpu_powergate_id() - convert from CPU ID to partition ID
|
||||||
|
* @pmc: power management controller
|
||||||
* @cpuid: CPU partition ID
|
* @cpuid: CPU partition ID
|
||||||
*
|
*
|
||||||
* Returns the partition ID corresponding to the CPU partition ID or a
|
* Returns the partition ID corresponding to the CPU partition ID or a
|
||||||
* negative error code on failure.
|
* negative error code on failure.
|
||||||
*/
|
*/
|
||||||
static int tegra_get_cpu_powergate_id(unsigned int cpuid)
|
static int tegra_get_cpu_powergate_id(struct tegra_pmc *pmc,
|
||||||
|
unsigned int cpuid)
|
||||||
{
|
{
|
||||||
if (pmc->soc && cpuid < pmc->soc->num_cpu_powergates)
|
if (pmc->soc && cpuid < pmc->soc->num_cpu_powergates)
|
||||||
return pmc->soc->cpu_powergates[cpuid];
|
return pmc->soc->cpu_powergates[cpuid];
|
||||||
@ -718,11 +733,11 @@ bool tegra_pmc_cpu_is_powered(unsigned int cpuid)
|
|||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
id = tegra_get_cpu_powergate_id(cpuid);
|
id = tegra_get_cpu_powergate_id(pmc, cpuid);
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return tegra_powergate_is_powered(id);
|
return tegra_powergate_is_powered(pmc, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -733,11 +748,11 @@ int tegra_pmc_cpu_power_on(unsigned int cpuid)
|
|||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
id = tegra_get_cpu_powergate_id(cpuid);
|
id = tegra_get_cpu_powergate_id(pmc, cpuid);
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
return id;
|
return id;
|
||||||
|
|
||||||
return tegra_powergate_set(id, true);
|
return tegra_powergate_set(pmc, id, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -748,7 +763,7 @@ int tegra_pmc_cpu_remove_clamping(unsigned int cpuid)
|
|||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
id = tegra_get_cpu_powergate_id(cpuid);
|
id = tegra_get_cpu_powergate_id(pmc, cpuid);
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
return id;
|
return id;
|
||||||
|
|
||||||
@ -778,9 +793,9 @@ static int tegra_pmc_restart_notify(struct notifier_block *this,
|
|||||||
writel(value, pmc->scratch + pmc->soc->regs->scratch0);
|
writel(value, pmc->scratch + pmc->soc->regs->scratch0);
|
||||||
|
|
||||||
/* reset everything but PMC_SCRATCH0 and PMC_RST_STATUS */
|
/* reset everything but PMC_SCRATCH0 and PMC_RST_STATUS */
|
||||||
value = tegra_pmc_readl(PMC_CNTRL);
|
value = tegra_pmc_readl(pmc, PMC_CNTRL);
|
||||||
value |= PMC_CNTRL_MAIN_RST;
|
value |= PMC_CNTRL_MAIN_RST;
|
||||||
tegra_pmc_writel(value, PMC_CNTRL);
|
tegra_pmc_writel(pmc, value, PMC_CNTRL);
|
||||||
|
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
}
|
}
|
||||||
@ -799,7 +814,7 @@ static int powergate_show(struct seq_file *s, void *data)
|
|||||||
seq_printf(s, "------------------\n");
|
seq_printf(s, "------------------\n");
|
||||||
|
|
||||||
for (i = 0; i < pmc->soc->num_powergates; i++) {
|
for (i = 0; i < pmc->soc->num_powergates; i++) {
|
||||||
status = tegra_powergate_is_powered(i);
|
status = tegra_powergate_is_powered(pmc, i);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -861,12 +876,13 @@ err:
|
|||||||
static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
|
static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
|
||||||
struct device_node *np, bool off)
|
struct device_node *np, bool off)
|
||||||
{
|
{
|
||||||
|
struct device *dev = pg->pmc->dev;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
pg->reset = of_reset_control_array_get_exclusive(np);
|
pg->reset = of_reset_control_array_get_exclusive(np);
|
||||||
if (IS_ERR(pg->reset)) {
|
if (IS_ERR(pg->reset)) {
|
||||||
err = PTR_ERR(pg->reset);
|
err = PTR_ERR(pg->reset);
|
||||||
pr_err("failed to get device resets: %d\n", err);
|
dev_err(dev, "failed to get device resets: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -883,6 +899,7 @@ static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
|
|||||||
|
|
||||||
static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
|
static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
|
||||||
{
|
{
|
||||||
|
struct device *dev = pmc->dev;
|
||||||
struct tegra_powergate *pg;
|
struct tegra_powergate *pg;
|
||||||
int id, err;
|
int id, err;
|
||||||
bool off;
|
bool off;
|
||||||
@ -893,7 +910,7 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
|
|||||||
|
|
||||||
id = tegra_powergate_lookup(pmc, np->name);
|
id = tegra_powergate_lookup(pmc, np->name);
|
||||||
if (id < 0) {
|
if (id < 0) {
|
||||||
pr_err("powergate lookup failed for %pOFn: %d\n", np, id);
|
dev_err(dev, "powergate lookup failed for %pOFn: %d\n", np, id);
|
||||||
goto free_mem;
|
goto free_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -909,17 +926,17 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
|
|||||||
pg->genpd.power_on = tegra_genpd_power_on;
|
pg->genpd.power_on = tegra_genpd_power_on;
|
||||||
pg->pmc = pmc;
|
pg->pmc = pmc;
|
||||||
|
|
||||||
off = !tegra_powergate_is_powered(pg->id);
|
off = !tegra_powergate_is_powered(pmc, pg->id);
|
||||||
|
|
||||||
err = tegra_powergate_of_get_clks(pg, np);
|
err = tegra_powergate_of_get_clks(pg, np);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pr_err("failed to get clocks for %pOFn: %d\n", np, err);
|
dev_err(dev, "failed to get clocks for %pOFn: %d\n", np, err);
|
||||||
goto set_available;
|
goto set_available;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tegra_powergate_of_get_resets(pg, np, off);
|
err = tegra_powergate_of_get_resets(pg, np, off);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pr_err("failed to get resets for %pOFn: %d\n", np, err);
|
dev_err(dev, "failed to get resets for %pOFn: %d\n", np, err);
|
||||||
goto remove_clks;
|
goto remove_clks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -932,19 +949,19 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
|
|||||||
|
|
||||||
err = pm_genpd_init(&pg->genpd, NULL, off);
|
err = pm_genpd_init(&pg->genpd, NULL, off);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pr_err("failed to initialise PM domain %pOFn: %d\n", np,
|
dev_err(dev, "failed to initialise PM domain %pOFn: %d\n", np,
|
||||||
err);
|
err);
|
||||||
goto remove_resets;
|
goto remove_resets;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = of_genpd_add_provider_simple(np, &pg->genpd);
|
err = of_genpd_add_provider_simple(np, &pg->genpd);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pr_err("failed to add PM domain provider for %pOFn: %d\n",
|
dev_err(dev, "failed to add PM domain provider for %pOFn: %d\n",
|
||||||
np, err);
|
np, err);
|
||||||
goto remove_genpd;
|
goto remove_genpd;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("added PM domain %s\n", pg->genpd.name);
|
dev_dbg(dev, "added PM domain %s\n", pg->genpd.name);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1000,7 +1017,8 @@ tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id,
|
static int tegra_io_pad_get_dpd_register_bit(struct tegra_pmc *pmc,
|
||||||
|
enum tegra_io_pad id,
|
||||||
unsigned long *request,
|
unsigned long *request,
|
||||||
unsigned long *status,
|
unsigned long *status,
|
||||||
u32 *mask)
|
u32 *mask)
|
||||||
@ -1009,7 +1027,7 @@ static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id,
|
|||||||
|
|
||||||
pad = tegra_io_pad_find(pmc, id);
|
pad = tegra_io_pad_find(pmc, id);
|
||||||
if (!pad) {
|
if (!pad) {
|
||||||
pr_err("invalid I/O pad ID %u\n", id);
|
dev_err(pmc->dev, "invalid I/O pad ID %u\n", id);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1029,43 +1047,44 @@ static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request,
|
static int tegra_io_pad_prepare(struct tegra_pmc *pmc, enum tegra_io_pad id,
|
||||||
unsigned long *status, u32 *mask)
|
unsigned long *request, unsigned long *status,
|
||||||
|
u32 *mask)
|
||||||
{
|
{
|
||||||
unsigned long rate, value;
|
unsigned long rate, value;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = tegra_io_pad_get_dpd_register_bit(id, request, status, mask);
|
err = tegra_io_pad_get_dpd_register_bit(pmc, id, request, status, mask);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (pmc->clk) {
|
if (pmc->clk) {
|
||||||
rate = clk_get_rate(pmc->clk);
|
rate = clk_get_rate(pmc->clk);
|
||||||
if (!rate) {
|
if (!rate) {
|
||||||
pr_err("failed to get clock rate\n");
|
dev_err(pmc->dev, "failed to get clock rate\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
tegra_pmc_writel(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
|
tegra_pmc_writel(pmc, DPD_SAMPLE_ENABLE, DPD_SAMPLE);
|
||||||
|
|
||||||
/* must be at least 200 ns, in APB (PCLK) clock cycles */
|
/* must be at least 200 ns, in APB (PCLK) clock cycles */
|
||||||
value = DIV_ROUND_UP(1000000000, rate);
|
value = DIV_ROUND_UP(1000000000, rate);
|
||||||
value = DIV_ROUND_UP(200, value);
|
value = DIV_ROUND_UP(200, value);
|
||||||
tegra_pmc_writel(value, SEL_DPD_TIM);
|
tegra_pmc_writel(pmc, value, SEL_DPD_TIM);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_io_pad_poll(unsigned long offset, u32 mask,
|
static int tegra_io_pad_poll(struct tegra_pmc *pmc, unsigned long offset,
|
||||||
u32 val, unsigned long timeout)
|
u32 mask, u32 val, unsigned long timeout)
|
||||||
{
|
{
|
||||||
u32 value;
|
u32 value;
|
||||||
|
|
||||||
timeout = jiffies + msecs_to_jiffies(timeout);
|
timeout = jiffies + msecs_to_jiffies(timeout);
|
||||||
|
|
||||||
while (time_after(timeout, jiffies)) {
|
while (time_after(timeout, jiffies)) {
|
||||||
value = tegra_pmc_readl(offset);
|
value = tegra_pmc_readl(pmc, offset);
|
||||||
if ((value & mask) == val)
|
if ((value & mask) == val)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1075,10 +1094,10 @@ static int tegra_io_pad_poll(unsigned long offset, u32 mask,
|
|||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra_io_pad_unprepare(void)
|
static void tegra_io_pad_unprepare(struct tegra_pmc *pmc)
|
||||||
{
|
{
|
||||||
if (pmc->clk)
|
if (pmc->clk)
|
||||||
tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
|
tegra_pmc_writel(pmc, DPD_SAMPLE_DISABLE, DPD_SAMPLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1095,21 +1114,21 @@ int tegra_io_pad_power_enable(enum tegra_io_pad id)
|
|||||||
|
|
||||||
mutex_lock(&pmc->powergates_lock);
|
mutex_lock(&pmc->powergates_lock);
|
||||||
|
|
||||||
err = tegra_io_pad_prepare(id, &request, &status, &mask);
|
err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pr_err("failed to prepare I/O pad: %d\n", err);
|
dev_err(pmc->dev, "failed to prepare I/O pad: %d\n", err);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
tegra_pmc_writel(IO_DPD_REQ_CODE_OFF | mask, request);
|
tegra_pmc_writel(pmc, IO_DPD_REQ_CODE_OFF | mask, request);
|
||||||
|
|
||||||
err = tegra_io_pad_poll(status, mask, 0, 250);
|
err = tegra_io_pad_poll(pmc, status, mask, 0, 250);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pr_err("failed to enable I/O pad: %d\n", err);
|
dev_err(pmc->dev, "failed to enable I/O pad: %d\n", err);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
tegra_io_pad_unprepare();
|
tegra_io_pad_unprepare(pmc);
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
mutex_unlock(&pmc->powergates_lock);
|
mutex_unlock(&pmc->powergates_lock);
|
||||||
@ -1131,21 +1150,21 @@ int tegra_io_pad_power_disable(enum tegra_io_pad id)
|
|||||||
|
|
||||||
mutex_lock(&pmc->powergates_lock);
|
mutex_lock(&pmc->powergates_lock);
|
||||||
|
|
||||||
err = tegra_io_pad_prepare(id, &request, &status, &mask);
|
err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pr_err("failed to prepare I/O pad: %d\n", err);
|
dev_err(pmc->dev, "failed to prepare I/O pad: %d\n", err);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
tegra_pmc_writel(IO_DPD_REQ_CODE_ON | mask, request);
|
tegra_pmc_writel(pmc, IO_DPD_REQ_CODE_ON | mask, request);
|
||||||
|
|
||||||
err = tegra_io_pad_poll(status, mask, mask, 250);
|
err = tegra_io_pad_poll(pmc, status, mask, mask, 250);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pr_err("failed to disable I/O pad: %d\n", err);
|
dev_err(pmc->dev, "failed to disable I/O pad: %d\n", err);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
tegra_io_pad_unprepare();
|
tegra_io_pad_unprepare(pmc);
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
mutex_unlock(&pmc->powergates_lock);
|
mutex_unlock(&pmc->powergates_lock);
|
||||||
@ -1153,22 +1172,24 @@ unlock:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tegra_io_pad_power_disable);
|
EXPORT_SYMBOL(tegra_io_pad_power_disable);
|
||||||
|
|
||||||
static int tegra_io_pad_is_powered(enum tegra_io_pad id)
|
static int tegra_io_pad_is_powered(struct tegra_pmc *pmc, enum tegra_io_pad id)
|
||||||
{
|
{
|
||||||
unsigned long request, status;
|
unsigned long request, status;
|
||||||
u32 mask, value;
|
u32 mask, value;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = tegra_io_pad_get_dpd_register_bit(id, &request, &status, &mask);
|
err = tegra_io_pad_get_dpd_register_bit(pmc, id, &request, &status,
|
||||||
|
&mask);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
value = tegra_pmc_readl(status);
|
value = tegra_pmc_readl(pmc, status);
|
||||||
|
|
||||||
return !(value & mask);
|
return !(value & mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage)
|
static int tegra_io_pad_set_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id,
|
||||||
|
int voltage)
|
||||||
{
|
{
|
||||||
const struct tegra_io_pad_soc *pad;
|
const struct tegra_io_pad_soc *pad;
|
||||||
u32 value;
|
u32 value;
|
||||||
@ -1183,29 +1204,29 @@ static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage)
|
|||||||
mutex_lock(&pmc->powergates_lock);
|
mutex_lock(&pmc->powergates_lock);
|
||||||
|
|
||||||
if (pmc->soc->has_impl_33v_pwr) {
|
if (pmc->soc->has_impl_33v_pwr) {
|
||||||
value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR);
|
value = tegra_pmc_readl(pmc, PMC_IMPL_E_33V_PWR);
|
||||||
|
|
||||||
if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
|
if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
|
||||||
value &= ~BIT(pad->voltage);
|
value &= ~BIT(pad->voltage);
|
||||||
else
|
else
|
||||||
value |= BIT(pad->voltage);
|
value |= BIT(pad->voltage);
|
||||||
|
|
||||||
tegra_pmc_writel(value, PMC_IMPL_E_33V_PWR);
|
tegra_pmc_writel(pmc, value, PMC_IMPL_E_33V_PWR);
|
||||||
} else {
|
} else {
|
||||||
/* write-enable PMC_PWR_DET_VALUE[pad->voltage] */
|
/* write-enable PMC_PWR_DET_VALUE[pad->voltage] */
|
||||||
value = tegra_pmc_readl(PMC_PWR_DET);
|
value = tegra_pmc_readl(pmc, PMC_PWR_DET);
|
||||||
value |= BIT(pad->voltage);
|
value |= BIT(pad->voltage);
|
||||||
tegra_pmc_writel(value, PMC_PWR_DET);
|
tegra_pmc_writel(pmc, value, PMC_PWR_DET);
|
||||||
|
|
||||||
/* update I/O voltage */
|
/* update I/O voltage */
|
||||||
value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
|
value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE);
|
||||||
|
|
||||||
if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
|
if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
|
||||||
value &= ~BIT(pad->voltage);
|
value &= ~BIT(pad->voltage);
|
||||||
else
|
else
|
||||||
value |= BIT(pad->voltage);
|
value |= BIT(pad->voltage);
|
||||||
|
|
||||||
tegra_pmc_writel(value, PMC_PWR_DET_VALUE);
|
tegra_pmc_writel(pmc, value, PMC_PWR_DET_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&pmc->powergates_lock);
|
mutex_unlock(&pmc->powergates_lock);
|
||||||
@ -1215,7 +1236,7 @@ static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_io_pad_get_voltage(enum tegra_io_pad id)
|
static int tegra_io_pad_get_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id)
|
||||||
{
|
{
|
||||||
const struct tegra_io_pad_soc *pad;
|
const struct tegra_io_pad_soc *pad;
|
||||||
u32 value;
|
u32 value;
|
||||||
@ -1228,9 +1249,9 @@ static int tegra_io_pad_get_voltage(enum tegra_io_pad id)
|
|||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
if (pmc->soc->has_impl_33v_pwr)
|
if (pmc->soc->has_impl_33v_pwr)
|
||||||
value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR);
|
value = tegra_pmc_readl(pmc, PMC_IMPL_E_33V_PWR);
|
||||||
else
|
else
|
||||||
value = tegra_pmc_readl(PMC_PWR_DET_VALUE);
|
value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE);
|
||||||
|
|
||||||
if ((value & BIT(pad->voltage)) == 0)
|
if ((value & BIT(pad->voltage)) == 0)
|
||||||
return TEGRA_IO_PAD_VOLTAGE_1V8;
|
return TEGRA_IO_PAD_VOLTAGE_1V8;
|
||||||
@ -1302,21 +1323,21 @@ void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
|
|||||||
|
|
||||||
ticks = pmc->cpu_good_time * rate + USEC_PER_SEC - 1;
|
ticks = pmc->cpu_good_time * rate + USEC_PER_SEC - 1;
|
||||||
do_div(ticks, USEC_PER_SEC);
|
do_div(ticks, USEC_PER_SEC);
|
||||||
tegra_pmc_writel(ticks, PMC_CPUPWRGOOD_TIMER);
|
tegra_pmc_writel(pmc, ticks, PMC_CPUPWRGOOD_TIMER);
|
||||||
|
|
||||||
ticks = pmc->cpu_off_time * rate + USEC_PER_SEC - 1;
|
ticks = pmc->cpu_off_time * rate + USEC_PER_SEC - 1;
|
||||||
do_div(ticks, USEC_PER_SEC);
|
do_div(ticks, USEC_PER_SEC);
|
||||||
tegra_pmc_writel(ticks, PMC_CPUPWROFF_TIMER);
|
tegra_pmc_writel(pmc, ticks, PMC_CPUPWROFF_TIMER);
|
||||||
|
|
||||||
wmb();
|
wmb();
|
||||||
|
|
||||||
pmc->rate = rate;
|
pmc->rate = rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = tegra_pmc_readl(PMC_CNTRL);
|
value = tegra_pmc_readl(pmc, PMC_CNTRL);
|
||||||
value &= ~PMC_CNTRL_SIDE_EFFECT_LP0;
|
value &= ~PMC_CNTRL_SIDE_EFFECT_LP0;
|
||||||
value |= PMC_CNTRL_CPU_PWRREQ_OE;
|
value |= PMC_CNTRL_CPU_PWRREQ_OE;
|
||||||
tegra_pmc_writel(value, PMC_CNTRL);
|
tegra_pmc_writel(pmc, value, PMC_CNTRL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1438,13 +1459,13 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
|
|||||||
if (of_property_read_u32(np, "nvidia,pinmux-id", &pinmux))
|
if (of_property_read_u32(np, "nvidia,pinmux-id", &pinmux))
|
||||||
pinmux = 0;
|
pinmux = 0;
|
||||||
|
|
||||||
value = tegra_pmc_readl(PMC_SENSOR_CTRL);
|
value = tegra_pmc_readl(pmc, PMC_SENSOR_CTRL);
|
||||||
value |= PMC_SENSOR_CTRL_SCRATCH_WRITE;
|
value |= PMC_SENSOR_CTRL_SCRATCH_WRITE;
|
||||||
tegra_pmc_writel(value, PMC_SENSOR_CTRL);
|
tegra_pmc_writel(pmc, value, PMC_SENSOR_CTRL);
|
||||||
|
|
||||||
value = (reg_data << PMC_SCRATCH54_DATA_SHIFT) |
|
value = (reg_data << PMC_SCRATCH54_DATA_SHIFT) |
|
||||||
(reg_addr << PMC_SCRATCH54_ADDR_SHIFT);
|
(reg_addr << PMC_SCRATCH54_ADDR_SHIFT);
|
||||||
tegra_pmc_writel(value, PMC_SCRATCH54);
|
tegra_pmc_writel(pmc, value, PMC_SCRATCH54);
|
||||||
|
|
||||||
value = PMC_SCRATCH55_RESET_TEGRA;
|
value = PMC_SCRATCH55_RESET_TEGRA;
|
||||||
value |= ctrl_id << PMC_SCRATCH55_CNTRL_ID_SHIFT;
|
value |= ctrl_id << PMC_SCRATCH55_CNTRL_ID_SHIFT;
|
||||||
@ -1462,11 +1483,11 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
|
|||||||
|
|
||||||
value |= checksum << PMC_SCRATCH55_CHECKSUM_SHIFT;
|
value |= checksum << PMC_SCRATCH55_CHECKSUM_SHIFT;
|
||||||
|
|
||||||
tegra_pmc_writel(value, PMC_SCRATCH55);
|
tegra_pmc_writel(pmc, value, PMC_SCRATCH55);
|
||||||
|
|
||||||
value = tegra_pmc_readl(PMC_SENSOR_CTRL);
|
value = tegra_pmc_readl(pmc, PMC_SENSOR_CTRL);
|
||||||
value |= PMC_SENSOR_CTRL_ENABLE_RST;
|
value |= PMC_SENSOR_CTRL_ENABLE_RST;
|
||||||
tegra_pmc_writel(value, PMC_SENSOR_CTRL);
|
tegra_pmc_writel(pmc, value, PMC_SENSOR_CTRL);
|
||||||
|
|
||||||
dev_info(pmc->dev, "emergency thermal reset enabled\n");
|
dev_info(pmc->dev, "emergency thermal reset enabled\n");
|
||||||
|
|
||||||
@ -1476,12 +1497,16 @@ out:
|
|||||||
|
|
||||||
static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev)
|
static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev)
|
||||||
{
|
{
|
||||||
|
struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
|
||||||
|
|
||||||
return pmc->soc->num_io_pads;
|
return pmc->soc->num_io_pads;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *tegra_io_pad_pinctrl_get_group_name(
|
static const char *tegra_io_pad_pinctrl_get_group_name(
|
||||||
struct pinctrl_dev *pctl, unsigned int group)
|
struct pinctrl_dev *pctl, unsigned int group)
|
||||||
{
|
{
|
||||||
|
struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl);
|
||||||
|
|
||||||
return pmc->soc->io_pads[group].name;
|
return pmc->soc->io_pads[group].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1490,6 +1515,8 @@ static int tegra_io_pad_pinctrl_get_group_pins(struct pinctrl_dev *pctl_dev,
|
|||||||
const unsigned int **pins,
|
const unsigned int **pins,
|
||||||
unsigned int *num_pins)
|
unsigned int *num_pins)
|
||||||
{
|
{
|
||||||
|
struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
|
||||||
|
|
||||||
*pins = &pmc->soc->io_pads[group].id;
|
*pins = &pmc->soc->io_pads[group].id;
|
||||||
*num_pins = 1;
|
*num_pins = 1;
|
||||||
return 0;
|
return 0;
|
||||||
@ -1506,23 +1533,25 @@ static const struct pinctrl_ops tegra_io_pad_pinctrl_ops = {
|
|||||||
static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev,
|
static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev,
|
||||||
unsigned int pin, unsigned long *config)
|
unsigned int pin, unsigned long *config)
|
||||||
{
|
{
|
||||||
const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
|
|
||||||
enum pin_config_param param = pinconf_to_config_param(*config);
|
enum pin_config_param param = pinconf_to_config_param(*config);
|
||||||
|
struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
|
||||||
|
const struct tegra_io_pad_soc *pad;
|
||||||
int ret;
|
int ret;
|
||||||
u32 arg;
|
u32 arg;
|
||||||
|
|
||||||
|
pad = tegra_io_pad_find(pmc, pin);
|
||||||
if (!pad)
|
if (!pad)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case PIN_CONFIG_POWER_SOURCE:
|
case PIN_CONFIG_POWER_SOURCE:
|
||||||
ret = tegra_io_pad_get_voltage(pad->id);
|
ret = tegra_io_pad_get_voltage(pmc, pad->id);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
arg = ret;
|
arg = ret;
|
||||||
break;
|
break;
|
||||||
case PIN_CONFIG_LOW_POWER_MODE:
|
case PIN_CONFIG_LOW_POWER_MODE:
|
||||||
ret = tegra_io_pad_is_powered(pad->id);
|
ret = tegra_io_pad_is_powered(pmc, pad->id);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
arg = !ret;
|
arg = !ret;
|
||||||
@ -1540,12 +1569,14 @@ static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev,
|
|||||||
unsigned int pin, unsigned long *configs,
|
unsigned int pin, unsigned long *configs,
|
||||||
unsigned int num_configs)
|
unsigned int num_configs)
|
||||||
{
|
{
|
||||||
const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin);
|
struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
|
||||||
|
const struct tegra_io_pad_soc *pad;
|
||||||
enum pin_config_param param;
|
enum pin_config_param param;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int err;
|
int err;
|
||||||
u32 arg;
|
u32 arg;
|
||||||
|
|
||||||
|
pad = tegra_io_pad_find(pmc, pin);
|
||||||
if (!pad)
|
if (!pad)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -1566,7 +1597,7 @@ static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev,
|
|||||||
if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 &&
|
if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 &&
|
||||||
arg != TEGRA_IO_PAD_VOLTAGE_3V3)
|
arg != TEGRA_IO_PAD_VOLTAGE_3V3)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
err = tegra_io_pad_set_voltage(pad->id, arg);
|
err = tegra_io_pad_set_voltage(pmc, pad->id, arg);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
break;
|
break;
|
||||||
@ -1615,7 +1646,7 @@ static ssize_t reset_reason_show(struct device *dev,
|
|||||||
{
|
{
|
||||||
u32 value, rst_src;
|
u32 value, rst_src;
|
||||||
|
|
||||||
value = tegra_pmc_readl(pmc->soc->regs->rst_status);
|
value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
|
||||||
rst_src = (value & pmc->soc->regs->rst_source_mask) >>
|
rst_src = (value & pmc->soc->regs->rst_source_mask) >>
|
||||||
pmc->soc->regs->rst_source_shift;
|
pmc->soc->regs->rst_source_shift;
|
||||||
|
|
||||||
@ -1629,7 +1660,7 @@ static ssize_t reset_level_show(struct device *dev,
|
|||||||
{
|
{
|
||||||
u32 value, rst_lvl;
|
u32 value, rst_lvl;
|
||||||
|
|
||||||
value = tegra_pmc_readl(pmc->soc->regs->rst_status);
|
value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
|
||||||
rst_lvl = (value & pmc->soc->regs->rst_level_mask) >>
|
rst_lvl = (value & pmc->soc->regs->rst_level_mask) >>
|
||||||
pmc->soc->regs->rst_level_shift;
|
pmc->soc->regs->rst_level_shift;
|
||||||
|
|
||||||
@ -1926,6 +1957,8 @@ static int tegra_pmc_probe(struct platform_device *pdev)
|
|||||||
pmc->base = base;
|
pmc->base = base;
|
||||||
mutex_unlock(&pmc->powergates_lock);
|
mutex_unlock(&pmc->powergates_lock);
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, pmc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cleanup_restart_handler:
|
cleanup_restart_handler:
|
||||||
@ -1938,14 +1971,18 @@ cleanup_debugfs:
|
|||||||
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
|
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
|
||||||
static int tegra_pmc_suspend(struct device *dev)
|
static int tegra_pmc_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
|
struct tegra_pmc *pmc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
tegra_pmc_writel(pmc, virt_to_phys(tegra_resume), PMC_SCRATCH41);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_pmc_resume(struct device *dev)
|
static int tegra_pmc_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
tegra_pmc_writel(0x0, PMC_SCRATCH41);
|
struct tegra_pmc *pmc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
tegra_pmc_writel(pmc, 0x0, PMC_SCRATCH41);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1982,11 +2019,11 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc)
|
|||||||
u32 value;
|
u32 value;
|
||||||
|
|
||||||
/* Always enable CPU power request */
|
/* Always enable CPU power request */
|
||||||
value = tegra_pmc_readl(PMC_CNTRL);
|
value = tegra_pmc_readl(pmc, PMC_CNTRL);
|
||||||
value |= PMC_CNTRL_CPU_PWRREQ_OE;
|
value |= PMC_CNTRL_CPU_PWRREQ_OE;
|
||||||
tegra_pmc_writel(value, PMC_CNTRL);
|
tegra_pmc_writel(pmc, value, PMC_CNTRL);
|
||||||
|
|
||||||
value = tegra_pmc_readl(PMC_CNTRL);
|
value = tegra_pmc_readl(pmc, PMC_CNTRL);
|
||||||
|
|
||||||
if (pmc->sysclkreq_high)
|
if (pmc->sysclkreq_high)
|
||||||
value &= ~PMC_CNTRL_SYSCLK_POLARITY;
|
value &= ~PMC_CNTRL_SYSCLK_POLARITY;
|
||||||
@ -1994,12 +2031,12 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc)
|
|||||||
value |= PMC_CNTRL_SYSCLK_POLARITY;
|
value |= PMC_CNTRL_SYSCLK_POLARITY;
|
||||||
|
|
||||||
/* configure the output polarity while the request is tristated */
|
/* configure the output polarity while the request is tristated */
|
||||||
tegra_pmc_writel(value, PMC_CNTRL);
|
tegra_pmc_writel(pmc, value, PMC_CNTRL);
|
||||||
|
|
||||||
/* now enable the request */
|
/* now enable the request */
|
||||||
value = tegra_pmc_readl(PMC_CNTRL);
|
value = tegra_pmc_readl(pmc, PMC_CNTRL);
|
||||||
value |= PMC_CNTRL_SYSCLK_OE;
|
value |= PMC_CNTRL_SYSCLK_OE;
|
||||||
tegra_pmc_writel(value, PMC_CNTRL);
|
tegra_pmc_writel(pmc, value, PMC_CNTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
|
static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
|
||||||
@ -2008,14 +2045,14 @@ static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
|
|||||||
{
|
{
|
||||||
u32 value;
|
u32 value;
|
||||||
|
|
||||||
value = tegra_pmc_readl(PMC_CNTRL);
|
value = tegra_pmc_readl(pmc, PMC_CNTRL);
|
||||||
|
|
||||||
if (invert)
|
if (invert)
|
||||||
value |= PMC_CNTRL_INTR_POLARITY;
|
value |= PMC_CNTRL_INTR_POLARITY;
|
||||||
else
|
else
|
||||||
value &= ~PMC_CNTRL_INTR_POLARITY;
|
value &= ~PMC_CNTRL_INTR_POLARITY;
|
||||||
|
|
||||||
tegra_pmc_writel(value, PMC_CNTRL);
|
tegra_pmc_writel(pmc, value, PMC_CNTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct tegra_pmc_soc tegra20_pmc_soc = {
|
static const struct tegra_pmc_soc tegra20_pmc_soc = {
|
||||||
@ -2419,7 +2456,7 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
|
|||||||
|
|
||||||
index = of_property_match_string(np, "reg-names", "wake");
|
index = of_property_match_string(np, "reg-names", "wake");
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
pr_err("failed to find PMC wake registers\n");
|
dev_err(pmc->dev, "failed to find PMC wake registers\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2427,7 +2464,7 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
|
|||||||
|
|
||||||
wake = ioremap_nocache(regs.start, resource_size(®s));
|
wake = ioremap_nocache(regs.start, resource_size(®s));
|
||||||
if (!wake) {
|
if (!wake) {
|
||||||
pr_err("failed to map PMC wake registers\n");
|
dev_err(pmc->dev, "failed to map PMC wake registers\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user