public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Maxim Sloyko <maxims@google.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2 02/15] dm: Simple Watchdog uclass
Date: Fri,  5 May 2017 15:01:02 -0700	[thread overview]
Message-ID: <20170505220115.143025-3-maxims@google.com> (raw)
In-Reply-To: <20170505220115.143025-1-maxims@google.com>

This is a simple uclass for Watchdog Timers. It has four operations:
start, restart, reset, stop. Drivers must implement start, restart and
stop operations, while implementing reset is optional: It's default
implementation expires watchdog timer in one clock tick.

Signed-off-by: Maxim Sloyko <maxims@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v2:
- Remove "probe" function from sandbox wdt driver
- Fix include order

Changes in v1:
- Rename wdt_reset to wdt_expire_now
- Rename wdt_restart to wdt_reset
- Clarified function documentation in few cases
- Add Sandbox WDT driver and unit tests


---
 arch/sandbox/dts/test.dts        |   4 ++
 arch/sandbox/include/asm/state.h |   9 ++++
 configs/sandbox_defconfig        |   2 +
 drivers/watchdog/Kconfig         |  21 ++++++++
 drivers/watchdog/Makefile        |   2 +
 drivers/watchdog/sandbox_wdt.c   |  66 ++++++++++++++++++++++++
 drivers/watchdog/wdt-uclass.c    |  72 ++++++++++++++++++++++++++
 include/dm/uclass-id.h           |   1 +
 include/wdt.h                    | 107 +++++++++++++++++++++++++++++++++++++++
 test/dm/Makefile                 |   1 +
 test/dm/wdt.c                    |  40 +++++++++++++++
 11 files changed, 325 insertions(+)
 create mode 100644 drivers/watchdog/sandbox_wdt.c
 create mode 100644 drivers/watchdog/wdt-uclass.c
 create mode 100644 include/wdt.h
 create mode 100644 test/dm/wdt.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index fff175d1b7..e04ecc64cc 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -418,6 +418,10 @@
 			};
 		};
 	};
+
+	wdt0: wdt at 0 {
+		compatible = "sandbox,wdt";
+	};
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 149f28d873..987cc7b49d 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -39,6 +39,12 @@ struct sandbox_spi_info {
 	struct udevice *emul;
 };
 
+struct sandbox_wdt_info {
+	unsigned long long counter;
+	uint reset_count;
+	bool running;
+};
+
 /* The complete state of the test system */
 struct sandbox_state {
 	const char *cmd;		/* Command to execute */
@@ -69,6 +75,9 @@ struct sandbox_state {
 	/* Pointer to information for each SPI bus/cs */
 	struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
 					[CONFIG_SANDBOX_SPI_MAX_CS];
+
+	/* Information about Watchdog */
+	struct sandbox_wdt_info wdt;
 };
 
 /* Minimum space we guarantee in the state FDT when calling read/write*/
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 01f6f5d5c6..a5f63e027f 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -171,3 +171,5 @@ CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
+CONFIG_WDT=y
+CONFIG_WDT_SANDBOX=y
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e69de29bb2..7a725f1e6d 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -0,0 +1,21 @@
+menu "Watchdog Timer Support"
+
+config WDT
+	bool "Enable driver model for watchdog timer drivers"
+	depends on DM
+	help
+	  Enable driver model for watchdog timer. At the moment the API
+	  is very simple and only supports four operations:
+	  start, restart, stop and reset (expire immediately).
+	  What exactly happens when the timer expires is up to a particular
+	  device/driver.
+
+config WDT_SANDBOX
+	bool "Enable Watchdog Timer support for Sandbox"
+	depends on SANDBOX && WDT
+	help
+		Enable Watchdog Timer support in Sandbox. This is a dummy device that
+		can be probed and supports all of the methods of WDT, but does not
+		really do anything.
+
+endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index a007ae8234..f523d34d57 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -15,3 +15,5 @@ obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
 obj-$(CONFIG_BFIN_WATCHDOG)  += bfin_wdt.o
 obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
+obj-$(CONFIG_WDT) += wdt-uclass.o
+obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
diff --git a/drivers/watchdog/sandbox_wdt.c b/drivers/watchdog/sandbox_wdt.c
new file mode 100644
index 0000000000..02b57f3986
--- /dev/null
+++ b/drivers/watchdog/sandbox_wdt.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <asm/state.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sandbox_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.counter = timeout;
+	state->wdt.running = true;
+
+	return 0;
+}
+
+static int sandbox_wdt_stop(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.running = false;
+
+	return 0;
+}
+
+static int sandbox_wdt_reset(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	state->wdt.reset_count++;
+
+	return 0;
+}
+
+static int sandbox_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	sandbox_wdt_start(dev, 1, flags);
+
+	return 0;
+}
+
+static const struct wdt_ops sandbox_wdt_ops = {
+	.start = sandbox_wdt_start,
+	.reset = sandbox_wdt_reset,
+	.stop = sandbox_wdt_stop,
+	.expire_now = sandbox_wdt_expire_now,
+};
+
+static const struct udevice_id sandbox_wdt_ids[] = {
+	{ .compatible = "sandbox,wdt" },
+	{}
+};
+
+U_BOOT_DRIVER(wdt_sandbox) = {
+	.name = "wdt_sandbox",
+	.id = UCLASS_WDT,
+	.of_match = sandbox_wdt_ids,
+	.ops = &sandbox_wdt_ops,
+};
diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c
new file mode 100644
index 0000000000..ab8a64c354
--- /dev/null
+++ b/drivers/watchdog/wdt-uclass.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <wdt.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->start)
+		return -ENOSYS;
+
+	return ops->start(dev, timeout, flags);
+}
+
+int wdt_stop(struct udevice *dev)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->stop)
+		return -ENOSYS;
+
+	return ops->stop(dev);
+}
+
+int wdt_reset(struct udevice *dev)
+{
+	const struct wdt_ops *ops = device_get_ops(dev);
+
+	if (!ops->reset)
+		return -ENOSYS;
+
+	return ops->reset(dev);
+}
+
+int wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	int ret = 0;
+	const struct wdt_ops *ops;
+
+	debug("WDT Resettting: %lu\n", flags);
+	ops = device_get_ops(dev);
+	if (ops->expire_now) {
+		return ops->expire_now(dev, flags);
+	} else {
+		if (!ops->start)
+			return -ENOSYS;
+
+		ret = ops->start(dev, 1, flags);
+		if (ret < 0)
+			return ret;
+
+		hang();
+	}
+
+	return ret;
+}
+
+UCLASS_DRIVER(wdt) = {
+	.id		= UCLASS_WDT,
+	.name		= "wdt",
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 8c92d0b030..b73a7fd436 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -83,6 +83,7 @@ enum uclass_id {
 	UCLASS_VIDEO,		/* Video or LCD device */
 	UCLASS_VIDEO_BRIDGE,	/* Video bridge, e.g. DisplayPort to LVDS */
 	UCLASS_VIDEO_CONSOLE,	/* Text console driver for video device */
+	UCLASS_WDT,		/* Watchdot Timer driver */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/wdt.h b/include/wdt.h
new file mode 100644
index 0000000000..0b5f05851a
--- /dev/null
+++ b/include/wdt.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _WDT_H_
+#define _WDT_H_
+
+/*
+ * Implement a simple watchdog uclass. Watchdog is basically a timer that
+ * is used to detect or recover from malfunction. During normal operation
+ * the watchdog would be regularly reset to prevent it from timing out.
+ * If, due to a hardware fault or program error, the computer fails to reset
+ * the watchdog, the timer will elapse and generate a timeout signal.
+ * The timeout signal is used to initiate corrective action or actions,
+ * which typically include placing the system in a safe, known state.
+ */
+
+/*
+ * Start the timer
+ *
+ * @dev: WDT Device
+ * @timeout: Number of ticks before timer expires
+ * @flags: Driver specific flags. This might be used to specify
+ * which action needs to be executed when the timer expires
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_start(struct udevice *dev, u64 timeout, ulong flags);
+
+/*
+ * Stop the timer, thus disabling the Watchdog. Use wdt_start to start it again.
+ *
+ * @dev: WDT Device
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_stop(struct udevice *dev);
+
+/*
+ * Reset the timer, typically restoring the counter to
+ * the value configured by start()
+ *
+ * @dev: WDT Device
+ * @return: 0 if OK, -ve on error
+ */
+int wdt_reset(struct udevice *dev);
+
+/*
+ * Expire the timer, thus executing its action immediately.
+ * This is typically used to reset the board or peripherals.
+ *
+ * @dev: WDT Device
+ * @flags: Driver specific flags
+ * @return 0 if OK -ve on error. If wdt action is system reset,
+ * this function may never return.
+ */
+int wdt_expire_now(struct udevice *dev, ulong flags);
+
+/*
+ * struct wdt_ops - Driver model wdt operations
+ *
+ * The uclass interface is implemented by all wdt devices which use
+ * driver model.
+ */
+struct wdt_ops {
+	/*
+	 * Start the timer
+	 *
+	 * @dev: WDT Device
+	 * @timeout: Number of ticks before the timer expires
+	 * @flags: Driver specific flags. This might be used to specify
+	 * which action needs to be executed when the timer expires
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*start)(struct udevice *dev, u64 timeout, ulong flags);
+	/*
+	 * Stop the timer
+	 *
+	 * @dev: WDT Device
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*stop)(struct udevice *dev);
+	/*
+	 * Reset the timer, typically restoring the counter to
+	 * the value configured by start()
+	 *
+	 * @dev: WDT Device
+	 * @return: 0 if OK, -ve on error
+	 */
+	int (*reset)(struct udevice *dev);
+	/*
+	 * Expire the timer, thus executing the action immediately (optional)
+	 *
+	 * If this function is not provided, a default implementation
+	 * will be used, which sets the counter to 1
+	 * and waits forever. This is good enough for system level
+	 * reset, where the function is not expected to return, but might not be
+	 * good enough for other use cases.
+	 *
+	 * @dev: WDT Device
+	 * @flags: Driver specific flags
+	 * @return 0 if OK -ve on error. May not return.
+	 */
+	int (*expire_now)(struct udevice *dev, ulong flags);
+};
+
+#endif  /* _WDT_H_ */
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 1885e17c38..78d14c27e6 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -41,4 +41,5 @@ obj-$(CONFIG_TIMER) += timer.o
 obj-$(CONFIG_DM_VIDEO) += video.o
 obj-$(CONFIG_ADC) += adc.o
 obj-$(CONFIG_SPMI) += spmi.o
+obj-$(CONFIG_WDT) += wdt.o
 endif
diff --git a/test/dm/wdt.c b/test/dm/wdt.c
new file mode 100644
index 0000000000..2ecfceaaff
--- /dev/null
+++ b/test/dm/wdt.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <asm/state.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+/* Test that watchdog driver functions are called */
+static int dm_test_wdt_base(struct unit_test_state *uts)
+{
+	struct sandbox_state *state = state_get_current();
+	struct udevice *dev;
+	const u64 timeout = 42;
+
+	ut_assertok(uclass_get_device(UCLASS_WDT, 0, &dev));
+	ut_asserteq(0, state->wdt.counter);
+	ut_asserteq(false, state->wdt.running);
+
+	ut_assertok(wdt_start(dev, timeout, 0));
+	ut_asserteq(timeout, state->wdt.counter);
+	ut_asserteq(true, state->wdt.running);
+
+	uint reset_count = state->wdt.reset_count;
+	ut_assertok(wdt_reset(dev));
+	ut_asserteq(reset_count + 1, state->wdt.reset_count);
+	ut_asserteq(true, state->wdt.running);
+
+	ut_assertok(wdt_stop(dev));
+	ut_asserteq(false, state->wdt.running);
+
+	return 0;
+}
+DM_TEST(dm_test_wdt_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.13.0.rc1.294.g07d810a77f-goog

  parent reply	other threads:[~2017-05-05 22:01 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-17 19:00 [U-Boot] [PATCH v1 00/15] Expand Aspeed AST2500 Support Maxim Sloyko
2017-04-17 19:00 ` [U-Boot] [PATCH v1 01/15] aspeed: Update ast2500 Device Tree Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-05-08 19:42   ` [U-Boot] [U-Boot,v1,01/15] " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 02/15] dm: Simple Watchdog uclass Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-05-08 19:42   ` [U-Boot] [U-Boot,v1,02/15] " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 03/15] aspeed: Watchdog Timer Driver Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-05-08 19:42   ` [U-Boot] [U-Boot,v1,03/15] " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 04/15] aspeed: Make SCU lock/unlock functions part of SCU API Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-05-08 19:42   ` [U-Boot] [U-Boot, v1, " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 05/15] aspeed: Reset Driver Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-05-08 19:42   ` [U-Boot] [U-Boot,v1,05/15] " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 06/15] aspeed: Device Tree configuration for " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-05-08 19:42   ` [U-Boot] [U-Boot, v1, " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-05-08 19:42   ` [U-Boot] [U-Boot, v1, " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 08/15] aspeed: AST2500 Pinctrl Driver Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-05-08 19:42   ` [U-Boot] [U-Boot,v1,08/15] " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-05-08 19:42   ` [U-Boot] [U-Boot, v1, " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 10/15] aspeed: Add P-Bus clock in ast2500 clock driver Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-05-08 19:42   ` [U-Boot] [U-Boot, v1, " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 11/15] aspeed: Add I2C Driver Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-05-05 19:18     ` Maxim Sloyko
2017-04-19 11:58   ` Heiko Schocher
2017-04-19 16:02     ` Maxim Sloyko
2017-04-20  4:03       ` Heiko Schocher
2017-05-08 19:42   ` [U-Boot] [U-Boot,v1,11/15] " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 12/15] aspeed: Enable I2C in EVB defconfig Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-05-08 19:43   ` [U-Boot] [U-Boot,v1,12/15] " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 13/15] aspeed: Add support for Clocks needed by MACs Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-05-08 19:43   ` [U-Boot] [U-Boot, v1, " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 14/15] aspeed: Refactor SCU to use consistent mask & shift Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-05-08 19:43   ` [U-Boot] [U-Boot, v1, " Tom Rini
2017-04-17 19:00 ` [U-Boot] [PATCH v1 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-05-08 19:43   ` [U-Boot] [U-Boot, v1, " Tom Rini
2017-05-05 22:01 ` [U-Boot] [PATCH v2 00/15] Expand Aspeed AST2500 Support Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] [PATCH v2 01/15] aspeed: Update ast2500 Device Tree Maxim Sloyko
2017-05-05 22:01   ` Maxim Sloyko [this message]
2017-05-05 22:01   ` [U-Boot] [PATCH v2 03/15] aspeed: Watchdog Timer Driver Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] [PATCH v2 04/15] aspeed: Make SCU lock/unlock functions part of SCU API Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] [PATCH v2 05/15] aspeed: Reset Driver Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] [PATCH v2 06/15] aspeed: Device Tree configuration for " Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] [PATCH v2 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] [PATCH v2 08/15] aspeed: AST2500 Pinctrl Driver Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] [PATCH v2 09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] [PATCH v2 10/15] aspeed: Add P-Bus clock in ast2500 clock driver Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] [PATCH v2 11/15] aspeed: Add I2C Driver Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] [PATCH v2 12/15] aspeed: Enable I2C in EVB defconfig Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] [PATCH v2 13/15] aspeed: Add support for Clocks needed by MACs Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] [PATCH v2 14/15] aspeed: Refactor SCU to use consistent mask & shift Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] [PATCH v2 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree Maxim Sloyko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170505220115.143025-3-maxims@google.com \
    --to=maxims@google.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox