Merge https://gitlab.denx.de/u-boot/custodians/u-boot-mpc85xx
[oweals/u-boot.git] / drivers / watchdog / orion_wdt.c
index a0df02d10382bb369415ecbd1f3335dfce7ee4e6..d33e2ac3dc19005dd045df17df40e262a47b9d94 100644 (file)
 
 #include <common.h>
 #include <dm.h>
+#include <clk.h>
+#include <log.h>
 #include <wdt.h>
+#include <linux/bitops.h>
+#include <linux/kernel.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
@@ -27,6 +31,8 @@ struct orion_wdt_priv {
        void __iomem *rstout;
        void __iomem *rstout_mask;
        u32 timeout;
+       unsigned long clk_rate;
+       struct clk clk;
 };
 
 #define RSTOUT_ENABLE_BIT              BIT(8)
@@ -44,17 +50,18 @@ static int orion_wdt_reset(struct udevice *dev)
        struct orion_wdt_priv *priv = dev_get_priv(dev);
 
        /* Reload watchdog duration */
-       writel(priv->timeout, priv->reg + priv->wdt_counter_offset);
+       writel(priv->clk_rate * priv->timeout,
+              priv->reg + priv->wdt_counter_offset);
 
        return 0;
 }
 
-static int orion_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+static int orion_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
 {
        struct orion_wdt_priv *priv = dev_get_priv(dev);
        u32 reg;
 
-       priv->timeout = (u32) timeout;
+       priv->timeout = DIV_ROUND_UP(timeout_ms, 1000);
 
        /* Enable the fixed watchdog clock input */
        reg = readl(priv->reg + TIMER_CTRL);
@@ -62,7 +69,8 @@ static int orion_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
        writel(reg, priv->reg + TIMER_CTRL);
 
        /* Set watchdog duration */
-       writel(priv->timeout, priv->reg + priv->wdt_counter_offset);
+       writel(priv->clk_rate * priv->timeout,
+              priv->reg + priv->wdt_counter_offset);
 
        /* Clear the watchdog expiration bit */
        reg = readl(priv->reg + TIMER_A370_STATUS);
@@ -114,9 +122,7 @@ static inline bool save_reg_from_ofdata(struct udevice *dev, int index,
        fdt_addr_t addr;
        fdt_size_t off;
 
-       addr = fdtdec_get_addr_size_auto_noparent(
-               gd->fdt_blob, dev_of_offset(dev), "reg", index, &off, true);
-
+       addr = devfdt_get_addr_size_index(dev, index, &off);
        if (addr == FDT_ADDR_T_NONE)
                return false;
 
@@ -149,9 +155,18 @@ err:
 
 static int orion_wdt_probe(struct udevice *dev)
 {
+       struct orion_wdt_priv *priv = dev_get_priv(dev);
+       int ret;
+
        debug("%s: Probing wdt%u\n", __func__, dev->seq);
        orion_wdt_stop(dev);
 
+       ret = clk_get_by_name(dev, "fixed", &priv->clk);
+       if (!ret)
+               priv->clk_rate = clk_get_rate(&priv->clk);
+       else
+               priv->clk_rate = 25000000;
+
        return 0;
 }