@@ -1124,7 +1124,17 @@ static void genpd_sync_power_off(struct generic_pm_domain *genpd, bool use_lock,
{
struct gpd_link *link;
- if (!genpd_status_on(genpd) || genpd_is_always_on(genpd))
+ /*
+ * Give the power domain a chance to switch to the deepest state in
+ * case it's already off but in an intermediate low power state.
+ */
+ genpd->state_idx_saved = genpd->state_idx;
+
+ if (genpd_is_always_on(genpd))
+ return;
+
+ if (!genpd_status_on(genpd) &&
+ genpd->state_idx == (genpd->state_count - 1))
return;
if (genpd->suspended_count != genpd->device_count
@@ -1143,6 +1153,9 @@ static void genpd_sync_power_off(struct generic_pm_domain *genpd, bool use_lock,
if (_genpd_power_off(genpd, false))
return;
+ if (genpd->status == GENPD_STATE_OFF)
+ return;
+
genpd->status = GENPD_STATE_OFF;
list_for_each_entry(link, &genpd->child_links, child_node) {
@@ -1189,6 +1202,9 @@ static void genpd_sync_power_on(struct generic_pm_domain *genpd, bool use_lock,
}
_genpd_power_on(genpd, false);
+ /* restore save power domain state after resume */
+ genpd->state_idx = genpd->state_idx_saved;
+
genpd->status = GENPD_STATE_ON;
}
@@ -167,6 +167,7 @@ struct generic_pm_domain {
};
};
+ unsigned int state_idx_saved; /* saved power state for recovery after system suspend/resume */
};
static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)