diff options
Diffstat (limited to 'power/rk3399.c')
-rw-r--r-- | power/rk3399.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/power/rk3399.c b/power/rk3399.c index 76b012c548..58056b98dc 100644 --- a/power/rk3399.c +++ b/power/rk3399.c @@ -91,6 +91,12 @@ static void force_shutdown(void) } DECLARE_DEFERRED(force_shutdown); +/* + * Debounce PGOOD_AP if we lose it suddenly during S0, since output voltage + * transitions may cause spurious pulses. + */ +#define PGOOD_AP_DEBOUNCE_TIMEOUT (100 * MSEC) + enum power_state power_handle_state(enum power_state state) { static int sys_reset_needed; @@ -110,15 +116,34 @@ enum power_state power_handle_state(enum power_state state) case POWER_S3: if (!power_has_signals(IN_PGOOD_S3) || forcing_shutdown) return POWER_S3S5; - else if (!gpio_get_level(GPIO_AP_EC_S3_S0_L)) + else if (power_get_signals() & IN_SUSPEND_DEASSERTED) return POWER_S3S0; break; case POWER_S0: - if (!power_has_signals(IN_PGOOD_S0) || + if (!power_has_signals(IN_PGOOD_S3) || + forcing_shutdown || + !(power_get_signals() & IN_SUSPEND_DEASSERTED)) + return POWER_S0S3; + + /* + * Wait up to PGOOD_AP_DEBOUNCE_TIMEOUT for IN_PGOOD_AP to + * come back before transitioning back to S3. + */ + if (power_wait_signals_timeout(IN_PGOOD_AP, + PGOOD_AP_DEBOUNCE_TIMEOUT) + == EC_ERROR_TIMEOUT) + return POWER_S0S3; + + /* + * power_wait_signals_timeout() can block and consume task + * wake events, so re-verify the state of the world. + */ + if (!power_has_signals(IN_PGOOD_S3) || forcing_shutdown || - gpio_get_level(GPIO_AP_EC_S3_S0_L)) + !(power_get_signals() & IN_SUSPEND_DEASSERTED)) return POWER_S0S3; + break; case POWER_G3S5: |