All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maxim Sloyko <maxims@google.com>
To: u-boot@lists.denx.de, Simon Glass <sjg@chromium.org>
Cc: openbmc@lists.ozlabs.org, Maxim Sloyko <maxims@google.com>,
	Stephen Warren <swarren@nvidia.com>
Subject: [PATCH v1 02/15] dm: Simple Watchdog uclass
Date: Mon, 17 Apr 2017 12:00:21 -0700	[thread overview]
Message-ID: <20170417190034.71945-3-maxims@google.com> (raw)
In-Reply-To: <20170417190034.71945-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>
---

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   |  76 +++++++++++++++++++++++++++
 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, 335 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@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..34d90bee7e
--- /dev/null
+++ b/drivers/watchdog/sandbox_wdt.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/state.h>
+#include <wdt.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 int sandbox_wdt_probe(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	memset(&state->wdt, 0, sizeof(state->wdt));
+
+	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,
+	.probe = sandbox_wdt_probe,
+};
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.12.2.762.g0e3151a226-goog

WARNING: multiple messages have this Message-ID (diff)
From: Maxim Sloyko <maxims@google.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v1 02/15] dm: Simple Watchdog uclass
Date: Mon, 17 Apr 2017 12:00:21 -0700	[thread overview]
Message-ID: <20170417190034.71945-3-maxims@google.com> (raw)
In-Reply-To: <20170417190034.71945-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>
---

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   |  76 +++++++++++++++++++++++++++
 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, 335 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..34d90bee7e
--- /dev/null
+++ b/drivers/watchdog/sandbox_wdt.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/state.h>
+#include <wdt.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 int sandbox_wdt_probe(struct udevice *dev)
+{
+	struct sandbox_state *state = state_get_current();
+
+	memset(&state->wdt, 0, sizeof(state->wdt));
+
+	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,
+	.probe = sandbox_wdt_probe,
+};
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.12.2.762.g0e3151a226-goog

  parent reply	other threads:[~2017-04-17 19:00 UTC|newest]

Thread overview: 132+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-17 19:00 [PATCH v1 00/15] Expand Aspeed AST2500 Support Maxim Sloyko
2017-04-17 19:00 ` [U-Boot] " Maxim Sloyko
2017-04-17 19:00 ` [PATCH v1 01/15] aspeed: Update ast2500 Device Tree Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,01/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` Maxim Sloyko [this message]
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-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,02/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 03/15] aspeed: Watchdog Timer Driver Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,03/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 04/15] aspeed: Make SCU lock/unlock functions part of SCU API Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot, v1, " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 05/15] aspeed: Reset Driver Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,05/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 06/15] aspeed: Device Tree configuration for " Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,06/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] [U-Boot, v1, 06/15] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot, v1, " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 08/15] aspeed: AST2500 Pinctrl Driver Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,08/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot,v1,09/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] [U-Boot, v1, 09/15] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 10/15] aspeed: Add P-Bus clock in ast2500 clock driver Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:11   ` Simon Glass
2017-04-19  0:11     ` [U-Boot] " Simon Glass
2017-05-08 19:42   ` [U-Boot, v1, " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 11/15] aspeed: Add I2C Driver Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-04-19  0:12     ` [U-Boot] " Simon Glass
2017-05-05 19:18     ` Maxim Sloyko
2017-05-05 19:18       ` [U-Boot] " Maxim Sloyko
2017-04-19 11:58   ` Heiko Schocher
2017-04-19 11:58     ` [U-Boot] " Heiko Schocher
2017-04-19 16:02     ` Maxim Sloyko
2017-04-19 16:02       ` [U-Boot] " Maxim Sloyko
2017-04-20  4:03       ` Heiko Schocher
2017-04-20  4:03         ` [U-Boot] " Heiko Schocher
2017-05-08 19:42   ` [U-Boot,v1,11/15] " Tom Rini
2017-05-08 19:42     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 12/15] aspeed: Enable I2C in EVB defconfig Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-04-19  0:12     ` [U-Boot] " Simon Glass
2017-05-08 19:43   ` [U-Boot,v1,12/15] " Tom Rini
2017-05-08 19:43     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 13/15] aspeed: Add support for Clocks needed by MACs Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-04-19  0:12     ` [U-Boot] " Simon Glass
2017-05-08 19:43   ` [U-Boot,v1,13/15] " Tom Rini
2017-05-08 19:43     ` [U-Boot] [U-Boot, v1, 13/15] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 14/15] aspeed: Refactor SCU to use consistent mask & shift Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-04-19  0:12     ` [U-Boot] " Simon Glass
2017-05-08 19:43   ` [U-Boot, v1, " Tom Rini
2017-05-08 19:43     ` [U-Boot] " Tom Rini
2017-04-17 19:00 ` [PATCH v1 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree Maxim Sloyko
2017-04-17 19:00   ` [U-Boot] " Maxim Sloyko
2017-04-19  0:12   ` Simon Glass
2017-04-19  0:12     ` [U-Boot] " Simon Glass
2017-05-08 19:43   ` [U-Boot, v1, " Tom Rini
2017-05-08 19:43     ` [U-Boot] " Tom Rini
2017-05-05 22:01 ` [PATCH v2 00/15] Expand Aspeed AST2500 Support Maxim Sloyko
2017-05-05 22:01   ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 01/15] aspeed: Update ast2500 Device Tree Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 02/15] dm: Simple Watchdog uclass Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 03/15] aspeed: Watchdog Timer Driver Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 04/15] aspeed: Make SCU lock/unlock functions part of SCU API Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 05/15] aspeed: Reset Driver Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 06/15] aspeed: Device Tree configuration for " Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 07/15] aspeed: Refactor AST2500 RAM Driver and Sysreset Driver Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 08/15] aspeed: AST2500 Pinctrl Driver Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 09/15] aspeed: Enable Pinctrl Driver in AST2500 EVB Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 10/15] aspeed: Add P-Bus clock in ast2500 clock driver Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 11/15] aspeed: Add I2C Driver Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 12/15] aspeed: Enable I2C in EVB defconfig Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 13/15] aspeed: Add support for Clocks needed by MACs Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 14/15] aspeed: Refactor SCU to use consistent mask & shift Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " Maxim Sloyko
2017-05-05 22:01   ` [PATCH v2 15/15] aspeed: Cleanup ast2500-u-boot.dtsi Device Tree Maxim Sloyko
2017-05-05 22:01     ` [U-Boot] " 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=20170417190034.71945-3-maxims@google.com \
    --to=maxims@google.com \
    --cc=openbmc@lists.ozlabs.org \
    --cc=sjg@chromium.org \
    --cc=swarren@nvidia.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.