diff options
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/Kconfig | 8 | ||||
-rw-r--r-- | drivers/watchdog/Makefile | 1 | ||||
-rw-r--r-- | drivers/watchdog/sandbox_alarm-wdt.c | 79 |
3 files changed, 88 insertions, 0 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index e55deaf906..29e375e117 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -281,6 +281,14 @@ config WDT_SANDBOX can be probed and supports all of the methods of WDT, but does not really do anything. +config WDT_ALARM_SANDBOX + bool "Enable SIGALRM-based Watchdog Timer support for Sandbox" + depends on SANDBOX && WDT + help + Enable support for a SIGALRM-based watchdog timer in Sandbox. This is + a watchdog device based on the host OS' alarm() function, which will + kill the sandbox with SIGALRM unless properly maintained. + config WDT_SBSA bool "SBSA watchdog timer support" depends on WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 0e2f582a5f..446d961d7d 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o obj-$(CONFIG_ULP_WATCHDOG) += ulp_wdog.o obj-$(CONFIG_$(SPL_TPL_)WDT) += wdt-uclass.o obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o +obj-$(CONFIG_WDT_ALARM_SANDBOX) += sandbox_alarm-wdt.o obj-$(CONFIG_WDT_APPLE) += apple_wdt.o obj-$(CONFIG_WDT_ARMADA_37XX) += armada-37xx-wdt.o obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o diff --git a/drivers/watchdog/sandbox_alarm-wdt.c b/drivers/watchdog/sandbox_alarm-wdt.c new file mode 100644 index 0000000000..71bb5d924e --- /dev/null +++ b/drivers/watchdog/sandbox_alarm-wdt.c @@ -0,0 +1,79 @@ +#include <common.h> +#include <dm.h> +#include <os.h> +#include <wdt.h> + +struct alarm_wdt_priv { + unsigned int timeout_sec; +}; + +static void alarm_handler(int sig) +{ + const char *msg = "!!! ALARM !!!\n"; + + os_write(2, msg, strlen(msg)); + os_fd_restore(); + os_set_alarm_handler(NULL); + os_raise_sigalrm(); +} + +static int alarm_wdt_start(struct udevice *dev, u64 timeout, ulong flags) +{ + struct alarm_wdt_priv *priv = dev_get_priv(dev); + unsigned int sec; + + timeout = DIV_ROUND_UP(timeout, 1000); + sec = min_t(u64, UINT_MAX, timeout); + priv->timeout_sec = sec; + + os_alarm(0); + os_set_alarm_handler(alarm_handler); + os_alarm(sec); + + return 0; +} + +static int alarm_wdt_stop(struct udevice *dev) +{ + os_alarm(0); + os_set_alarm_handler(NULL); + + return 0; +} + +static int alarm_wdt_reset(struct udevice *dev) +{ + struct alarm_wdt_priv *priv = dev_get_priv(dev); + + os_alarm(priv->timeout_sec); + + return 0; +} + +static int alarm_wdt_expire_now(struct udevice *dev, ulong flags) +{ + alarm_handler(0); + + return 0; +} + + +static const struct wdt_ops alarm_wdt_ops = { + .start = alarm_wdt_start, + .reset = alarm_wdt_reset, + .stop = alarm_wdt_stop, + .expire_now = alarm_wdt_expire_now, +}; + +static const struct udevice_id alarm_wdt_ids[] = { + { .compatible = "sandbox,alarm-wdt" }, + {} +}; + +U_BOOT_DRIVER(alarm_wdt_sandbox) = { + .name = "alarm_wdt_sandbox", + .id = UCLASS_WDT, + .of_match = alarm_wdt_ids, + .ops = &alarm_wdt_ops, + .priv_auto = sizeof(struct alarm_wdt_priv), +}; |