summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Vasut <marex@denx.de>2019-10-03 14:47:07 +0200
committerMarek Vasut <marex@denx.de>2020-02-05 03:01:57 +0100
commitcf89ef8d10f240554541c20b2e1bdcdd58d1d7e6 (patch)
tree21d5696946d525f937cbe0e9618330c1657cba42
parentcf8c8367884c32844bb002bf6eba02e72a0d75b2 (diff)
downloadu-boot-cf89ef8d10f240554541c20b2e1bdcdd58d1d7e6.tar.gz
watchdog: designware: Optionally fetch clock and reset from DT
Add optional support for fetching watchdog clock rate from DT and ungating reset via reset framework. This is optional as not all platforms using DW WDT support the clock and reset frameworks yet. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chin Liang See <chin.liang.see@intel.com> Cc: Dalon Westergreen <dwesterg@gmail.com> Cc: Dinh Nguyen <dinguyen@kernel.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Ley Foon Tan <ley.foon.tan@intel.com> Cc: Philipp Tomisch <philipp.tomisch@theobroma-systems.com> Cc: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com> Cc: Tien Fong Chee <tien.fong.chee@intel.com> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com> Tested-by: Jagan Teki <jagan@amarulasolutions.com> # roc-rk3399-pc
-rw-r--r--drivers/watchdog/designware_wdt.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/drivers/watchdog/designware_wdt.c b/drivers/watchdog/designware_wdt.c
index a7b735979a..1024a04596 100644
--- a/drivers/watchdog/designware_wdt.c
+++ b/drivers/watchdog/designware_wdt.c
@@ -3,8 +3,10 @@
* Copyright (C) 2013 Altera Corporation <www.altera.com>
*/
+#include <clk.h>
#include <common.h>
#include <dm.h>
+#include <reset.h>
#include <wdt.h>
#include <asm/io.h>
#include <asm/utils.h>
@@ -15,11 +17,11 @@
#define DW_WDT_CR_EN_OFFSET 0x00
#define DW_WDT_CR_RMOD_OFFSET 0x01
-#define DW_WDT_CR_RMOD_VAL 0x00
#define DW_WDT_CRR_RESTART_VAL 0x76
struct designware_wdt_priv {
void __iomem *base;
+ unsigned int clk_khz;
};
/*
@@ -42,9 +44,7 @@ static int designware_wdt_settimeout(void __iomem *base, unsigned int clk_khz,
static void designware_wdt_enable(void __iomem *base)
{
- writel((DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET) |
- BIT(DW_WDT_CR_EN_OFFSET),
- base + DW_WDT_CR);
+ writel(BIT(DW_WDT_CR_EN_OFFSET), base + DW_WDT_CR);
}
static unsigned int designware_wdt_is_enabled(void __iomem *base)
@@ -93,8 +93,7 @@ static int designware_wdt_stop(struct udevice *dev)
struct designware_wdt_priv *priv = dev_get_priv(dev);
designware_wdt_reset(dev);
- writel(DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET,
- priv->base + DW_WDT_CR);
+ writel(0, priv->base + DW_WDT_CR);
return 0;
}
@@ -106,7 +105,7 @@ static int designware_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
designware_wdt_stop(dev);
/* set timer in miliseconds */
- designware_wdt_settimeout(priv->base, CONFIG_DW_WDT_CLOCK_KHZ, timeout);
+ designware_wdt_settimeout(priv->base, priv->clk_khz, timeout);
designware_wdt_enable(priv->base);
@@ -117,11 +116,38 @@ static int designware_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
static int designware_wdt_probe(struct udevice *dev)
{
struct designware_wdt_priv *priv = dev_get_priv(dev);
+ __maybe_unused int ret;
priv->base = dev_remap_addr(dev);
if (!priv->base)
return -EINVAL;
+#if CONFIG_IS_ENABLED(CLK)
+ struct clk clk;
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret)
+ return ret;
+
+ priv->clk_khz = clk_get_rate(&clk);
+ if (!priv->clk_khz)
+ return -EINVAL;
+#else
+ priv->clk_khz = CONFIG_DW_WDT_CLOCK_KHZ;
+#endif
+
+#if CONFIG_IS_ENABLED(DM_RESET)
+ struct reset_ctl_bulk resets;
+
+ ret = reset_get_bulk(dev, &resets);
+ if (ret)
+ return ret;
+
+ ret = reset_deassert_bulk(&resets);
+ if (ret)
+ return ret;
+#endif
+
/* reset to disable the watchdog */
return designware_wdt_stop(dev);
}