This patch enhances the Qualcomm watchdog driver by introducing support for dynamic timeout configuration. Specifically:
- Calculates and sets the bark and bite timeout values based on the clock rate and the requested timeout in milliseconds. - Adds retrieval of the watchdog clock rate during probe using the common clock framework. - Adds a default timeout value for ARCH_SNAPDRAGON in WATCHDOG_TIMEOUT_MSECS. These changes improve the configurability and accuracy of the watchdog timer on Qualcomm platforms. This work builds upon the previous submission: https://lore.kernel.org/all/20250422-b4-qcom-wdt-v3-1-730d4d5a8...@paulsajna.com/ Signed-off-by: Balaji Selvanathan <balaji.selvanat...@oss.qualcomm.com> --- drivers/watchdog/Kconfig | 2 ++ drivers/watchdog/qcom-wdt.c | 24 ++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 808f4e578e2..45c5e20e2ed 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -29,6 +29,7 @@ config WATCHDOG_TIMEOUT_MSECS int "Watchdog timeout in msec" default 128000 if ARCH_MX31 || ARCH_MX5 || ARCH_MX6 default 128000 if ARCH_MX7 || ARCH_VF610 + default 30000 if ARCH_SNAPDRAGON default 30000 if ARCH_SOCFPGA default 16000 if ARCH_SUNXI default 5376 if ULP_WATCHDOG @@ -338,6 +339,7 @@ endif config WDT_QCOM bool "Qualcomm watchdog timer support" depends on WDT && ARCH_SNAPDRAGON + imply WATCHDOG help Select this to enable Qualcomm watchdog timer, which can be found on some Qualcomm chips. diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index 3601ba93774..adbb5aacdc3 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c @@ -13,6 +13,7 @@ #include <dm.h> #include <dm/device_compat.h> #include <wdt.h> +#include <clk.h> #include <asm/io.h> @@ -30,6 +31,7 @@ struct qcom_wdt_match_data { struct qcom_wdt { void __iomem *base; + ulong clk_rate; const u32 *layout; }; @@ -53,10 +55,14 @@ static void __iomem *wdt_addr(struct qcom_wdt *wdt, enum wdt_reg reg) int qcom_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) { struct qcom_wdt *wdt = dev_get_priv(dev); + ulong bark_timeout_s = ((timeout_ms - 1) * wdt->clk_rate) / 1000; + ulong bite_timeout_s = (timeout_ms * wdt->clk_rate) / 1000; writel(0, wdt_addr(wdt, WDT_EN)); - writel(1, wdt_addr(wdt, WDT_RST)); - writel(1, wdt_addr(wdt, WDT_EN)); + writel(BIT(0), wdt_addr(wdt, WDT_RST)); + writel(bark_timeout_s, wdt_addr(wdt, WDT_BARK_TIME)); + writel(bite_timeout_s, wdt_addr(wdt, WDT_BITE_TIME)); + writel(BIT(0), wdt_addr(wdt, WDT_EN)); if (readl(wdt_addr(wdt, WDT_EN)) != 1) { dev_err(dev, "Failed to enable Qualcomm watchdog!\n"); return -EIO; @@ -87,12 +93,26 @@ int qcom_wdt_reset(struct udevice *dev) static int qcom_wdt_probe(struct udevice *dev) { + struct clk clk; + long rate; + int ret; + struct qcom_wdt *wdt = dev_get_priv(dev); struct qcom_wdt_match_data *data = (void *)dev_get_driver_data(dev); wdt->base = dev_read_addr_ptr(dev); wdt->layout = data->offset; + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return ret; + + rate = clk_get_rate(&clk); + if (rate <= 0) + return rate < 0 ? (int)rate : -EINVAL; + + wdt->clk_rate = (ulong)rate; + return 0; } -- 2.34.1