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 @@ static int tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np) 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, }; diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h index 361cb64246f7..d186bccd125d 100644 --- a/include/soc/tegra/pmc.h +++ b/include/soc/tegra/pmc.h @@ -171,6 +171,8 @@ int tegra_io_rail_power_off(unsigned int id); void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode); void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode); +bool tegra_pmc_core_domain_state_synced(void); + #else static inline int tegra_powergate_power_on(unsigned int id) { @@ -227,6 +229,11 @@ static inline void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode) { } +static inline bool tegra_pmc_core_domain_state_synced(void) +{ + return false; +} + #endif /* CONFIG_SOC_TEGRA_PMC */ #if defined(CONFIG_SOC_TEGRA_PMC) && defined(CONFIG_PM_SLEEP)