Commit 7fe5719b authored by Thierry Reding's avatar Thierry Reding

soc/tegra: pmc: Implement acquire/release for resets

By implementing the acquire/release protocol, the resets can be shared
with other drivers that also adhere to this protocol. This will be used
for example by the SOR driver to put hardware into a known good state,
irrespective of whether or not the power domain can be reset.
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 41c4f599
...@@ -656,10 +656,15 @@ static int tegra_genpd_power_on(struct generic_pm_domain *domain) ...@@ -656,10 +656,15 @@ static int tegra_genpd_power_on(struct generic_pm_domain *domain)
int err; int err;
err = tegra_powergate_power_up(pg, true); err = tegra_powergate_power_up(pg, true);
if (err) if (err) {
dev_err(dev, "failed to turn on PM domain %s: %d\n", dev_err(dev, "failed to turn on PM domain %s: %d\n",
pg->genpd.name, err); pg->genpd.name, err);
goto out;
}
reset_control_release(pg->reset);
out:
return err; return err;
} }
...@@ -669,10 +674,18 @@ static int tegra_genpd_power_off(struct generic_pm_domain *domain) ...@@ -669,10 +674,18 @@ static int tegra_genpd_power_off(struct generic_pm_domain *domain)
struct device *dev = pg->pmc->dev; struct device *dev = pg->pmc->dev;
int err; int err;
err = reset_control_acquire(pg->reset);
if (err < 0) {
pr_err("failed to acquire resets: %d\n", err);
return err;
}
err = tegra_powergate_power_down(pg); err = tegra_powergate_power_down(pg);
if (err) if (err) {
dev_err(dev, "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);
reset_control_release(pg->reset);
}
return err; return err;
} }
...@@ -937,20 +950,34 @@ static int tegra_powergate_of_get_resets(struct tegra_powergate *pg, ...@@ -937,20 +950,34 @@ static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
struct device *dev = pg->pmc->dev; 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_released(np);
if (IS_ERR(pg->reset)) { if (IS_ERR(pg->reset)) {
err = PTR_ERR(pg->reset); err = PTR_ERR(pg->reset);
dev_err(dev, "failed to get device resets: %d\n", err); dev_err(dev, "failed to get device resets: %d\n", err);
return err; return err;
} }
if (off) err = reset_control_acquire(pg->reset);
if (err < 0) {
pr_err("failed to acquire resets: %d\n", err);
goto out;
}
if (off) {
err = reset_control_assert(pg->reset); err = reset_control_assert(pg->reset);
else } else {
err = reset_control_deassert(pg->reset); err = reset_control_deassert(pg->reset);
if (err < 0)
goto out;
if (err) reset_control_release(pg->reset);
}
out:
if (err) {
reset_control_release(pg->reset);
reset_control_put(pg->reset); reset_control_put(pg->reset);
}
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment