diff options
-rw-r--r-- | drivers/watchdog/Kconfig | 2 | ||||
-rw-r--r-- | drivers/watchdog/qcom-wdt.c | 24 |
2 files changed, 24 insertions, 2 deletions
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 <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; } |