Merge https://source.denx.de/u-boot/custodians/u-boot-samsung
[platform/kernel/u-boot.git] / drivers / watchdog / orion_wdt.c
index a0df02d..c30ed82 100644 (file)
@@ -4,8 +4,8 @@
  * Watchdog driver for Orion/Kirkwood processors
  *
  * Authors:    Tomas Hlavacek <tmshlvck@gmail.com>
- *             Sylver Bruneau <sylver.bruneau@googlemail.com>
- *             Marek Behun <marek.behun@nic.cz>
+ *             Sylver Bruneau <sylver.bruneau@googlemail.com>
+ *             Marek Behun <marek.behun@nic.cz>
  *
  * This file is licensed under  the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
 
 #include <common.h>
 #include <dm.h>
+#include <clk.h>
+#include <log.h>
 #include <wdt.h>
+#include <asm/global_data.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 +32,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 +51,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 +70,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 +123,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;
 
@@ -127,7 +134,7 @@ static inline bool save_reg_from_ofdata(struct udevice *dev, int index,
        return true;
 }
 
-static int orion_wdt_ofdata_to_platdata(struct udevice *dev)
+static int orion_wdt_of_to_plat(struct udevice *dev)
 {
        struct orion_wdt_priv *priv = dev_get_priv(dev);
 
@@ -149,9 +156,18 @@ err:
 
 static int orion_wdt_probe(struct udevice *dev)
 {
-       debug("%s: Probing wdt%u\n", __func__, dev->seq);
+       struct orion_wdt_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       debug("%s: Probing wdt%u\n", __func__, dev_seq(dev));
        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;
 }
 
@@ -171,7 +187,7 @@ U_BOOT_DRIVER(orion_wdt) = {
        .id = UCLASS_WDT,
        .of_match = orion_wdt_ids,
        .probe = orion_wdt_probe,
-       .priv_auto_alloc_size = sizeof(struct orion_wdt_priv),
-       .ofdata_to_platdata = orion_wdt_ofdata_to_platdata,
+       .priv_auto      = sizeof(struct orion_wdt_priv),
+       .of_to_plat = orion_wdt_of_to_plat,
        .ops = &orion_wdt_ops,
 };