summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew McRae <amcrae@google.com>2020-06-20 11:48:59 +1000
committerCommit Bot <commit-bot@chromium.org>2020-06-23 03:17:54 +0000
commit131f7dc96e1c794befabdd8b182c7d5a190b58cc (patch)
treecdab2380508491fe000509b8544f3b41677d87af
parentbaceadc0e81945b1ca0e58ae09d3d4724a991d40 (diff)
downloadchrome-ec-131f7dc96e1c794befabdd8b182c7d5a190b58cc.tar.gz
npcx: Add a new flag to check for initial power-on
The CR50 will reset the EC on some platforms after power-on. Add a reset flag to detect this and treat the second restart as a power-on restart rather than reset. Subsume the CONFIG_GPIO_INIT_POWER_ON_DELAY_MS config to make it clear what the behaviour will be. BUG=b:151329011 TEST=Confirm on dalboz, puff & variants that second reset is treated correctly. BRANCH=none Change-Id: Ib66de920403f08099b87d1eff797270606b44f8f Signed-off-by: Andrew McRae <amcrae@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2255830 Reviewed-by: Peter Marheine <pmarheine@chromium.org> Commit-Queue: Andrew McRae <amcrae@chromium.org> Tested-by: Andrew McRae <amcrae@chromium.org>
-rw-r--r--baseboard/grunt/baseboard.h7
-rw-r--r--baseboard/zork/baseboard.h7
-rw-r--r--board/puff/board.h1
-rw-r--r--chip/npcx/gpio.c8
-rw-r--r--chip/npcx/system.c63
-rw-r--r--include/config.h25
-rw-r--r--include/ec_commands.h1
-rw-r--r--include/reset_flag_desc.inc1
8 files changed, 81 insertions, 32 deletions
diff --git a/baseboard/grunt/baseboard.h b/baseboard/grunt/baseboard.h
index 466c5b05f9..589c2454ed 100644
--- a/baseboard/grunt/baseboard.h
+++ b/baseboard/grunt/baseboard.h
@@ -97,11 +97,10 @@
/*
* On power-on, H1 releases the EC from reset but then quickly asserts and
* releases the reset a second time. This means the EC sees 2 resets:
- * (1) power-on reset, (2) reset-pin reset. If we add a delay between reset (1)
- * and configuring GPIO output levels, then reset (2) will happen before the
- * end of the delay so we avoid extra output toggles.
+ * (1) power-on reset, (2) reset-pin reset. This config will
+ * allow the second reset to be treated as a power-on.
*/
-#define CONFIG_GPIO_INIT_POWER_ON_DELAY_MS 100
+#define CONFIG_BOARD_RESET_AFTER_POWER_ON
#define CONFIG_KEYBOARD_BOARD_CONFIG
#define CONFIG_KEYBOARD_COL2_INVERTED
diff --git a/baseboard/zork/baseboard.h b/baseboard/zork/baseboard.h
index 3b7b6bbf45..57667760ad 100644
--- a/baseboard/zork/baseboard.h
+++ b/baseboard/zork/baseboard.h
@@ -99,11 +99,10 @@
/*
* On power-on, H1 releases the EC from reset but then quickly asserts and
* releases the reset a second time. This means the EC sees 2 resets:
- * (1) power-on reset, (2) reset-pin reset. If we add a delay between reset (1)
- * and configuring GPIO output levels, then reset (2) will happen before the
- * end of the delay so we avoid extra output toggles.
+ * (1) power-on reset, (2) reset-pin reset. This config will
+ * allow the second reset to be treated as a power-on.
*/
-#define CONFIG_GPIO_INIT_POWER_ON_DELAY_MS 100
+#define CONFIG_BOARD_RESET_AFTER_POWER_ON
#define CONFIG_IO_EXPANDER
#define CONFIG_IO_EXPANDER_NCT38XX
diff --git a/board/puff/board.h b/board/puff/board.h
index 83cbd5dca6..2d81fd2310 100644
--- a/board/puff/board.h
+++ b/board/puff/board.h
@@ -31,6 +31,7 @@
#define CONFIG_DEDICATED_RECOVERY_BUTTON
#define CONFIG_DEDICATED_RECOVERY_BUTTON_2
#define CONFIG_BUTTONS_RUNTIME_CONFIG
+#define CONFIG_BOARD_RESET_AFTER_POWER_ON
/* TODO: (b/143496253) re-enable CEC */
/* #define CONFIG_CEC */
#define CONFIG_CRC8
diff --git a/chip/npcx/gpio.c b/chip/npcx/gpio.c
index e20319ab0f..26d5345b22 100644
--- a/chip/npcx/gpio.c
+++ b/chip/npcx/gpio.c
@@ -506,7 +506,6 @@ void gpio_pre_init(void)
system_check_bbram_on_reset();
is_warm = system_is_reboot_warm();
-#ifdef CONFIG_GPIO_INIT_POWER_ON_DELAY_MS
/*
* On power-on of some boards, H1 releases the EC from reset but then
* quickly asserts and releases the reset a second time. This means the
@@ -517,11 +516,12 @@ void gpio_pre_init(void)
*
* Make sure to set up the timer before using udelay().
*/
- if (system_get_reset_flags() & EC_RESET_FLAG_POWER_ON) {
+ if (IS_ENABLED(CONFIG_BOARD_RESET_AFTER_POWER_ON) &&
+ system_get_reset_flags() & EC_RESET_FLAG_INITIAL_PWR) {
__hw_early_init_hwtimer(0);
- udelay(CONFIG_GPIO_INIT_POWER_ON_DELAY_MS * MSEC);
+ udelay(2 * SECOND);
+ /* Shouldn't get here, but proceeding anyway... */
}
-#endif
#ifdef CHIP_FAMILY_NPCX7
/*
diff --git a/chip/npcx/system.c b/chip/npcx/system.c
index 14e5b4ced6..2a1407d4f8 100644
--- a/chip/npcx/system.c
+++ b/chip/npcx/system.c
@@ -321,7 +321,8 @@ uint32_t chip_read_reset_flags(void)
static void check_reset_cause(void)
{
uint32_t hib_wake_flags = bbram_data_read(BBRM_DATA_INDEX_WAKE);
- uint32_t flags = chip_read_reset_flags();
+ uint32_t chip_flags = chip_read_reset_flags();
+ uint32_t flags = chip_flags;
/* Clear saved reset flags in bbram */
#ifdef CONFIG_POWER_BUTTON_INIT_IDLE
@@ -329,9 +330,9 @@ static void check_reset_cause(void)
* We're not sure whether we're booting or not. AP_IDLE will be cleared
* on S5->S3 transition.
*/
- chip_save_reset_flags(flags & EC_RESET_FLAG_AP_IDLE);
+ chip_flags &= EC_RESET_FLAG_AP_IDLE;
#else
- chip_save_reset_flags(0);
+ chip_flags = 0;
#endif
/* Clear saved hibernate wake flag in bbram , too */
bbram_data_write(BBRM_DATA_INDEX_WAKE, 0);
@@ -343,12 +344,60 @@ static void check_reset_cause(void)
flags |= EC_RESET_FLAG_RESET_PIN;
#else
/* Check for VCC1 reset */
- if (IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_STS))
- flags |= EC_RESET_FLAG_RESET_PIN;
- else
- flags |= EC_RESET_FLAG_POWER_ON;
+ int reset = IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_STS);
+
+ /*
+ * If configured, check the saved flags to see whether
+ * the previous restart was a power-on, in which case
+ * treat this restart as a power-on as well.
+ * This is to workaround the fact that the H1 will
+ * reset the EC at power up.
+ */
+ if (IS_ENABLED(CONFIG_BOARD_RESET_AFTER_POWER_ON)) {
+ /*
+ * Reset pin restart rather than power-on, so check
+ * for any flag set from a previous power-on.
+ */
+ if (reset) {
+ if (flags & EC_RESET_FLAG_INITIAL_PWR)
+ /*
+ * The previous restart was a power-on
+ * so treat this restart as that, and
+ * clear the flag so later code will
+ * not wait for the second reset.
+ */
+ flags =
+ (flags & ~EC_RESET_FLAG_INITIAL_PWR)
+ | EC_RESET_FLAG_POWER_ON;
+ else
+ /*
+ * No previous power-on flag,
+ * so this is a subsequent restart
+ * i.e any restarts after the
+ * second restart caused by the H1.
+ */
+ flags |= EC_RESET_FLAG_RESET_PIN;
+ } else {
+ /*
+ * Power-on restart, so set a flag and save it
+ * for the next imminent reset. Later code
+ * will check for this flag and wait for the
+ * second reset.
+ */
+ flags |= EC_RESET_FLAG_POWER_ON
+ | EC_RESET_FLAG_INITIAL_PWR;
+ chip_flags |= EC_RESET_FLAG_INITIAL_PWR;
+ }
+ } else
+ /*
+ * No second reset after power-on, so
+ * set the flags according to the restart reason.
+ */
+ flags |= reset ? EC_RESET_FLAG_RESET_PIN
+ : EC_RESET_FLAG_POWER_ON;
#endif
}
+ chip_save_reset_flags(chip_flags);
/*
* Set scratch bit to distinguish VCC1RST# is asserted again
diff --git a/include/config.h b/include/config.h
index 0edf5697c2..70d9179789 100644
--- a/include/config.h
+++ b/include/config.h
@@ -681,6 +681,18 @@
*/
#undef CONFIG_BOARD_FORCE_RESET_PIN
+/*
+ * For some boards on power-on, the EC is reset by the H1 after power-on,
+ * so the EC sees 2 resets. This config enables the EC to save a flag
+ * on the first power-up restart, and then wait for the second reset before
+ * any other setup is done (such as GPIOs, timers, UART etc.)
+ * On the second reset, the saved flag is used to detect the previous
+ * power-on, and treat the second reset as a power-on instead of a reset.
+ *
+ * NOTE: Implemented only for npcx
+ */
+#undef CONFIG_BOARD_RESET_AFTER_POWER_ON
+
/* Permanent LM4 boot configuration */
#undef CONFIG_BOOTCFG_VALUE
@@ -1908,19 +1920,6 @@
#undef CONFIG_GESTURE_SIGMO_SKIP_MS
#undef CONFIG_GESTURE_SIGMO_THRES_MG
-/*
- * Delay between power on and configuring GPIOs.
- * On power-on of some boards, H1 releases the EC from reset but then
- * quickly asserts and releases the reset a second time. This means the
- * EC sees 2 resets: (1) power-on reset, (2) reset-pin reset. If we add
- * a delay between reset (1) and configuring GPIO output levels, then
- * reset (2) will happen before the end of the delay so we avoid extra
- * output toggles.
- *
- * NOTE: Implemented only for npcx
- */
-#undef CONFIG_GPIO_INIT_POWER_ON_DELAY_MS
-
/* Support getting gpio flags. */
#undef CONFIG_GPIO_GET_EXTENDED
diff --git a/include/ec_commands.h b/include/ec_commands.h
index c239de8b66..877ce10018 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -5799,6 +5799,7 @@ struct ec_params_set_cbi {
*/
#define EC_RESET_FLAG_EFS BIT(20) /* Jumped to this image by EFS */
#define EC_RESET_FLAG_AP_IDLE BIT(21) /* Leave alone AP */
+#define EC_RESET_FLAG_INITIAL_PWR BIT(22) /* EC had power, then was reset */
struct ec_response_uptime_info {
/*
diff --git a/include/reset_flag_desc.inc b/include/reset_flag_desc.inc
index ea7f8b567e..ed3ce69a0d 100644
--- a/include/reset_flag_desc.inc
+++ b/include/reset_flag_desc.inc
@@ -29,3 +29,4 @@
"stay-in-ro",
"efs",
"ap-idle",
+"initial-pwr",