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: Thierry Reding <treding@nvidia.com>
This commit is contained in:
Thierry Reding 2019-02-18 17:36:43 +01:00
Родитель 41c4f5996b
Коммит 7fe5719b43
1 изменённых файлов: 35 добавлений и 8 удалений

Просмотреть файл

@ -656,10 +656,15 @@ static int tegra_genpd_power_on(struct generic_pm_domain *domain)
int err;
err = tegra_powergate_power_up(pg, true);
if (err)
if (err) {
dev_err(dev, "failed to turn on PM domain %s: %d\n",
pg->genpd.name, err);
goto out;
}
reset_control_release(pg->reset);
out:
return err;
}
@ -669,10 +674,18 @@ static int tegra_genpd_power_off(struct generic_pm_domain *domain)
struct device *dev = pg->pmc->dev;
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);
if (err)
if (err) {
dev_err(dev, "failed to turn off PM domain %s: %d\n",
pg->genpd.name, err);
reset_control_release(pg->reset);
}
return err;
}
@ -937,20 +950,34 @@ static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
struct device *dev = pg->pmc->dev;
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)) {
err = PTR_ERR(pg->reset);
dev_err(dev, "failed to get device resets: %d\n", err);
return err;
}
if (off)
err = reset_control_assert(pg->reset);
else
err = reset_control_deassert(pg->reset);
err = reset_control_acquire(pg->reset);
if (err < 0) {
pr_err("failed to acquire resets: %d\n", err);
goto out;
}
if (err)
if (off) {
err = reset_control_assert(pg->reset);
} else {
err = reset_control_deassert(pg->reset);
if (err < 0)
goto out;
reset_control_release(pg->reset);
}
out:
if (err) {
reset_control_release(pg->reset);
reset_control_put(pg->reset);
}
return err;
}