summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2019-05-13 15:22:36 -0600
committerJack Rosenthal <jrosenth@chromium.org>2019-06-06 19:55:59 +0000
commit0c5985a74f66f89f05d6f26666c15229fc68d1df (patch)
tree99aaeabb8b1d4ac9cf302a170725876e715f5c2f
parentc723e723392aabc35747a6678b4b7931d7aeddb7 (diff)
downloadchrome-ec-0c5985a74f66f89f05d6f26666c15229fc68d1df.tar.gz
ish: max-retries mechanism for watchdog timer
This adds a relevant config option, as well as implementation for a max-retries mechanism on the watchdog timer. Included is an implementation for ISH which counts persistent data storage and halts when the max-retries is exceeded. BUG=b:132059981 BRANCH=none TEST=observed system halt after 4 resets, then re-enable once we had a successful reset Change-Id: I7b443d9a20a474b294d494c5b6046a38eaf6ff12 Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1609605 Reviewed-by: Jett Rink <jettrink@chromium.org> Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
-rw-r--r--chip/ish/system.c35
-rw-r--r--chip/ish/watchdog.c8
-rw-r--r--include/config.h7
3 files changed, 49 insertions, 1 deletions
diff --git a/chip/ish/system.c b/chip/ish/system.c
index 0d778eaa5e..f634981817 100644
--- a/chip/ish/system.c
+++ b/chip/ish/system.c
@@ -10,6 +10,7 @@
#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
+#include "interrupts.h"
#include "ish_fwst.h"
#include "ish_persistent_data.h"
#include "power_mgt.h"
@@ -21,6 +22,10 @@
#include "timer.h"
#include "util.h"
+#define CPUTS(outstr) cputs(CC_SYSTEM, outstr)
+#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
+
int system_is_reboot_warm(void)
{
return !(system_get_reset_flags() &
@@ -45,6 +50,27 @@ uint32_t chip_read_reset_flags(void)
return ish_persistent_data.reset_flags;
}
+/*
+ * Kill the Minute-IA core and don't come back alive.
+ *
+ * Used when the watchdog timer exceeds max retries and we want to
+ * disable ISH completely.
+ */
+__attribute__((noreturn))
+static void system_halt(void)
+{
+ cflush();
+
+ while (1) {
+ disable_all_interrupts();
+ WDT_CONTROL = 0;
+ CCU_TCG_EN = 1;
+ __asm__ volatile (
+ "cli\n"
+ "hlt\n");
+ }
+}
+
void system_reset(int flags)
{
uint32_t save_flags;
@@ -60,8 +86,15 @@ void system_reset(int flags)
system_encode_save_flags(flags, &save_flags);
- if (flags & SYSTEM_RESET_AP_WATCHDOG)
+ if (flags & SYSTEM_RESET_AP_WATCHDOG) {
save_flags |= RESET_FLAG_WATCHDOG;
+ ish_persistent_data.watchdog_counter += 1;
+ if (ish_persistent_data.watchdog_counter
+ >= CONFIG_WATCHDOG_MAX_RETRIES) {
+ CPRINTS("Halting ISH due to max watchdog resets");
+ system_halt();
+ }
+ }
chip_save_reset_flags(save_flags);
diff --git a/chip/ish/watchdog.c b/chip/ish/watchdog.c
index 79f6e788df..2e83b57f25 100644
--- a/chip/ish/watchdog.c
+++ b/chip/ish/watchdog.c
@@ -21,6 +21,7 @@
#include "common.h"
#include "hooks.h"
+#include "ish_persistent_data.h"
#include "task.h"
#include "registers.h"
#include "system.h"
@@ -32,6 +33,13 @@
int watchdog_init(void)
{
+ /*
+ * Put reset counter back at zero if last reset was not caused
+ * by watchdog
+ */
+ if ((system_get_reset_flags() & RESET_FLAG_WATCHDOG) == 0)
+ ish_persistent_data.watchdog_counter = 0;
+
/* Initialize WDT clock divider */
CCU_WDT_CD = WDT_CLOCK_HZ / 10; /* 10 Hz => 100 ms period */
diff --git a/include/config.h b/include/config.h
index ce38ee658b..fcc4bf6727 100644
--- a/include/config.h
+++ b/include/config.h
@@ -3972,6 +3972,13 @@
*/
#undef CONFIG_WATCHDOG_HELP
+/*
+ * The maximum number of times that the watchdog timer may reset
+ * before halting the system (or taking some sort of other
+ * chip-dependent corrective action).
+ */
+#define CONFIG_WATCHDOG_MAX_RETRIES 4
+
/* Watchdog period in ms; see also AUX_TIMER_PERIOD_MS */
#define CONFIG_WATCHDOG_PERIOD_MS 1600