]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
soc/tegra: pmc: Implement acquire/release for resets
authorThierry Reding <treding@nvidia.com>
Mon, 18 Feb 2019 16:36:43 +0000 (17:36 +0100)
committerThierry Reding <treding@nvidia.com>
Fri, 22 Mar 2019 13:05:07 +0000 (14:05 +0100)
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>
drivers/soc/tegra/pmc.c

index 0df25851869365e4dccd0e10f8042f54d65e99c4..0c5f79528e5f7f202518d020a12729e869104554 100644 (file)
@@ -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_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);
-       else
+       } else {
                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);
+       }
 
        return err;
 }