aboutsummaryrefslogtreecommitdiff
path: root/drivers/soc/tegra/pmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc/tegra/pmc.c')
-rw-r--r--drivers/soc/tegra/pmc.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index ceceb1709e0a..2ace21db4ae8 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -429,6 +429,9 @@ struct tegra_pmc {
struct irq_chip irq;
struct notifier_block clk_nb;
+
+ bool core_domain_state_synced;
+ bool core_domain_registered;
};
static struct tegra_pmc *pmc = &(struct tegra_pmc) {
@@ -1303,6 +1306,11 @@ free_mem:
return err;
}
+bool tegra_pmc_core_domain_state_synced(void)
+{
+ return pmc->core_domain_state_synced;
+}
+
static int
tegra_pmc_core_pd_set_performance_state(struct generic_pm_domain *genpd,
unsigned int level)
@@ -1370,6 +1378,8 @@ static int tegra_pmc_core_pd_add(struct tegra_pmc *pmc, struct device_node *np)
goto remove_genpd;
}
+ pmc->core_domain_registered = true;
+
return 0;
remove_genpd:
@@ -3782,6 +3792,29 @@ static const struct of_device_id tegra_pmc_match[] = {
{ }
};
+static void tegra_pmc_sync_state(struct device *dev)
+{
+ int err;
+
+ /*
+ * Older device-trees don't have core PD, and thus, there are
+ * no dependencies that will block the state syncing. We shouldn't
+ * mark the domain as synced in this case.
+ */
+ if (!pmc->core_domain_registered)
+ return;
+
+ pmc->core_domain_state_synced = true;
+
+ /* this is a no-op if core regulator isn't used */
+ mutex_lock(&pmc->powergates_lock);
+ err = dev_pm_opp_sync_regulators(dev);
+ mutex_unlock(&pmc->powergates_lock);
+
+ if (err)
+ dev_err(dev, "failed to sync regulators: %d\n", err);
+}
+
static struct platform_driver tegra_pmc_driver = {
.driver = {
.name = "tegra-pmc",
@@ -3790,6 +3823,7 @@ static struct platform_driver tegra_pmc_driver = {
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
.pm = &tegra_pmc_pm_ops,
#endif
+ .sync_state = tegra_pmc_sync_state,
},
.probe = tegra_pmc_probe,
};