watchdog: at91sam9_wdt: Fix WDT setup in at91_wdt_start()
authorStefan Roese <sr@denx.de>
Tue, 2 Apr 2019 08:57:19 +0000 (10:57 +0200)
committerEugen Hristev <eugen.hristev@microchip.com>
Tue, 9 Apr 2019 06:28:50 +0000 (09:28 +0300)
This patch fixes the timer register setup in at91_wdt_start() to
correctly configure the register again. The input timeout value is
now in milli-seconds instead of seconds with the new watchdog API.
Make sure to take this into account and only use a max timeout
value of 16 seconds as appropriate for this SoC.

Also the check against a lower timeout value than 0 is removed. This
check makes no sense, as the timeout value is unsigned.

Signed-off-by: Stefan Roese <sr@denx.de>
Reported-by: Heiko Schocher <hs@denx.de>
Cc: Heiko Schocher <hs@denx.de>
Cc: Andreas Bießmann <andreas@biessmann.org>
Cc: Eugen Hristev <eugen.hristev@microchip.com>
Reviewed-by: Heiko Schocher <hs@denx.de>
Tested on the taurus board:
Tested-by: Heiko Schocher <hs@denx.de>
drivers/watchdog/at91sam9_wdt.c

index 13f8772e4130ac1e273c920d211eefc4491f5eff..b0a3b4ed58636a945f7355d2ce0d33b791a7086c 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/io.h>
 #include <asm/arch/at91_wdt.h>
 #include <common.h>
+#include <div64.h>
 #include <dm.h>
 #include <errno.h>
 #include <wdt.h>
@@ -31,27 +32,30 @@ DECLARE_GLOBAL_DATA_PTR;
 #define WDT_SEC2TICKS(s)       (((s) << 8) - 1)
 
 /* Hardware timeout in seconds */
-#define WDT_MAX_TIMEOUT 16
-#define WDT_MIN_TIMEOUT 0
-#define WDT_DEFAULT_TIMEOUT 2
+#define WDT_MAX_TIMEOUT                16
+#define WDT_DEFAULT_TIMEOUT    2
 
 struct at91_wdt_priv {
        void __iomem *regs;
-       u32     regval;
-       u32     timeout;
+       u32 regval;
+       u32 timeout;
 };
 
 /*
  * Set the watchdog time interval in 1/256Hz (write-once)
  * Counter is 12 bit.
  */
-static int at91_wdt_start(struct udevice *dev, u64 timeout_s, ulong flags)
+static int at91_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
 {
        struct at91_wdt_priv *priv = dev_get_priv(dev);
-       u32 timeout = WDT_SEC2TICKS(timeout_s);
+       u64 timeout;
+       u32 ticks;
 
-       if (timeout_s > WDT_MAX_TIMEOUT || timeout_s < WDT_MIN_TIMEOUT)
-               timeout = priv->timeout;
+       /* Calculate timeout in seconds and the resulting ticks */
+       timeout = timeout_ms;
+       do_div(timeout, 1000);
+       timeout = min_t(u64, timeout, WDT_MAX_TIMEOUT);
+       ticks = WDT_SEC2TICKS(timeout);
 
        /* Check if disabled */
        if (readl(priv->regs + AT91_WDT_MR) & AT91_WDT_MR_WDDIS) {
@@ -65,12 +69,10 @@ static int at91_wdt_start(struct udevice *dev, u64 timeout_s, ulong flags)
         * Since WDV is a 12-bit counter, the maximum period is
         * 4096 / 256 = 16 seconds.
         */
-
        priv->regval = AT91_WDT_MR_WDRSTEN      /* causes watchdog reset */
                | AT91_WDT_MR_WDDBGHLT          /* disabled in debug mode */
                | AT91_WDT_MR_WDD(0xfff)        /* restart at any time */
-               | AT91_WDT_MR_WDV(timeout);     /* timer value */
-
+               | AT91_WDT_MR_WDV(ticks);       /* timer value */
        writel(priv->regval, priv->regs + AT91_WDT_MR);
 
        return 0;