diff options
Diffstat (limited to 'chip')
-rw-r--r-- | chip/lm4/power_button.c | 118 |
1 files changed, 61 insertions, 57 deletions
diff --git a/chip/lm4/power_button.c b/chip/lm4/power_button.c index aa69d2c231..0ca733597b 100644 --- a/chip/lm4/power_button.c +++ b/chip/lm4/power_button.c @@ -55,19 +55,26 @@ #define LID_DEBOUNCE_US 30000 /* Debounce time for lid switch */ enum power_button_state { - PWRBTN_STATE_IDLE = 0, /* Button up; state machine idle */ - PWRBTN_STATE_PRESSED, /* Button pressed; debouncing done */ - PWRBTN_STATE_T0, /* Button down, chipset on; sending - * initial short pulse */ - PWRBTN_STATE_T1, /* Button down, chipset on; delaying - * until we should reassert signal */ - PWRBTN_STATE_HELD, /* Button down, signal asserted to - * chipset */ - PWRBTN_STATE_LID_OPEN, /* Force pulse due to lid-open event */ - PWRBTN_STATE_RELEASED, /* Button released; debouncing done */ - PWRBTN_STATE_EAT_RELEASE, /* Ignore next button release */ - PWRBTN_STATE_BOOT_RECOVERY, /* Forced pulse at EC boot */ - PWRBTN_STATE_WAS_OFF, /* Chipset was off; stretching pulse */ + /* Button up; state machine idle */ + PWRBTN_STATE_IDLE = 0, + /* Button pressed; debouncing done */ + PWRBTN_STATE_PRESSED, + /* Button down, chipset on; sending initial short pulse */ + PWRBTN_STATE_T0, + /* Button down, chipset on; delaying until we should reassert signal */ + PWRBTN_STATE_T1, + /* Button down, signal asserted to chipset */ + PWRBTN_STATE_HELD, + /* Force pulse due to lid-open event */ + PWRBTN_STATE_LID_OPEN, + /* Button released; debouncing done */ + PWRBTN_STATE_RELEASED, + /* Ignore next button release */ + PWRBTN_STATE_EAT_RELEASE, + /* Forced pulse at EC boot due to keyboard controlled reset */ + PWRBTN_STATE_BOOT_KB_RESET, + /* Power button pressed when chipset was off; stretching pulse */ + PWRBTN_STATE_WAS_OFF, }; static enum power_button_state pwrbtn_state = PWRBTN_STATE_IDLE; @@ -252,7 +259,7 @@ static void lid_switch_close(uint64_t tnow) /* Handle debounced power button changing state */ static void power_button_changed(uint64_t tnow) { - if (pwrbtn_state == PWRBTN_STATE_BOOT_RECOVERY || + if (pwrbtn_state == PWRBTN_STATE_BOOT_KB_RESET || pwrbtn_state == PWRBTN_STATE_LID_OPEN || pwrbtn_state == PWRBTN_STATE_WAS_OFF) { /* Ignore all power button changes during an initial pulse */ @@ -288,72 +295,69 @@ static void lid_switch_changed(uint64_t tnow) lid_switch_close(tnow); } - /* Set initial power button state */ static void set_initial_pwrbtn_state(void) { - debounced_power_pressed = get_power_button_pressed(); - - if (system_get_reset_cause() == SYSTEM_RESET_RESET_PIN) { - /* Reset triggered by keyboard-controlled reset, so override - * the power button signal to the PCH. */ - if (keyboard_scan_recovery_pressed()) { - /* In recovery mode, so send a power button pulse to - * the PCH so it powers on. */ - CPRINTF("[%T PB init-recovery]\n"); - chipset_exit_hard_off(); + if (system_jumped_to_this_image() && + chipset_in_state(CHIPSET_STATE_ON)) { + /* + * Jumped to this image while the chipset was already on, so + * simply reflect the actual power button state. + */ + if (get_power_button_pressed()) { + *memmap_switches |= EC_SWITCH_POWER_BUTTON_PRESSED; set_pwrbtn_to_pch(0); - pwrbtn_state = PWRBTN_STATE_BOOT_RECOVERY; - tnext_state = get_time().val + PWRBTN_INITIAL_US; - } else { - /* Keyboard-controlled reset, so don't let the PCH see - * that the power button was pressed. Otherwise, it - * might power on. */ - CPRINTF("[%T PB init-reset]\n"); - set_pwrbtn_to_pch(1); - if (get_power_button_pressed()) - pwrbtn_state = PWRBTN_STATE_EAT_RELEASE; - else - pwrbtn_state = PWRBTN_STATE_IDLE; } - } else if (system_get_reset_cause() == SYSTEM_RESET_WAKE_PIN && - debounced_lid_open == 1) { - /* Reset triggered by wake pin and lid is open, so power on the - * system. Note that on EVT+, if the system is off, lid is - * open, and you plug it in, it'll turn on due to AC detect. */ - CPRINTF("[%T PB init-hib-wake]\n"); - chipset_exit_hard_off(); - set_pwrbtn_to_pch(0); + } else if (system_get_reset_cause() == SYSTEM_RESET_RESET_PIN && + keyboard_scan_get_boot_key() == BOOT_KEY_DOWN_ARROW) { + /* + * Reset triggered by keyboard-controlled reset, and down-arrow + * was held down. Leave the main processor off. This is a + * fail-safe combination for debugging failures booting the + * main processor. + * + * Don't let the PCH see that the power button was pressed. + * Otherwise, it might power on. + */ + CPRINTF("[%T PB init-off]\n"); + set_pwrbtn_to_pch(1); if (get_power_button_pressed()) - pwrbtn_state = PWRBTN_STATE_WAS_OFF; + pwrbtn_state = PWRBTN_STATE_EAT_RELEASE; else - pwrbtn_state = PWRBTN_STATE_LID_OPEN; - tnext_state = get_time().val + PWRBTN_INITIAL_US; + pwrbtn_state = PWRBTN_STATE_IDLE; } else { - /* Copy initial power button state to PCH and memory-mapped - * switch positions. */ - set_pwrbtn_to_pch(get_power_button_pressed() ? 0 : 1); + /* + * All other EC reset conditions power on the main processor so + * it can verify the EC. + */ + CPRINTF("[%T PB init-on]\n"); + chipset_exit_hard_off(); + set_pwrbtn_to_pch(0); + tnext_state = get_time().val + PWRBTN_INITIAL_US; + if (get_power_button_pressed()) { - /* Wake chipset if power button is pressed at boot */ - chipset_exit_hard_off(); *memmap_switches |= EC_SWITCH_POWER_BUTTON_PRESSED; + + if (system_get_reset_cause() == SYSTEM_RESET_RESET_PIN) + pwrbtn_state = PWRBTN_STATE_BOOT_KB_RESET; + else + pwrbtn_state = PWRBTN_STATE_WAS_OFF; + } else { + pwrbtn_state = PWRBTN_STATE_RELEASED; } } } - int power_ac_present(void) { return gpio_get_level(GPIO_AC_PRESENT); } - int power_lid_open_debounced(void) { return debounced_lid_open; } - /*****************************************************************************/ /* Task / state machine */ @@ -412,7 +416,7 @@ static void state_machine(uint64_t tnow) set_pwrbtn_to_pch(1); pwrbtn_state = PWRBTN_STATE_IDLE; break; - case PWRBTN_STATE_BOOT_RECOVERY: + case PWRBTN_STATE_BOOT_KB_RESET: /* Initial forced pulse is done. Ignore the actual power * button until it's released, so that holding down the * recovery combination doesn't cause the chipset to shut back |