summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@google.com>2018-12-21 15:03:01 -0800
committerchrome-bot <chrome-bot@chromium.org>2019-01-22 21:05:23 -0800
commitca8b915b59822f9d464862b599ade8e35712abc3 (patch)
treea4469987d5275d029217737e58bd6301c0130fd5
parent34ad90fb651e650f41194df4ff483af6daecd808 (diff)
downloadchrome-ec-ca8b915b59822f9d464862b599ade8e35712abc3.tar.gz
cr50: REFRESH+PWR combinatinon to enter recovery mode
Add support for entering recovery mode via the REFRESH_PWR key combination. This is needed on a platform with a closed source EC when the EC cannot be trusted to handle the normal ESC+REFRRESH+PWR combination. Add an interrupt handler for the RBOX key combo and when it is detected, generate an EC reset pulse via RBOX. The recovery state is latched into NVMEM so it can be queried by coreboot/verstage on the next boot. This change also ensures that all EC resets initiated by the Cr50 have a minimum pulse width of 30 ms to meet the EC requirement. BUG=b:122715254,b:119275910, BRANCH=cr50 TEST=make buildall. Verified boot to recovery mode screen after pressing REFRESH+PWR. Verified recovery mode entry from S0 and S5 states. Change-Id: I840ee1024bbfba00e47050eeb8b1ede244148c05 Signed-off-by: Duncan Laurie <dlaurie@google.com> Signed-off-by: Keith Short <keithshort@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1389061 Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
-rw-r--r--board/cr50/board.c53
-rw-r--r--board/cr50/recovery_button.c45
-rw-r--r--board/cr50/recovery_button.h17
3 files changed, 111 insertions, 4 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index ef8a91ec98..e984b9be04 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -24,6 +24,7 @@
#include "nvmem_vars.h"
#include "rbox.h"
#include "rdd.h"
+#include "recovery_button.h"
#include "registers.h"
#include "scratch_reg1.h"
#include "signed_header.h"
@@ -757,6 +758,16 @@ static void board_init(void)
bitbang_config.uart_in = ec_uart.producer.queue;
/*
+ * Enable interrupt handler for RBOX key combo so it can be used to
+ * store the recovery request.
+ */
+ if (board_uses_closed_source_set1()) {
+ /* Enable interrupt handler for reset button combo */
+ task_enable_irq(GC_IRQNUM_RBOX0_INTR_BUTTON_COMBO0_RDY_INT);
+ GWRITE_FIELD(RBOX, INT_ENABLE, INTR_BUTTON_COMBO0_RDY, 1);
+ }
+
+ /*
* Note that the AP, EC, and servo state machines do not have explicit
* init_xxx_state() functions, because they don't need to configure
* registers prior to starting their state machines. Their state
@@ -953,6 +964,27 @@ void board_reboot_ap(void)
}
/**
+ * Reboot the EC
+ */
+static void board_reboot_ec(void)
+{
+ assert_ec_rst();
+ deassert_ec_rst();
+}
+
+/*
+ * This interrupt handler will be called if the RBOX key combo is detected.
+ */
+static void key_combo0_irq(void)
+{
+ GWRITE_FIELD(RBOX, INT_STATE, INTR_BUTTON_COMBO0_RDY, 1);
+ recovery_button_record();
+ board_reboot_ec();
+ CPRINTS("Recovery Requested");
+}
+DECLARE_IRQ(GC_IRQNUM_RBOX0_INTR_BUTTON_COMBO0_RDY_INT, key_combo0_irq, 0);
+
+/**
* Console command to toggle system (AP) reset
*/
static int command_sys_rst(int argc, char **argv)
@@ -1039,13 +1071,28 @@ void assert_ec_rst(void)
wait_ec_rst(1);
}
-void deassert_ec_rst(void)
+
+static void deassert_ec_rst_now(void)
{
wait_ec_rst(0);
if (uart_bitbang_is_enabled())
task_enable_irq(bitbang_config.rx_irq);
}
+DECLARE_DEFERRED(deassert_ec_rst_now);
+
+void deassert_ec_rst(void)
+{
+ /*
+ * On closed source set1, the EC requires a minimum 30 ms pulse to
+ * properly reset. Ensure EC reset is never de-asesrted for less
+ * than this time.
+ */
+ if (board_uses_closed_source_set1())
+ hook_call_deferred(&deassert_ec_rst_now_data, 30 * MSEC);
+ else
+ deassert_ec_rst_now();
+}
int is_ec_rst_asserted(void)
{
@@ -1065,9 +1112,7 @@ static int command_ec_rst(int argc, char **argv)
if (!strcasecmp("pulse", argv[1])) {
ccprintf("Pulsing EC reset\n");
- assert_ec_rst();
- usleep(200);
- deassert_ec_rst();
+ board_reboot_ec();
} else if (parse_bool(argv[1], &val)) {
if (val)
assert_ec_rst();
diff --git a/board/cr50/recovery_button.c b/board/cr50/recovery_button.c
index af4d4d7c87..0ed4b78508 100644
--- a/board/cr50/recovery_button.c
+++ b/board/cr50/recovery_button.c
@@ -9,6 +9,8 @@
#include "console.h"
#include "extension.h"
#include "registers.h"
+#include "timer.h"
+#include "u2f_impl.h"
#include "util.h"
/*
@@ -20,12 +22,53 @@
*/
static uint8_t rec_btn_force_pressed;
+/*
+ * Timestamp of the most recent recovery button press
+ */
+static timestamp_t last_press;
+
+/* How long do we latch the last recovery button press */
+#define RECOVERY_BUTTON_TIMEOUT (10 * SECOND)
+
+void recovery_button_record(void)
+{
+ last_press = get_time();
+}
+
+/*
+ * Read the recovery button latched state and unconditionally clear the state.
+ *
+ * Returns 1 iff the recovery button key combination was recorded within the
+ * last RECOVERY_BUTTON_TIMEOUT microseconds. Note that deep sleep also
+ * clears the recovery button state.
+ */
+static int pop_recovery_button_state(void)
+{
+ int latched_state = 0;
+
+ if (last_press.val &&
+ ((get_time().val - last_press.val) < RECOVERY_BUTTON_TIMEOUT))
+ latched_state = 1;
+
+ last_press.val = 0;
+
+ /* Latched recovery button state */
+ return latched_state;
+}
+
static uint8_t is_rec_btn_pressed(void)
{
if (rec_btn_force_pressed)
return 1;
/*
+ * Platform has a defined recovery button combination and it
+ * the combination was pressed within a timeout
+ */
+ if (board_uses_closed_source_set1() && pop_recovery_button_state())
+ return 1;
+
+ /*
* If not force pressed, check the actual state of button. Note,
* the value is inverted because the button is active low.
*/
@@ -68,6 +111,8 @@ static enum vendor_cmd_rc vc_get_rec_btn(enum vendor_cmd_cc code,
*(uint8_t *)buf = is_rec_btn_pressed();
*response_size = 1;
+ ccprints("%s: state=%d", __func__, *(uint8_t *)buf);
+
return VENDOR_RC_SUCCESS;
}
DECLARE_VENDOR_COMMAND(VENDOR_CC_GET_REC_BTN, vc_get_rec_btn);
diff --git a/board/cr50/recovery_button.h b/board/cr50/recovery_button.h
new file mode 100644
index 0000000000..4a237a776a
--- /dev/null
+++ b/board/cr50/recovery_button.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __EC_BOARD_CR50_RECOVERY_BUTTON_H
+#define __EC_BOARD_CR50_RECOVERY_BUTTON_H
+
+/**
+ * Latch a recovery button sequence. This state is latched for
+ * RECOVERY_BUTTON_TIMEOUT or until the AP requests the recovery button
+ * state.
+ */
+void recovery_button_record(void);
+
+#endif /* ! __EC_BOARD_CR50_RECOVERY_BUTTON_H */