summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-06-26 16:16:59 -0700
committerGerrit <chrome-bot@google.com>2012-06-26 17:33:53 -0700
commit55073a0a84e9d52cda08233ec842f7a5d9113877 (patch)
tree219505a646b06f09ced385824cd9bfe8100f918f
parentb73bfcaa922905a668ff03e8969ce3e96f0a9283 (diff)
downloadchrome-ec-55073a0a84e9d52cda08233ec842f7a5d9113877.tar.gz
Power on AP every EC reboot.
Needed for EC software sync so the AP can verify the EC's RW code and tell the EC to jump to RW when necessary. If the AP then decides it doesn't need to stay booted, the AP can shut back down. (The AP verifying the EC's code and/or shutting back down are NOT part of this CL...) Also add a Power+Refresh+DownArrow key combination which causes the EC to reset WITHOUT powering on the AP; this will be needed for debugging the AP power-on sequence. BUG=chrome-os-partner:10892 TEST=manual 1) power+refresh+down -> ec reboots, system stays down 2) power+refresh+esc -> ec reboots, system to recovery 3) power+refresh -> ec reboots, system boots 4) hibernate, then open lid -> ec reboots, system boots 5) hibernate, then power button -> ec reboots, system boots 6) yank battery, then reconnect -> ec reboots, system boots 7) reboot ec -> system boots 8) 'sysjump A' when AP already booted -> system stays on 9) 'sysjump A' when AP shut down -> system boots Change-Id: I65d2f7d9cca3acb84b76302cdcd8c8a800f03253 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/26158
-rw-r--r--chip/lm4/power_button.c118
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