diff options
author | Jack Rosenthal <jrosenth@chromium.org> | 2019-03-14 13:14:15 -0600 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-03-26 04:44:00 -0700 |
commit | 9a5a7225737051e9523a775ebf8bba63f144259b (patch) | |
tree | 4c604846f721c564c9dd966d7e5184230805c243 /chip/ish/watchdog.c | |
parent | 5555323902f965a6e489e797f0e156d460e62d67 (diff) | |
download | chrome-ec-9a5a7225737051e9523a775ebf8bba63f144259b.tar.gz |
ish: Add watchdog timer
This adds support for the watchdog timer (WDT) available on Intel Sensor
Hub (ISH). The ISH will reset after T1 expires; see the comments at the
top of watchdog.c for further information on this design decision.
Originally, we had planned to implement a counter that would disable the
WDT after N failures. This was abandoned, since the register used to
store the counter was not able to maintain a value across reset on a
reliable basis (see b:128679825).
BUG=b:127980538,b:128679825
BRANCH=none
TEST=Used waitms command on arcada to verify WDT triggered a warning
IRQ after T1 and reset the system.
Change-Id: I4bd16c253110d60c57eb24cda2abc0facee20748
Signed-off-by: Jack Rosenthal <jrosenth@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1526316
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Reviewed-by: Jett Rink <jettrink@chromium.org>
Diffstat (limited to 'chip/ish/watchdog.c')
-rw-r--r-- | chip/ish/watchdog.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/chip/ish/watchdog.c b/chip/ish/watchdog.c new file mode 100644 index 0000000000..fd0ebcf247 --- /dev/null +++ b/chip/ish/watchdog.c @@ -0,0 +1,84 @@ +/* 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. + * + * Watchdog Timer + * + * In ISH, there is a watchdog timer available from the hardware. It is + * controlled by a few registers: + * + * - WDT_CONTROL (consists of enable bit, T1, and T2 values): When T1 + * reaches 0, a warning is fired. After T2 then reaches 0, the system + * will reset. + * - WDT_RELOAD: Pet the watchdog by setting to 1 + * - WDT_VALUES: Gives software access to T1 and T2 if needed + * + * For ISH implementation, we wish to reset only the ISH. Waiting until + * T2 expires will kill the whole system. The functionality of T2 is + * ignored, and we simply call system_reset when T1 expires. T2 will + * only be used if the system cannot reset when T1 expires. + */ + +#include "common.h" +#include "console.h" +#include "hooks.h" +#include "task.h" +#include "registers.h" +#include "system.h" +#include "watchdog.h" + +/* Units are hundreds of milliseconds */ +#define WDT_T1_PERIOD (100) /* 10 seconds */ +#define WDT_T2_PERIOD (10) /* 1 second */ + +int watchdog_init(void) +{ + /* Initialize WDT clock divider */ + CCU_WDT_CD = WDT_CLOCK_HZ / 10; /* 10 Hz => 100 ms period */ + + /* Enable the watchdog timer and set initial T1/T2 values */ + WDT_CONTROL = WDT_CONTROL_ENABLE_BIT + | (WDT_T2_PERIOD << 8) + | WDT_T1_PERIOD; + + task_enable_irq(ISH_WDT_IRQ); + + return EC_SUCCESS; +} + +/* Parameters are pushed by hardware, we only care about %EIP */ +__attribute__ ((noreturn)) +void watchdog_warning(uint32_t errorcode, + uint32_t eip, + uint32_t cs, + uint32_t eflags) +{ + ccprintf("\nWDT Expired. EIP was 0x%08X. Resetting...\n", eip); + cflush(); + + system_reset(SYSTEM_RESET_AP_WATCHDOG); + __builtin_unreachable(); +} + +__attribute__ ((noreturn)) +void watchdog_warning_irq(void) +{ + /* + * Parameters to watchdog_warning were pushed by hardware, use + * asm here to re-use these parameters in the call. + */ + __asm__ ("call watchdog_warning\n"); + __builtin_unreachable(); +} +DECLARE_IRQ(ISH_WDT_IRQ, watchdog_warning_irq); + +void watchdog_reload(void) +{ + /* + * ISH Supplemental Registers Info, 1.2.6.2: + * "When firmware writes a 1 to this bit, hardware reloads + * the values in WDT_T1 and WDT_T2..." + */ + WDT_RELOAD = 1; +} +DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT); |