aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/watchdog/sp805_wdt.c15
-rw-r--r--drivers/watchdog/wdt-uclass.c44
-rw-r--r--include/wdt.h37
3 files changed, 57 insertions, 39 deletions
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index ca3ccbe76cb..65fd2384f12 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -7,6 +7,7 @@
#include <asm/io.h>
#include <common.h>
+#include <clk.h>
#include <dm/device.h>
#include <dm/fdtaddr.h>
#include <dm/read.h>
@@ -34,6 +35,7 @@ DECLARE_GLOBAL_DATA_PTR;
struct sp805_wdt_priv {
void __iomem *reg;
+ unsigned long clk_rate;
};
static int sp805_wdt_reset(struct udevice *dev)
@@ -63,8 +65,13 @@ static int sp805_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
* set 120s, the gd->bus_clk is less than 1145MHz, the load_value will
* not overflow.
*/
- load_value = (gd->bus_clk) /
- (2 * 1000 * SYS_FSL_WDT_CLK_DIV) * load_time;
+ if (gd->bus_clk) {
+ load_value = (gd->bus_clk) /
+ (2 * 1000 * SYS_FSL_WDT_CLK_DIV) * load_time;
+ } else {
+ /* platform provide clk */
+ load_value = (timeout / 2) * (priv->clk_rate / 1000);
+ }
writel(UNLOCK, priv->reg + WDTLOCK);
writel(load_value, priv->reg + WDTLOAD);
@@ -105,11 +112,15 @@ static int sp805_wdt_probe(struct udevice *dev)
static int sp805_wdt_ofdata_to_platdata(struct udevice *dev)
{
struct sp805_wdt_priv *priv = dev_get_priv(dev);
+ struct clk clk;
priv->reg = (void __iomem *)dev_read_addr(dev);
if (IS_ERR(priv->reg))
return PTR_ERR(priv->reg);
+ if (!clk_get_by_index(dev, 0, &clk))
+ priv->clk_rate = clk_get_rate(&clk);
+
return 0;
}
diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c
index d9e4dc7cb8a..4cdb7bd64cd 100644
--- a/drivers/watchdog/wdt-uclass.c
+++ b/drivers/watchdog/wdt-uclass.c
@@ -14,6 +14,48 @@
DECLARE_GLOBAL_DATA_PTR;
+#define WATCHDOG_TIMEOUT_SECS (CONFIG_WATCHDOG_TIMEOUT_MSECS / 1000)
+
+/*
+ * Reset every 1000ms, or however often is required as indicated by a
+ * hw_margin_ms property.
+ */
+static ulong reset_period = 1000;
+
+int initr_watchdog(void)
+{
+ u32 timeout = WATCHDOG_TIMEOUT_SECS;
+
+ /*
+ * Init watchdog: This will call the probe function of the
+ * watchdog driver, enabling the use of the device
+ */
+ if (uclass_get_device_by_seq(UCLASS_WDT, 0,
+ (struct udevice **)&gd->watchdog_dev)) {
+ debug("WDT: Not found by seq!\n");
+ if (uclass_get_device(UCLASS_WDT, 0,
+ (struct udevice **)&gd->watchdog_dev)) {
+ printf("WDT: Not found!\n");
+ return 0;
+ }
+ }
+
+ if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
+ timeout = dev_read_u32_default(gd->watchdog_dev, "timeout-sec",
+ WATCHDOG_TIMEOUT_SECS);
+ reset_period = dev_read_u32_default(gd->watchdog_dev,
+ "hw_margin_ms",
+ 4 * reset_period) / 4;
+ }
+
+ wdt_start(gd->watchdog_dev, timeout * 1000, 0);
+ gd->flags |= GD_FLG_WDT_READY;
+ printf("WDT: Started with%s servicing (%ds timeout)\n",
+ IS_ENABLED(CONFIG_WATCHDOG) ? "" : "out", timeout);
+
+ return 0;
+}
+
int wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
{
const struct wdt_ops *ops = device_get_ops(dev);
@@ -85,7 +127,7 @@ void watchdog_reset(void)
/* Do not reset the watchdog too often */
now = get_timer(0);
if (time_after(now, next_reset)) {
- next_reset = now + 1000; /* reset every 1000ms */
+ next_reset = now + reset_period;
wdt_reset(gd->watchdog_dev);
}
}
diff --git a/include/wdt.h b/include/wdt.h
index dd83dfdd320..aea5abc7680 100644
--- a/include/wdt.h
+++ b/include/wdt.h
@@ -106,41 +106,6 @@ struct wdt_ops {
int (*expire_now)(struct udevice *dev, ulong flags);
};
-#if CONFIG_IS_ENABLED(WDT)
-#ifndef CONFIG_WATCHDOG_TIMEOUT_MSECS
-#define CONFIG_WATCHDOG_TIMEOUT_MSECS (60 * 1000)
-#endif
-#define WATCHDOG_TIMEOUT_SECS (CONFIG_WATCHDOG_TIMEOUT_MSECS / 1000)
-
-static inline int initr_watchdog(void)
-{
- u32 timeout = WATCHDOG_TIMEOUT_SECS;
-
- /*
- * Init watchdog: This will call the probe function of the
- * watchdog driver, enabling the use of the device
- */
- if (uclass_get_device_by_seq(UCLASS_WDT, 0,
- (struct udevice **)&gd->watchdog_dev)) {
- debug("WDT: Not found by seq!\n");
- if (uclass_get_device(UCLASS_WDT, 0,
- (struct udevice **)&gd->watchdog_dev)) {
- printf("WDT: Not found!\n");
- return 0;
- }
- }
-
- if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
- timeout = dev_read_u32_default(gd->watchdog_dev, "timeout-sec",
- WATCHDOG_TIMEOUT_SECS);
- }
- wdt_start(gd->watchdog_dev, timeout * 1000, 0);
- gd->flags |= GD_FLG_WDT_READY;
- printf("WDT: Started with%s servicing (%ds timeout)\n",
- IS_ENABLED(CONFIG_WATCHDOG) ? "" : "out", timeout);
-
- return 0;
-}
-#endif
+int initr_watchdog(void);
#endif /* _WDT_H_ */