diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/drivers/watchdog/tangier_wdt.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/drivers/watchdog/tangier_wdt.c')
-rw-r--r-- | roms/u-boot/drivers/watchdog/tangier_wdt.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/watchdog/tangier_wdt.c b/roms/u-boot/drivers/watchdog/tangier_wdt.c new file mode 100644 index 000000000..bdc65597d --- /dev/null +++ b/roms/u-boot/drivers/watchdog/tangier_wdt.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2017 Intel Corporation + */ +#include <common.h> +#include <dm.h> +#include <log.h> +#include <wdt.h> +#include <div64.h> +#include <asm/scu.h> + +/* Hardware timeout in seconds */ +#define WDT_PRETIMEOUT 15 +#define WDT_TIMEOUT_MIN (1 + WDT_PRETIMEOUT) +#define WDT_TIMEOUT_MAX 170 + +/* + * Note, firmware chooses 90 seconds as a default timeout for watchdog on + * Intel Tangier SoC. It means that without handling it in the running code + * the reboot will happen. + */ + +enum { + SCU_WATCHDOG_START = 0, + SCU_WATCHDOG_STOP = 1, + SCU_WATCHDOG_KEEPALIVE = 2, + SCU_WATCHDOG_SET_ACTION_ON_TIMEOUT = 3, +}; + +static int tangier_wdt_reset(struct udevice *dev) +{ + scu_ipc_simple_command(IPCMSG_WATCHDOG_TIMER, SCU_WATCHDOG_KEEPALIVE); + return 0; +} + +static int tangier_wdt_stop(struct udevice *dev) +{ + return scu_ipc_simple_command(IPCMSG_WATCHDOG_TIMER, SCU_WATCHDOG_STOP); +} + +static int tangier_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) +{ + u32 timeout_sec; + int in_size; + struct ipc_wd_start { + u32 pretimeout; + u32 timeout; + } ipc_wd_start; + + /* Calculate timeout in seconds and restrict to min and max value */ + do_div(timeout_ms, 1000); + timeout_sec = clamp_t(u32, timeout_ms, WDT_TIMEOUT_MIN, WDT_TIMEOUT_MAX); + + /* Update values in the IPC request */ + ipc_wd_start.pretimeout = timeout_sec - WDT_PRETIMEOUT; + ipc_wd_start.timeout = timeout_sec; + + /* + * SCU expects the input size for watchdog IPC + * to be based on 4 bytes + */ + in_size = DIV_ROUND_UP(sizeof(ipc_wd_start), 4); + + scu_ipc_command(IPCMSG_WATCHDOG_TIMER, SCU_WATCHDOG_START, + (u32 *)&ipc_wd_start, in_size, NULL, 0); + + return 0; +} + +static const struct wdt_ops tangier_wdt_ops = { + .reset = tangier_wdt_reset, + .start = tangier_wdt_start, + .stop = tangier_wdt_stop, +}; + +static const struct udevice_id tangier_wdt_ids[] = { + { .compatible = "intel,tangier-wdt" }, + { /* sentinel */ } +}; + +static int tangier_wdt_probe(struct udevice *dev) +{ + debug("%s: Probing wdt%u\n", __func__, dev_seq(dev)); + return 0; +} + +U_BOOT_DRIVER(wdt_tangier) = { + .name = "wdt_tangier", + .id = UCLASS_WDT, + .of_match = tangier_wdt_ids, + .ops = &tangier_wdt_ops, + .probe = tangier_wdt_probe, +}; |