Merge https://source.denx.de/u-boot/custodians/u-boot-watchdog

CI: https://dev.azure.com/sr0718/u-boot/_build/results?buildId=378&view=results

* watchdog: gpio_wdt: add support for stoppable devices (Rasmus)
* watchdog: Add DaVinci's watchdog support (Bastien)
* cyclic: disentangling cyclic API from schedule() (Rasmus)
* watchdog: introduce separate SPL symbol for WDT_GPIO (Rasmus)
diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h
index d419824..5decf73 100644
--- a/arch/m68k/include/asm/ptrace.h
+++ b/arch/m68k/include/asm/ptrace.h
@@ -9,6 +9,8 @@
  */
 #ifndef __ASSEMBLY__
 
+#include <linux/types.h>
+
 struct pt_regs {
 	ulong d0;
 	ulong d1;
diff --git a/boot/cedit.c b/boot/cedit.c
index d12892f..d69290c 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -20,6 +20,7 @@
 #include <video.h>
 #include <linux/delay.h>
 #include "scene_internal.h"
+#include <u-boot/schedule.h>
 
 enum {
 	CMOS_MAX_BITS	= 2048,
diff --git a/common/cyclic.c b/common/cyclic.c
index ec38fad..196797f 100644
--- a/common/cyclic.c
+++ b/common/cyclic.c
@@ -15,6 +15,7 @@
 #include <linux/errno.h>
 #include <linux/list.h>
 #include <asm/global_data.h>
+#include <u-boot/schedule.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -44,7 +45,7 @@
 	hlist_del(&cyclic->list);
 }
 
-void cyclic_run(void)
+static void cyclic_run(void)
 {
 	struct cyclic_info *cyclic;
 	struct hlist_node *tmp;
diff --git a/doc/develop/cyclic.rst b/doc/develop/cyclic.rst
index 893c269..6f1da6f 100644
--- a/doc/develop/cyclic.rst
+++ b/doc/develop/cyclic.rst
@@ -49,8 +49,8 @@
 How is this cyclic functionality integrated /  executed?
 --------------------------------------------------------
 
-The cyclic infrastructure integrates the main function responsible for
-calling all registered cyclic functions cyclic_run() into the common
-WATCHDOG_RESET macro. This guarantees that cyclic_run() is executed
-very often, which is necessary for the cyclic functions to get scheduled
-and executed at their configured periods.
+The cyclic infrastructure integrates cyclic_run(), the main function
+responsible for calling all registered cyclic functions, into the
+common schedule() function. This guarantees that cyclic_run() is
+executed very often, which is necessary for the cyclic functions to
+get scheduled and executed at their configured periods.
diff --git a/drivers/ddr/altera/sdram_n5x.c b/drivers/ddr/altera/sdram_n5x.c
index db09986..d1fc93b 100644
--- a/drivers/ddr/altera/sdram_n5x.c
+++ b/drivers/ddr/altera/sdram_n5x.c
@@ -22,6 +22,7 @@
 #include <asm/io.h>
 #include <linux/err.h>
 #include <linux/sizes.h>
+#include <u-boot/schedule.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/drivers/ddr/altera/sdram_soc64.c b/drivers/ddr/altera/sdram_soc64.c
index 9e57c2e..10a8e64 100644
--- a/drivers/ddr/altera/sdram_soc64.c
+++ b/drivers/ddr/altera/sdram_soc64.c
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <dm/device_compat.h>
 #include <linux/sizes.h>
+#include <u-boot/schedule.h>
 
 #define PGTABLE_OFF	0x4000
 
diff --git a/drivers/i2c/rz_riic.c b/drivers/i2c/rz_riic.c
index 5f3f8d1..f292c82 100644
--- a/drivers/i2c/rz_riic.c
+++ b/drivers/i2c/rz_riic.c
@@ -14,6 +14,7 @@
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <reset.h>
+#include <u-boot/schedule.h>
 #include <wait_bit.h>
 
 #define RIIC_ICCR1	0x00
diff --git a/drivers/led/led_sw_blink.c b/drivers/led/led_sw_blink.c
index 06a43db..ee1546d 100644
--- a/drivers/led/led_sw_blink.c
+++ b/drivers/led/led_sw_blink.c
@@ -5,6 +5,7 @@
  * Author: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
  */
 
+#include <cyclic.h>
 #include <dm.h>
 #include <led.h>
 #include <time.h>
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 90bc565..0e45f0a 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -175,6 +175,13 @@
 	help
 	  Enable support for the watchdog timer in Dialog DA9063.
 
+config WDT_DAVINCI
+	bool "DaVinci watchdog timer support"
+	depends on WDT
+	help
+	  Select this to enable the watchdog timer for DaVinci SoCs such as the
+	  OMAP-L138.
+
 config WDT_GPIO
 	bool "External gpio watchdog support"
 	depends on WDT
@@ -184,6 +191,15 @@
 	  doc/device-tree-bindings/watchdog/gpio-wdt.txt for
 	  information on how to describe the watchdog in device tree.
 
+config SPL_WDT_GPIO
+	bool "External gpio watchdog support in SPL"
+	depends on SPL_WDT
+	depends on SPL_DM_GPIO
+	depends on SPL_OF_REAL
+	default WDT_GPIO
+	help
+	  Support for external watchdog fed by toggling a gpio in SPL.
+
 config WDT_MAX6370
 	bool "MAX6370 watchdog timer support"
 	depends on WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 51be6ab..0b107c0 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -30,8 +30,9 @@
 obj-$(CONFIG_WDT_ORION) += orion_wdt.o
 obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
 obj-$(CONFIG_WDT_DA9063) += da9063-wdt.o
+obj-$(CONFIG_WDT_DAVINCI) += davinci_wdt.o
 obj-$(CONFIG_WDT_FTWDT010) += ftwdt010_wdt.o
-obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o
+obj-$(CONFIG_$(SPL_TPL_)WDT_GPIO) += gpio_wdt.o
 obj-$(CONFIG_WDT_MAX6370) += max6370_wdt.o
 obj-$(CONFIG_WDT_MCF) += mcf_wdt.o
 obj-$(CONFIG_WDT_MESON_GXBB) += meson_gxbb_wdt.o
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
new file mode 100644
index 0000000..fa8d784
--- /dev/null
+++ b/drivers/watchdog/davinci_wdt.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * DaVinci Watchdog driver
+ *
+ */
+
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <wdt.h>
+
+/* Control Register */
+#define DAVINCI_WDT_ID			0x00
+#define DAVINCI_WDT_TIM12		0x10
+#define DAVINCI_WDT_TIM34		0x14
+#define DAVINCI_WDT_PRD12		0x18
+#define DAVINCI_WDT_PRD34		0x1C
+#define DAVINCI_WDT_TCR			0x20
+#define DAVINCI_WDT_TGCR		0x24
+#define DAVINCI_WDT_WDTCR		0x28
+
+#define DAVINCI_TCR_CONT_EN		BIT(7)
+
+#define DAVINCI_TGCR_PLUSEN		BIT(4)
+#define DAVINCI_TGCR_WDT_MODE		BIT(3)
+#define DAVINCI_TGCR_TIM34RS		BIT(1)
+#define DAVINCI_TGCR_TIM12RS		BIT(0)
+
+#define DAVINCI_WDTCR_INVALID_KEY	(0x5555 << 16)
+#define DAVINCI_WDTCR_WDKEY0		(0xA5C6 << 16)
+#define DAVINCI_WDTCR_WDKEY1		(0xDA7E << 16)
+#define DAVINCI_WDTCR_WDFLAG		BIT(15)
+#define DAVINCI_WDTCR_WDEN		BIT(14)
+
+#define DEFAULT_THRESHOLD		0xA03200000
+
+struct davinci_wdt_priv {
+	void __iomem *base;
+	struct clk *ref_clk;
+};
+
+static int davinci_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+	struct davinci_wdt_priv *priv = dev_get_priv(dev);
+	ulong rate = clk_get_rate(priv->ref_clk);
+	u64 threshold;
+
+	if (!rate)
+		threshold = DEFAULT_THRESHOLD;
+	else
+		threshold = rate * timeout_ms / 1000;
+
+	/* Reset control registers */
+	writel(0, priv->base + DAVINCI_WDT_TCR);
+	writel(0, priv->base + DAVINCI_WDT_TGCR);
+
+	/* Enable watchdog mode and timers */
+	writel(DAVINCI_TGCR_WDT_MODE | DAVINCI_TGCR_TIM12RS | DAVINCI_TGCR_TIM34RS,
+	       priv->base + DAVINCI_WDT_TGCR);
+
+	/* Reset counters */
+	writel(0, priv->base + DAVINCI_WDT_TIM12);
+	writel(0, priv->base + DAVINCI_WDT_TIM34);
+
+	/* Set timeout threshold */
+	writel(threshold & 0xFFFFFFFF, priv->base + DAVINCI_WDT_PRD12);
+	writel(threshold >> 32, priv->base + DAVINCI_WDT_PRD34);
+
+	/* Enable counter */
+	writel(DAVINCI_TCR_CONT_EN, priv->base + DAVINCI_WDT_TCR);
+
+	/* Go to watchdog's active state */
+	writel(DAVINCI_WDTCR_WDEN | DAVINCI_WDTCR_WDKEY0, priv->base + DAVINCI_WDT_WDTCR);
+	writel(DAVINCI_WDTCR_WDEN | DAVINCI_WDTCR_WDKEY1, priv->base + DAVINCI_WDT_WDTCR);
+
+	return 0;
+}
+
+static int davinci_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	struct davinci_wdt_priv *priv = dev_get_priv(dev);
+
+	writel(DAVINCI_WDTCR_INVALID_KEY, priv->base + DAVINCI_WDT_WDTCR);
+
+	return 0;
+}
+
+static int davinci_wdt_restart(struct udevice *dev)
+{
+	struct davinci_wdt_priv *priv = dev_get_priv(dev);
+
+	writel(DAVINCI_WDTCR_WDEN | DAVINCI_WDTCR_WDKEY0, priv->base + DAVINCI_WDT_WDTCR);
+	writel(DAVINCI_WDTCR_WDEN | DAVINCI_WDTCR_WDKEY1, priv->base + DAVINCI_WDT_WDTCR);
+
+	return 0;
+}
+
+static int davinci_wdt_probe(struct udevice *dev)
+{
+	struct davinci_wdt_priv *priv = dev_get_priv(dev);
+
+	priv->base = dev_remap_addr_index(dev, 0);
+	if (!priv->base)
+		return -EFAULT;
+
+	priv->ref_clk = devm_clk_get(dev, "ref");
+	if (IS_ERR(priv->ref_clk))
+		return PTR_ERR(priv->ref_clk);
+
+	return 0;
+}
+
+static const struct wdt_ops davinci_wdt_ops = {
+	.start = davinci_wdt_start,
+	.reset = davinci_wdt_restart,
+	.expire_now = davinci_wdt_expire_now,
+};
+
+static const struct udevice_id davinci_wdt_ids[] = {
+	{.compatible = "ti,davinci-wdt"},
+	{}
+};
+
+U_BOOT_DRIVER(davinci_wdt) = {
+	.name = "davinci_wdt",
+	.id = UCLASS_WDT,
+	.probe = davinci_wdt_probe,
+	.of_match = davinci_wdt_ids,
+	.ops = &davinci_wdt_ops,
+	.priv_auto = sizeof(struct davinci_wdt_priv),
+};
diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c
index 2920c2c..e889861 100644
--- a/drivers/watchdog/gpio_wdt.c
+++ b/drivers/watchdog/gpio_wdt.c
@@ -45,14 +45,32 @@
 	if (priv->always_running)
 		return 0;
 
-	return -ENOSYS;
+	dm_gpio_set_dir_flags(&priv->gpio, GPIOD_IS_OUT);
+	gpio_wdt_reset(dev);
+
+	return 0;
+}
+
+static int gpio_wdt_stop(struct udevice *dev)
+{
+	struct gpio_wdt_priv *priv = dev_get_priv(dev);
+
+	if (priv->always_running)
+		return -EOPNOTSUPP;
+
+	if (priv->hw_algo == HW_ALGO_TOGGLE)
+		dm_gpio_set_dir_flags(&priv->gpio, GPIOD_IS_IN);
+	else
+		dm_gpio_set_value(&priv->gpio, 1);
+
+	return 0;
 }
 
 static int dm_probe(struct udevice *dev)
 {
 	struct gpio_wdt_priv *priv = dev_get_priv(dev);
-	int ret;
 	const char *algo = dev_read_string(dev, "hw_algo");
+	int ret, flags;
 
 	if (!algo)
 		return -EINVAL;
@@ -64,7 +82,9 @@
 		return -EINVAL;
 
 	priv->always_running = dev_read_bool(dev, "always-running");
-	ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT);
+	flags = priv->always_running || priv->hw_algo == HW_ALGO_LEVEL ?
+		GPIOD_IS_OUT : GPIOD_IS_IN;
+	ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, flags);
 	if (ret < 0) {
 		dev_err(dev, "Request for wdt gpio failed: %d\n", ret);
 		return ret;
@@ -78,6 +98,7 @@
 
 static const struct wdt_ops gpio_wdt_ops = {
 	.start = gpio_wdt_start,
+	.stop  = gpio_wdt_stop,
 	.reset = gpio_wdt_reset,
 };
 
diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c
index 2141edf..97af8cb 100644
--- a/fs/cramfs/uncompress.c
+++ b/fs/cramfs/uncompress.c
@@ -21,9 +21,9 @@
  */
 
 #include <stdio.h>
-#include <cyclic.h>
 #include <malloc.h>
 #include <watchdog.h>
+#include <u-boot/schedule.h>
 #include <u-boot/zlib.h>
 
 static z_stream stream;
@@ -63,7 +63,7 @@
 	stream.avail_in = 0;
 
 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
-	stream.outcb = (cb_func)cyclic_run;
+	stream.outcb = (cb_func)schedule;
 #else
 	stream.outcb = Z_NULL;
 #endif /* CONFIG_HW_WATCHDOG */
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 644a0d7..b84cc5b 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -21,7 +21,6 @@
 
 #ifndef __ASSEMBLY__
 #include <board_f.h>
-#include <cyclic.h>
 #include <event_internal.h>
 #include <fdtdec.h>
 #include <membuff.h>
diff --git a/include/cyclic.h b/include/cyclic.h
index cd95b69..c6c463d 100644
--- a/include/cyclic.h
+++ b/include/cyclic.h
@@ -13,6 +13,7 @@
 
 #include <linux/list.h>
 #include <asm/types.h>
+#include <u-boot/schedule.h> // to be removed later
 
 /**
  * struct cyclic_info - Information about cyclic execution function
@@ -86,21 +87,6 @@
  */
 struct hlist_head *cyclic_get_list(void);
 
-/**
- * cyclic_run() - Interate over all registered cyclic functions
- *
- * Interate over all registered cyclic functions and if the it's function
- * needs to be executed, then call into these registered functions.
- */
-void cyclic_run(void);
-
-/**
- * schedule() - Schedule all potentially waiting tasks
- *
- * Basically a wrapper for cyclic_run(), pontentially enhanced by some
- * other parts, that need to get handled periodically.
- */
-void schedule(void);
 #else
 
 static inline void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func,
@@ -112,14 +98,6 @@
 {
 }
 
-static inline void cyclic_run(void)
-{
-}
-
-static inline void schedule(void)
-{
-}
-
 static inline int cyclic_unregister_all(void)
 {
 	return 0;
diff --git a/include/u-boot/schedule.h b/include/u-boot/schedule.h
new file mode 100644
index 0000000..4fd34c4
--- /dev/null
+++ b/include/u-boot/schedule.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _U_BOOT_SCHEDULE_H
+#define _U_BOOT_SCHEDULE_H
+
+#if CONFIG_IS_ENABLED(CYCLIC)
+/**
+ * schedule() - Schedule all potentially waiting tasks
+ *
+ * Run all pending tasks registered via the cyclic framework, and
+ * potentially perform other actions that need to be done
+ * periodically.
+ */
+void schedule(void);
+
+#else
+
+static inline void schedule(void)
+{
+}
+
+#endif
+
+#endif
diff --git a/include/watchdog.h b/include/watchdog.h
index d1956fa..0149b44 100644
--- a/include/watchdog.h
+++ b/include/watchdog.h
@@ -10,7 +10,7 @@
 #ifndef _WATCHDOG_H_
 #define _WATCHDOG_H_
 
-#include <cyclic.h>
+#include <u-boot/schedule.h> // to be removed later
 
 /*
  * Reset the watchdog timer, always returns 0
diff --git a/lib/sha1.c b/lib/sha1.c
index 8141228..a9d6497 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -17,7 +17,7 @@
 #endif
 
 #ifndef USE_HOSTCC
-#include <cyclic.h>
+#include <u-boot/schedule.h>
 #endif /* USE_HOSTCC */
 #include <string.h>
 #include <u-boot/sha1.h>
diff --git a/lib/sha256.c b/lib/sha256.c
index 665ba6f..329802f 100644
--- a/lib/sha256.c
+++ b/lib/sha256.c
@@ -6,7 +6,7 @@
  */
 
 #ifndef USE_HOSTCC
-#include <cyclic.h>
+#include <u-boot/schedule.h>
 #endif /* USE_HOSTCC */
 #include <string.h>
 #include <u-boot/sha256.h>
diff --git a/lib/sha512.c b/lib/sha512.c
index ffe2c5c..ea555ff 100644
--- a/lib/sha512.c
+++ b/lib/sha512.c
@@ -11,7 +11,7 @@
  */
 
 #ifndef USE_HOSTCC
-#include <cyclic.h>
+#include <u-boot/schedule.h>
 #endif /* USE_HOSTCC */
 #include <compiler.h>
 #include <u-boot/sha512.h>
diff --git a/test/dm/wdt.c b/test/dm/wdt.c
index 541bcba..bef2959 100644
--- a/test/dm/wdt.c
+++ b/test/dm/wdt.c
@@ -3,7 +3,6 @@
  * Copyright 2017 Google, Inc
  */
 
-#include <cyclic.h>
 #include <dm.h>
 #include <time.h>
 #include <wdt.h>
@@ -14,6 +13,7 @@
 #include <test/test.h>
 #include <test/ut.h>
 #include <linux/delay.h>
+#include <u-boot/schedule.h>
 #include <watchdog.h>
 
 /* Test that watchdog driver functions are called */
@@ -71,7 +71,7 @@
 	ut_assertok(wdt_reset(wdt));
 	ut_asserteq(val, sandbox_gpio_get_value(gpio, offset));
 
-	ut_asserteq(-ENOSYS, wdt_stop(wdt));
+	ut_asserteq(-EOPNOTSUPP, wdt_stop(wdt));
 
 	return 0;
 }
@@ -103,7 +103,7 @@
 	ut_assertok(wdt_reset(wdt));
 	ut_asserteq(val, sandbox_gpio_get_value(gpio, offset));
 
-	ut_asserteq(-ENOSYS, wdt_stop(wdt));
+	ut_asserteq(-EOPNOTSUPP, wdt_stop(wdt));
 
 	return 0;
 }
@@ -131,7 +131,7 @@
 	/* Neither device should be "started", so watchdog_reset() should be a no-op. */
 	reset_count = state->wdt.reset_count;
 	val = sandbox_gpio_get_value(gpio, offset);
-	cyclic_run();
+	schedule();
 	ut_asserteq(reset_count, state->wdt.reset_count);
 	ut_asserteq(val, sandbox_gpio_get_value(gpio, offset));
 
@@ -141,19 +141,19 @@
 
 	/* Make sure both devices have just been pinged. */
 	timer_test_add_offset(100);
-	cyclic_run();
+	schedule();
 	reset_count = state->wdt.reset_count;
 	val = sandbox_gpio_get_value(gpio, offset);
 
 	/* The gpio watchdog should be pinged, the sandbox one not. */
 	timer_test_add_offset(30);
-	cyclic_run();
+	schedule();
 	ut_asserteq(reset_count, state->wdt.reset_count);
 	ut_asserteq(!val, sandbox_gpio_get_value(gpio, offset));
 
 	/* After another ~30ms, both devices should get pinged. */
 	timer_test_add_offset(30);
-	cyclic_run();
+	schedule();
 	ut_asserteq(reset_count + 1, state->wdt.reset_count);
 	ut_asserteq(val, sandbox_gpio_get_value(gpio, offset));