aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/dts/socfpga_cyclone5_vining_fpga-u-boot.dtsi4
-rwxr-xr-xarch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi4
-rw-r--r--configs/socfpga_stratix10_defconfig3
-rw-r--r--configs/socfpga_vining_fpga_defconfig2
-rw-r--r--drivers/watchdog/Kconfig2
-rw-r--r--drivers/watchdog/designware_wdt.c122
-rw-r--r--include/configs/socfpga_soc64_common.h4
7 files changed, 112 insertions, 29 deletions
diff --git a/arch/arm/dts/socfpga_cyclone5_vining_fpga-u-boot.dtsi b/arch/arm/dts/socfpga_cyclone5_vining_fpga-u-boot.dtsi
index 44bedd8..2e4468e 100644
--- a/arch/arm/dts/socfpga_cyclone5_vining_fpga-u-boot.dtsi
+++ b/arch/arm/dts/socfpga_cyclone5_vining_fpga-u-boot.dtsi
@@ -56,3 +56,7 @@
&portc {
bank-name = "portc";
};
+
+&watchdog0 {
+ u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi b/arch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi
index 38855ae..a903040 100755
--- a/arch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi
+++ b/arch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi
@@ -31,3 +31,7 @@
&sysmgr {
u-boot,dm-pre-reloc;
};
+
+&watchdog0 {
+ u-boot,dm-pre-reloc;
+};
diff --git a/configs/socfpga_stratix10_defconfig b/configs/socfpga_stratix10_defconfig
index a83d991..26db40f 100644
--- a/configs/socfpga_stratix10_defconfig
+++ b/configs/socfpga_stratix10_defconfig
@@ -58,5 +58,6 @@ CONFIG_USB=y
CONFIG_DM_USB=y
CONFIG_USB_DWC2=y
CONFIG_USB_STORAGE=y
-# CONFIG_SPL_USE_TINY_PRINTF is not set
CONFIG_DESIGNWARE_WATCHDOG=y
+CONFIG_WDT=y
+# CONFIG_SPL_USE_TINY_PRINTF is not set
diff --git a/configs/socfpga_vining_fpga_defconfig b/configs/socfpga_vining_fpga_defconfig
index 85c458a..0dcae81 100644
--- a/configs/socfpga_vining_fpga_defconfig
+++ b/configs/socfpga_vining_fpga_defconfig
@@ -96,5 +96,5 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0525
CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
CONFIG_USB_GADGET_DWC2_OTG=y
CONFIG_USB_GADGET_DOWNLOAD=y
-# CONFIG_SPL_WDT is not set
CONFIG_DESIGNWARE_WATCHDOG=y
+CONFIG_WDT=y
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index c9987d4..77354ad 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -47,7 +47,7 @@ config ULP_WATCHDOG
config DESIGNWARE_WATCHDOG
bool "Designware watchdog timer support"
- select HW_WATCHDOG
+ select HW_WATCHDOG if !WDT
help
Enable this to support Designware Watchdog Timer IP, present e.g.
on Altera SoCFPGA SoCs.
diff --git a/drivers/watchdog/designware_wdt.c b/drivers/watchdog/designware_wdt.c
index c668567..a7b7359 100644
--- a/drivers/watchdog/designware_wdt.c
+++ b/drivers/watchdog/designware_wdt.c
@@ -4,7 +4,8 @@
*/
#include <common.h>
-#include <watchdog.h>
+#include <dm.h>
+#include <wdt.h>
#include <asm/io.h>
#include <asm/utils.h>
@@ -17,46 +18,51 @@
#define DW_WDT_CR_RMOD_VAL 0x00
#define DW_WDT_CRR_RESTART_VAL 0x76
+struct designware_wdt_priv {
+ void __iomem *base;
+};
+
/*
* Set the watchdog time interval.
* Counter is 32 bit.
*/
-static int designware_wdt_settimeout(unsigned int timeout)
+static int designware_wdt_settimeout(void __iomem *base, unsigned int clk_khz,
+ unsigned int timeout)
{
signed int i;
/* calculate the timeout range value */
- i = (log_2_n_round_up(timeout * CONFIG_DW_WDT_CLOCK_KHZ)) - 16;
- if (i > 15)
- i = 15;
- if (i < 0)
- i = 0;
+ i = log_2_n_round_up(timeout * clk_khz) - 16;
+ i = clamp(i, 0, 15);
+
+ writel(i | (i << 4), base + DW_WDT_TORR);
- writel((i | (i << 4)), (CONFIG_DW_WDT_BASE + DW_WDT_TORR));
return 0;
}
-static void designware_wdt_enable(void)
+static void designware_wdt_enable(void __iomem *base)
{
- writel(((DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET) |
- (0x1 << DW_WDT_CR_EN_OFFSET)),
- (CONFIG_DW_WDT_BASE + DW_WDT_CR));
+ writel((DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET) |
+ BIT(DW_WDT_CR_EN_OFFSET),
+ base + DW_WDT_CR);
}
-static unsigned int designware_wdt_is_enabled(void)
+static unsigned int designware_wdt_is_enabled(void __iomem *base)
{
- unsigned long val;
- val = readl((CONFIG_DW_WDT_BASE + DW_WDT_CR));
- return val & 0x1;
+ return readl(base + DW_WDT_CR) & BIT(0);
}
-#if defined(CONFIG_HW_WATCHDOG)
-void hw_watchdog_reset(void)
+static void designware_wdt_reset_common(void __iomem *base)
{
- if (designware_wdt_is_enabled())
+ if (designware_wdt_is_enabled(base))
/* restart the watchdog counter */
- writel(DW_WDT_CRR_RESTART_VAL,
- (CONFIG_DW_WDT_BASE + DW_WDT_CRR));
+ writel(DW_WDT_CRR_RESTART_VAL, base + DW_WDT_CRR);
+}
+
+#if !CONFIG_IS_ENABLED(WDT)
+void hw_watchdog_reset(void)
+{
+ designware_wdt_reset_common((void __iomem *)CONFIG_DW_WDT_BASE);
}
void hw_watchdog_init(void)
@@ -64,10 +70,80 @@ void hw_watchdog_init(void)
/* reset to disable the watchdog */
hw_watchdog_reset();
/* set timer in miliseconds */
- designware_wdt_settimeout(CONFIG_WATCHDOG_TIMEOUT_MSECS);
+ designware_wdt_settimeout((void __iomem *)CONFIG_DW_WDT_BASE,
+ CONFIG_DW_WDT_CLOCK_KHZ,
+ CONFIG_WATCHDOG_TIMEOUT_MSECS);
/* enable the watchdog */
- designware_wdt_enable();
+ designware_wdt_enable((void __iomem *)CONFIG_DW_WDT_BASE);
/* reset the watchdog */
hw_watchdog_reset();
}
+#else
+static int designware_wdt_reset(struct udevice *dev)
+{
+ struct designware_wdt_priv *priv = dev_get_priv(dev);
+
+ designware_wdt_reset_common(priv->base);
+
+ return 0;
+}
+
+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);
+
+ return 0;
+}
+
+static int designware_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+ struct designware_wdt_priv *priv = dev_get_priv(dev);
+
+ designware_wdt_stop(dev);
+
+ /* set timer in miliseconds */
+ designware_wdt_settimeout(priv->base, CONFIG_DW_WDT_CLOCK_KHZ, timeout);
+
+ designware_wdt_enable(priv->base);
+
+ /* reset the watchdog */
+ return designware_wdt_reset(dev);
+}
+
+static int designware_wdt_probe(struct udevice *dev)
+{
+ struct designware_wdt_priv *priv = dev_get_priv(dev);
+
+ priv->base = dev_remap_addr(dev);
+ if (!priv->base)
+ return -EINVAL;
+
+ /* reset to disable the watchdog */
+ return designware_wdt_stop(dev);
+}
+
+static const struct wdt_ops designware_wdt_ops = {
+ .start = designware_wdt_start,
+ .reset = designware_wdt_reset,
+ .stop = designware_wdt_stop,
+};
+
+static const struct udevice_id designware_wdt_ids[] = {
+ { .compatible = "snps,dw-wdt"},
+ {}
+};
+
+U_BOOT_DRIVER(designware_wdt) = {
+ .name = "designware_wdt",
+ .id = UCLASS_WDT,
+ .of_match = designware_wdt_ids,
+ .priv_auto_alloc_size = sizeof(struct designware_wdt_priv),
+ .probe = designware_wdt_probe,
+ .ops = &designware_wdt_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
#endif
diff --git a/include/configs/socfpga_soc64_common.h b/include/configs/socfpga_soc64_common.h
index ac7c005..87c7345 100644
--- a/include/configs/socfpga_soc64_common.h
+++ b/include/configs/socfpga_soc64_common.h
@@ -150,9 +150,7 @@ unsigned int cm_get_qspi_controller_clk_hz(void);
/*
* L4 Watchdog
*/
-#ifdef CONFIG_SPL_BUILD
-#define CONFIG_HW_WATCHDOG
-#else
+#ifndef CONFIG_SPL_BUILD
#undef CONFIG_HW_WATCHDOG
#undef CONFIG_DESIGNWARE_WATCHDOG
#endif