summaryrefslogtreecommitdiff
path: root/power/rk3399.c
diff options
context:
space:
mode:
Diffstat (limited to 'power/rk3399.c')
-rw-r--r--power/rk3399.c31
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: