summaryrefslogtreecommitdiff
path: root/zephyr/shim/src/watchdog.c
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/shim/src/watchdog.c')
-rw-r--r--zephyr/shim/src/watchdog.c180
1 files changed, 129 insertions, 51 deletions
diff --git a/zephyr/shim/src/watchdog.c b/zephyr/shim/src/watchdog.c
index 208930f5ea..0b96cbaa0e 100644
--- a/zephyr/shim/src/watchdog.c
+++ b/zephyr/shim/src/watchdog.c
@@ -14,81 +14,159 @@
LOG_MODULE_REGISTER(watchdog_shim, LOG_LEVEL_ERR);
-#define wdt DEVICE_DT_GET(DT_CHOSEN(cros_ec_watchdog))
+struct watchdog_info {
+ const struct device *wdt_dev;
+ struct wdt_timeout_cfg config;
+};
+
+__maybe_unused static void wdt_warning_handler(const struct device *wdt_dev,
+ int channel_id);
+
+const struct watchdog_info wdt_info[] = {
+ {
+ .wdt_dev = DEVICE_DT_GET(DT_CHOSEN(cros_ec_watchdog)),
+ .config = {
+#if DT_NODE_HAS_COMPAT(DT_CHOSEN(cros_ec_watchdog), st_stm32_watchdog)
+ .flags = WDT_FLAG_RESET_SOC,
+ .window.min = 0U,
+ .window.max = CONFIG_WATCHDOG_PERIOD_MS,
+ .callback = NULL,
+#else
+ .flags = WDT_FLAG_RESET_SOC,
+ .window.min = 0U,
+ .window.max = CONFIG_AUX_TIMER_PERIOD_MS,
+ .callback = wdt_warning_handler,
+#endif
+ },
+ },
+#ifdef CONFIG_PLATFORM_EC_WATCHDOG_HELPER
+ {
+ .wdt_dev = DEVICE_DT_GET(DT_CHOSEN(cros_ec_watchdog_helper)),
+ .config = {
+ .flags = 0U,
+ .window.min = 0U,
+ .window.max = CONFIG_AUX_TIMER_PERIOD_MS,
+ .callback = wdt_warning_handler,
+ },
+ },
+#endif
+};
+
+/* Array to keep channel used to implement watchdog */
+int wdt_chan[ARRAY_SIZE(wdt_info)];
+bool watchdog_initialized;
#ifdef TEST_BUILD
-extern bool wdt_warning_triggered;
+bool wdt_warning_triggered;
#endif /* TEST_BUILD */
-static void wdt_warning_handler(const struct device *wdt_dev, int channel_id)
+static int watchdog_config(const struct watchdog_info *info)
{
- const char *thread_name = k_thread_name_get(k_current_get());
+ const struct device *wdt_dev = info->wdt_dev;
+ const struct wdt_timeout_cfg *config = &info->config;
+ int chan;
-#ifdef CONFIG_RISCV
- printk("WDT pre-warning MEPC:%p THREAD_NAME:%s\n",
- (void *)csr_read(mepc), thread_name);
-#else
- /* TODO(b/176523207): watchdog warning message */
- printk("Watchdog deadline is close! THREAD_NAME:%s\n", thread_name);
-#endif
-#ifdef TEST_BUILD
- wdt_warning_triggered = true;
-#endif
-#ifdef CONFIG_SOC_SERIES_MEC172X
- extern void cros_chip_wdt_handler(const struct device *wdt_dev,
- int channel_id);
- cros_chip_wdt_handler(wdt_dev, channel_id);
-#endif
+ chan = wdt_install_timeout(wdt_dev, config);
+
+ /* If watchdog is running, reinstall it. */
+ if (chan == -EBUSY) {
+ wdt_disable(wdt_dev);
+ chan = wdt_install_timeout(wdt_dev, config);
+ }
+
+ if (chan < 0) {
+ LOG_ERR("Watchdog install error: %d", chan);
+ }
+
+ return chan;
}
-int watchdog_init(void)
+static int watchdog_enable(const struct device *wdt_dev)
{
int err;
- struct wdt_timeout_cfg wdt_config;
-
- if (!device_is_ready(wdt)) {
- LOG_ERR("Error: device %s is not ready", wdt->name);
- return -1;
- }
- /* Reset SoC when watchdog timer expires. */
- wdt_config.flags = WDT_FLAG_RESET_SOC;
+ err = wdt_setup(wdt_dev, 0);
+ if (err < 0)
+ LOG_ERR("Watchdog %s setup error: %d", wdt_dev->name, err);
- /*
- * Set the Warning timer as CONFIG_AUX_TIMER_PERIOD_MS.
- * Then the watchdog reset time = CONFIG_WATCHDOG_PERIOD_MS.
- */
- wdt_config.window.min = 0U;
- wdt_config.window.max = CONFIG_AUX_TIMER_PERIOD_MS;
- wdt_config.callback = wdt_warning_handler;
+ return err;
+}
- err = wdt_install_timeout(wdt, &wdt_config);
+static int watchdog_init_device(const struct watchdog_info *info)
+{
+ const struct device *wdt_dev = info->wdt_dev;
+ int chan, err;
- /* If watchdog is running, reinstall it. */
- if (err == -EBUSY) {
- wdt_disable(wdt);
- err = wdt_install_timeout(wdt, &wdt_config);
+ if (!device_is_ready(wdt_dev)) {
+ LOG_ERR("Error: device %s is not ready", wdt_dev->name);
+ return -ENODEV;
}
- if (err < 0) {
- LOG_ERR("Watchdog install error");
- return err;
- }
+ chan = watchdog_config(info);
+ if (chan < 0)
+ return chan;
- err = wdt_setup(wdt, 0);
- if (err < 0) {
- LOG_ERR("Watchdog setup error");
+ err = watchdog_enable(wdt_dev);
+ if (err < 0)
return err;
+
+ return chan;
+}
+
+int watchdog_init(void)
+{
+ int err = EC_SUCCESS;
+
+ if (watchdog_initialized)
+ return -EBUSY;
+
+ for (int i = 0; i < ARRAY_SIZE(wdt_info); i++) {
+ wdt_chan[i] = watchdog_init_device(&wdt_info[i]);
+ if (wdt_chan[i] < 0 && err == EC_SUCCESS)
+ err = wdt_chan[i];
}
- return EC_SUCCESS;
+ watchdog_initialized = true;
+ watchdog_reload();
+
+ return err;
}
void watchdog_reload(void)
{
- if (!device_is_ready(wdt))
- LOG_ERR("Error: device %s is not ready", wdt->name);
+ if (!watchdog_initialized)
+ return;
+
+ for (int i = 0; i < ARRAY_SIZE(wdt_info); i++) {
+ if (wdt_chan[i] < 0)
+ continue;
- wdt_feed(wdt, 0);
+ wdt_feed(wdt_info[i].wdt_dev, wdt_chan[i]);
+ }
}
DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT);
+
+__maybe_unused static void wdt_warning_handler(const struct device *wdt_dev,
+ int channel_id)
+{
+ const char *thread_name = k_thread_name_get(k_current_get());
+
+#ifdef CONFIG_RISCV
+ printk("WDT pre-warning MEPC:%p THREAD_NAME:%s\n",
+ (void *)csr_read(mepc), thread_name);
+#else
+ /* TODO(b/176523207): watchdog warning message */
+ printk("Watchdog deadline is close! THREAD_NAME:%s\n", thread_name);
+#endif
+#ifdef TEST_BUILD
+ wdt_warning_triggered = true;
+#endif
+#ifdef CONFIG_SOC_SERIES_MEC172X
+ extern void cros_chip_wdt_handler(const struct device *wdt_dev,
+ int channel_id);
+ cros_chip_wdt_handler(wdt_dev, channel_id);
+#endif
+
+ /* Watchdog is disabled after calling handler. Re-enable it now. */
+ watchdog_enable(wdt_dev);
+}