/* * Copyright (c) 2023 Centralp * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #define WDT_SETUP_HELP \ "Set up watchdog instance. Syntax:\n" \ "" #define WDT_DISABLE_HELP \ "Disable watchdog instance. Syntax:\n" \ "" #define WDT_TIMEOUT_HELP \ "Install a new timeout. Syntax:\n" \ " " #define WDT_FEED_HELP \ "Feed specified watchdog timeout. Syntax:\n" \ " " static const char *const wdt_reset_name[] = { [WDT_FLAG_RESET_NONE] = "none", [WDT_FLAG_RESET_CPU_CORE] = "cpu", [WDT_FLAG_RESET_SOC] = "soc", }; struct args_index { uint8_t device; uint8_t reset; uint8_t timeout_min; uint8_t timeout_max; uint8_t channel_id; }; static const struct args_index args_indx = { .device = 1, .reset = 2, .timeout_min = 3, .timeout_max = 4, .channel_id = 2, }; static int parse_named_int(const char *name, const char *const keystack[], size_t count) { char *endptr; int i; /* Attempt to parse name as a number first */ i = strtoul(name, &endptr, 0); if (*endptr == '\0') { return i; } /* Name is not a number, look it up */ for (i = 0; i < count; i++) { if (strcmp(name, keystack[i]) == 0) { return i; } } return -ENOTSUP; } static int cmd_setup(const struct shell *sh, size_t argc, char *argv[]) { const struct device *dev; dev = device_get_binding(argv[args_indx.device]); if (!dev) { shell_error(sh, "WDT device not found"); return -ENODEV; } return wdt_setup(dev, 0); } static int cmd_disable(const struct shell *sh, size_t argc, char *argv[]) { const struct device *dev; dev = device_get_binding(argv[args_indx.device]); if (!dev) { shell_error(sh, "WDT device not found"); return -ENODEV; } return wdt_disable(dev); } static int cmd_timeout(const struct shell *sh, size_t argc, char *argv[]) { const struct device *dev; int flags; int timeout_min; int timeout_max; struct wdt_timeout_cfg cfg; int rc; dev = device_get_binding(argv[args_indx.device]); if (!dev) { shell_error(sh, "WDT device not found"); return -ENODEV; } flags = parse_named_int(argv[args_indx.reset], wdt_reset_name, ARRAY_SIZE(wdt_reset_name)); if (flags < 0) { shell_error(sh, "Reset mode '%s' unknown", argv[args_indx.reset]); return -EINVAL; } timeout_min = parse_named_int(argv[args_indx.timeout_min], NULL, 0); if (timeout_min < 0) { shell_error(sh, "Unable to convert '%s' to integer", argv[args_indx.timeout_min]); return -EINVAL; } timeout_max = parse_named_int(argv[args_indx.timeout_max], NULL, 0); if (timeout_max < 0) { shell_error(sh, "Unable to convert '%s' to integer", argv[args_indx.timeout_max]); return -EINVAL; } cfg.window.min = timeout_min; cfg.window.max = timeout_max; cfg.callback = NULL; cfg.flags = flags; rc = wdt_install_timeout(dev, &cfg); if (rc >= 0) { shell_print(sh, "Channel ID = %d", rc); } return rc; } static int cmd_feed(const struct shell *sh, size_t argc, char *argv[]) { const struct device *dev; int channel_id; dev = device_get_binding(argv[args_indx.device]); if (!dev) { shell_error(sh, "WDT device not found"); return -ENODEV; } channel_id = parse_named_int(argv[args_indx.channel_id], NULL, 0); if (channel_id < 0) { shell_error(sh, "Unable to convert '%s' to integer", argv[args_indx.channel_id]); return -EINVAL; } return wdt_feed(dev, channel_id); } /* Device name autocompletion support */ static void device_name_get(size_t idx, struct shell_static_entry *entry) { const struct device *dev = shell_device_lookup(idx, NULL); entry->syntax = (dev != NULL) ? dev->name : NULL; entry->handler = NULL; entry->help = NULL; entry->subcmd = NULL; } SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get); /* clang-format off */ SHELL_STATIC_SUBCMD_SET_CREATE(sub_wdt, SHELL_CMD_ARG(setup, &dsub_device_name, WDT_SETUP_HELP, cmd_setup, 2, 0), SHELL_CMD_ARG(disable, &dsub_device_name, WDT_DISABLE_HELP, cmd_disable, 2, 0), SHELL_CMD_ARG(timeout, &dsub_device_name, WDT_TIMEOUT_HELP, cmd_timeout, 5, 0), SHELL_CMD_ARG(feed, &dsub_device_name, WDT_FEED_HELP, cmd_feed, 3, 0), SHELL_SUBCMD_SET_END ); /* clang-format on */ SHELL_CMD_REGISTER(wdt, &sub_wdt, "Watchdog commands", NULL);