oak: power: change power state while losting POWER_GOOD signal

Check IN_POWER_GOOD signal in S0 and go to S3 if IN_POWER_GOOD is lost.
Finally it will go to S5(G3).
Check suspend and power good signal after POWER_DEBOUNCE_TIME to
avoid transient state.

BRANCH=none
BUG=none
TEST=manual
  Test power related commands such as "shutdown -P now" or "apshutdown".

Change-Id: Ia06fc7d8334c0dfbb0263474f57e4dca7313d331
Signed-off-by: YH Huang <yh.huang@mediatek.com>
Reviewed-on: https://chromium-review.googlesource.com/282680
Reviewed-by: Rong Chang <rongchang@chromium.org>
This commit is contained in:
YH Huang
2015-07-01 19:45:09 +08:00
committed by ChromeOS Commit Bot
parent d3cd34d8c5
commit e58a913bcc

View File

@@ -58,9 +58,9 @@
#define PMIC_PWRON_DEBOUNCE_TIME (60 * MSEC)
/*
* The suspend signal from SoC should be kept at least 50ms.
* The power signal from SoC should be kept at least 50ms.
*/
#define SUSPEND_DEBOUNCE_TIME (50 * MSEC)
#define POWER_DEBOUNCE_TIME (50 * MSEC)
/*
* The time to bootup the PMIC from power-off to power-on.
@@ -167,6 +167,60 @@ enum blacklight_override_t {
/* Forward declaration */
static void chipset_turn_off_power_rails(void);
/**
* Check the suspend signal is on after POWER_DEBOUNCE_TIME to avoid transient state.
*
* @return non-zero if SUSPEND is asserted.
*/
static int is_suspend_asserted(void)
{
if (power_get_signals() & IN_SUSPEND)
usleep(POWER_DEBOUNCE_TIME);
return power_get_signals() & IN_SUSPEND;
}
/**
* Check the suspend signal is off after POWER_DEBOUNCE_TIME to avoid transient state.
*
* @return non-zero if SUSPEND is deasserted.
*/
static int is_suspend_deasserted(void)
{
if (!(power_get_signals() & IN_SUSPEND))
usleep(POWER_DEBOUNCE_TIME);
return !(power_get_signals() & IN_SUSPEND);
}
/**
* Check power good signal is on after POWER_DEBOUNCE_TIME to avoid transient state.
*
* @return non-zero if POWER_GOOD is asserted.
*/
static int is_power_good_asserted(void)
{
if (!gpio_get_level(GPIO_SYSTEM_POWER_H))
return 0;
else if (power_get_signals() & IN_POWER_GOOD)
usleep(POWER_DEBOUNCE_TIME);
return power_get_signals() & IN_POWER_GOOD;
}
/**
* Check power good signal is off after POWER_DEBOUNCE_TIME to avoid transient state.
*
* @return non-zero if POWER_GOOD is deasserted.
*/
static int is_power_good_deasserted(void)
{
if (!(power_get_signals() & IN_POWER_GOOD))
usleep(POWER_DEBOUNCE_TIME);
return !(power_get_signals() & IN_POWER_GOOD);
}
/**
* Set the system power signal.
*
@@ -288,6 +342,12 @@ static int check_for_power_off_event(void)
power_button_was_pressed = pressed;
/* POWER_GOOD released by AP : shutdown immediate */
if (is_power_good_deasserted()) {
CPRINTS("POWER_GOOD is lost");
return POWER_OFF_BY_POWER_GOOD_LOST;
}
return POWER_OFF_CANCEL;
}
@@ -346,7 +406,7 @@ enum power_state power_chipset_init(void)
init_power_state = POWER_G3;
} else {
/* In the SYSJUMP case, we check if the AP is on */
if (power_get_signals() & IN_POWER_GOOD) {
if (is_power_good_asserted()) {
CPRINTS("SOC ON\n");
init_power_state = POWER_S0;
disable_sleep(SLEEP_MASK_AP_RUN);
@@ -400,6 +460,10 @@ void chipset_force_shutdown(void)
*/
static void power_off(void)
{
/* Check the power off status */
if (!gpio_get_level(GPIO_SYSTEM_POWER_H))
return;
/* Call hooks before we drop power rails */
hook_notify(HOOK_CHIPSET_SHUTDOWN);
/* switch off all rails */
@@ -409,6 +473,9 @@ static void power_off(void)
gpio_set_flags(power_signal_list[MTK_SUSPEND_ASSERTED].gpio,
GPIO_INPUT);
/* Change EC_INT to low */
gpio_set_level(GPIO_EC_INT, 0);
lid_opened = 0;
enable_sleep(SLEEP_MASK_AP_RUN);
#ifdef HAS_TASK_POWERLED
@@ -432,7 +499,7 @@ static int check_for_power_on_event(void)
ap_off_flag = system_get_reset_flags() & RESET_FLAG_AP_OFF;
system_clear_reset_flags(RESET_FLAG_AP_OFF);
/* check if system is already ON */
if (power_get_signals() & IN_POWER_GOOD) {
if (is_power_good_asserted()) {
if (ap_off_flag) {
CPRINTS("system is on, but RESET_FLAG_AP_OFF is on");
return POWER_ON_CANCEL;
@@ -635,9 +702,10 @@ enum power_state power_handle_state(enum power_state state)
return POWER_S5;
case POWER_S3:
if (!(power_get_signals() & IN_POWER_GOOD))
if (is_power_good_deasserted()) {
power_off();
return POWER_S3S5;
else if (!(power_get_signals() & IN_SUSPEND))
} else if (is_suspend_deasserted())
return POWER_S3S0;
return state;
@@ -654,16 +722,8 @@ enum power_state power_handle_state(enum power_state state)
CPRINTS("power off %d", value);
power_off();
return POWER_S0S3;
} else if (power_get_signals() & IN_SUSPEND) {
/*
* add susuend signal debounce:
* check suspend signal after 50ms, to avoid
* transient state during SoC boot up.
*/
usleep(SUSPEND_DEBOUNCE_TIME);
if (power_get_signals() & IN_SUSPEND)
return POWER_S0S3;
}
} else if (is_suspend_asserted())
return POWER_S0S3;
return state;
case POWER_S0S3: