power: rk3399: Debounce PGOOD_AP signal

PGOOD_AP may go low for a period < 100ms during regulator output voltage
transitions, so ignore such pulses.

BRANCH=None
BUG=chrome-os-partner:54814
TEST=On kevin, verify suspend / resume succeeds for 10 cycles.

Change-Id: I5b6240a570472e1ea74de6e5f2341472ea7afe6b
Reviewed-on: https://chromium-review.googlesource.com/374524
Commit-Ready: Shawn N <shawnn@chromium.org>
Tested-by: Douglas Anderson <dianders@chromium.org>
Tested-by: Shunqian Zheng <zhengsq@rock-chips.com>
Tested-by: Shawn N <shawnn@chromium.org>
Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
This commit is contained in:
Shawn Nematbakhsh
2016-08-23 15:02:10 -07:00
committed by chrome-bot
parent 3071b82b58
commit 6fefca3d6a
3 changed files with 52 additions and 8 deletions

View File

@@ -68,7 +68,7 @@ uint32_t power_get_signals(void);
int power_has_signals(uint32_t want);
/**
* Wait for power input signals to be present
* Wait for power input signals to be present using default timeout
*
* @param want Mask of signals which must be present (one or more
* POWER_SIGNAL_MASK()s). If want=0, stops waiting for
@@ -78,6 +78,18 @@ int power_has_signals(uint32_t want);
*/
int power_wait_signals(uint32_t want);
/**
* Wait for power input signals to be present
*
* @param want Mask of signals which must be present (one or more
* POWER_SIGNAL_MASK()s). If want=0, stops waiting for
* signals.
* @param timeout Timeout in usec to wait for signals to be present.
* @return EC_SUCCESS when all inputs are present, or ERROR_TIMEOUT if timeout
* before reaching the desired state.
*/
int power_wait_signals_timeout(uint32_t want, int timeout);
/**
* Set the low-level power chipset state.
*

View File

@@ -133,17 +133,24 @@ int power_has_signals(uint32_t want)
}
int power_wait_signals(uint32_t want)
{
int ret = power_wait_signals_timeout(want, DEFAULT_TIMEOUT);
if (ret == EC_ERROR_TIMEOUT)
CPRINTS("power timeout on input; wanted 0x%04x, got 0x%04x",
want, in_signals & want);
return ret;
}
int power_wait_signals_timeout(uint32_t want, int timeout)
{
in_want = want;
if (!want)
return EC_SUCCESS;
while ((in_signals & in_want) != in_want) {
if (task_wait_event(DEFAULT_TIMEOUT) == TASK_EVENT_TIMER) {
if (task_wait_event(timeout) == TASK_EVENT_TIMER) {
power_update_signals();
CPRINTS("power timeout on input; "
"wanted 0x%04x, got 0x%04x",
in_want, in_signals & in_want);
return EC_ERROR_TIMEOUT;
}
/*

View File

@@ -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 ||
gpio_get_level(GPIO_AP_EC_S3_S0_L))
!(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 ||
!(power_get_signals() & IN_SUSPEND_DEASSERTED))
return POWER_S0S3;
break;
case POWER_G3S5: