From: Balaji Selvanathan Date: Tue, 27 May 2025 12:49:26 +0000 (+0530) Subject: drivers: watchdog: qcom: Add timeout configuration support in watchdog X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=35811a7b0d68ce1a32446953e3ccf7a2186f08f8;p=thirdparty%2Fu-boot.git drivers: watchdog: qcom: Add timeout configuration support in watchdog 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-730d4d5a858d@paulsajna.com/ Signed-off-by: Balaji Selvanathan Link: https://lore.kernel.org/r/20250527124926.128413-1-balaji.selvanathan@oss.qualcomm.com Signed-off-by: Casey Connolly --- diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 38519add771..45eb9b4d3f9 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 #include #include +#include #include @@ -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; }