* [PATCH 2/4] watchdog: implement generic support for .running device parameter
2019-11-04 18:25 [PATCH 1/4] watchdog: always populate watchdog priority from device tree if possible Ahmad Fatoum
@ 2019-11-04 18:25 ` Ahmad Fatoum
2019-11-04 18:25 ` [PATCH 3/4] watchdog: imxwd: support .running device parameter on i.MX2+ Ahmad Fatoum
2019-11-04 18:25 ` [PATCH 4/4] watchdog: f71808e: support .running device parameter Ahmad Fatoum
2 siblings, 0 replies; 4+ messages in thread
From: Ahmad Fatoum @ 2019-11-04 18:25 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Linux watchdog have an optional WDOG_HW_RUNNING bit that is used in
conjunction with CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED to automatically
ping running watchdogs until userspace takes over.
So far, when we ported Linux drivers, we dropped this detection, but it
would be useful to have this information in barebox as well:
The American Megatrends BIOS I am using allows configuring the hardware
watchdog from the BIOS. barebox enables the WDT as well, so in normal
operation we would never notice if after a BIOS update, the watchdog is
no longer enabled. If we maintain a running parameter on watchdog
devices, board code can be written to check whether the watchdog device
is indeed running.
To achieve this, add the necessary bits to the watchdog API. How we go
about it differs from Linux a little:
- We use a status_supported bitmask to differentiate between watchdogs
that are not running and watchdogs whose running status is
unknown.
- Because we can check the status_supported bitmask watchdog_hw_running
can fail and would return a negative value
- We do the maintenance of the running parameter after barebox
feeds/disables the watchdog in the core, so it doesn't need to
be replicated across drivers. Drivers will only need to initialize the
bitmasks once at probe time.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/watchdog/wd_core.c | 33 ++++++++++++++++++++++++++++++++-
include/watchdog.h | 17 +++++++++++++++++
2 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/drivers/watchdog/wd_core.c b/drivers/watchdog/wd_core.c
index 39cac6f6c494..ee9b413ff95b 100644
--- a/drivers/watchdog/wd_core.c
+++ b/drivers/watchdog/wd_core.c
@@ -37,6 +37,8 @@ static const char *watchdog_name(struct watchdog *wd)
*/
int watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
{
+ int ret;
+
if (!wd)
return -ENODEV;
@@ -45,7 +47,18 @@ int watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
pr_debug("setting timeout on %s to %ds\n", watchdog_name(wd), timeout);
- return wd->set_timeout(wd, timeout);
+ ret = wd->set_timeout(wd, timeout);
+ if (ret)
+ return ret;
+
+ if (test_bit(WDOG_HW_RUNNING, &wd->status_supported)) {
+ if (timeout)
+ set_bit(WDOG_HW_RUNNING, &wd->status);
+ else
+ clear_bit(WDOG_HW_RUNNING, &wd->status);
+ }
+
+ return ret;
}
EXPORT_SYMBOL(watchdog_set_timeout);
@@ -118,6 +131,15 @@ static int watchdog_register_poller(struct watchdog *wd)
return PTR_ERR_OR_ZERO(p);
}
+static const char *watchdog_get_running(struct device_d *dev, struct param_d *p)
+{
+ /*
+ * This won't ever fail, because the parameter is only registed when
+ * test_bit(WDOG_HW_RUNNING, &w->status_supported) is true
+ */
+ return watchdog_hw_running((struct watchdog *)p->value) ? "1" : "0";
+}
+
static int watchdog_register_dev(struct watchdog *wd, const char *name, int id)
{
wd->dev.parent = wd->hwdev;
@@ -162,6 +184,15 @@ int watchdog_register(struct watchdog *wd)
if (ret)
return ret;
+ if (test_bit(WDOG_HW_RUNNING, &wd->status_supported)) {
+ p = dev_add_param(&wd->dev, "running", NULL,
+ watchdog_get_running, PARAM_FLAG_RO);
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
+ p->value = (char *)wd;
+ }
+
if (!wd->priority)
wd->priority = dev_get_watchdog_priority(wd->hwdev);
diff --git a/include/watchdog.h b/include/watchdog.h
index 105b7ca81093..eccddac1b8bb 100644
--- a/include/watchdog.h
+++ b/include/watchdog.h
@@ -15,6 +15,9 @@
#include <poller.h>
#include <driver.h>
+#include <linux/bitops.h>
+
+#define WDOG_HW_RUNNING 3
struct watchdog {
int (*set_timeout)(struct watchdog *, unsigned);
@@ -27,8 +30,22 @@ struct watchdog {
unsigned int poller_enable;
struct poller_async poller;
struct list_head list;
+ unsigned long status;
+ unsigned long status_supported;
};
+/*
+ * Use the following function to check whether or not the hardware watchdog
+ * is running
+ */
+static inline int watchdog_hw_running(struct watchdog *w)
+{
+ if (!test_bit(WDOG_HW_RUNNING, &w->status_supported))
+ return -ENOSYS;
+
+ return !!test_bit(WDOG_HW_RUNNING, &w->status);
+}
+
#ifdef CONFIG_WATCHDOG
int watchdog_register(struct watchdog *);
int watchdog_deregister(struct watchdog *);
--
2.24.0.rc1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 3/4] watchdog: imxwd: support .running device parameter on i.MX2+
2019-11-04 18:25 [PATCH 1/4] watchdog: always populate watchdog priority from device tree if possible Ahmad Fatoum
2019-11-04 18:25 ` [PATCH 2/4] watchdog: implement generic support for .running device parameter Ahmad Fatoum
@ 2019-11-04 18:25 ` Ahmad Fatoum
2019-11-04 18:25 ` [PATCH 4/4] watchdog: f71808e: support .running device parameter Ahmad Fatoum
2 siblings, 0 replies; 4+ messages in thread
From: Ahmad Fatoum @ 2019-11-04 18:25 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The i.MX can be fused to start the watchdog on power-on reset.
To give users an easy way to determine whether the watchdog is running,
implement support for WDOG_HW_RUNNING.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/watchdog/imxwd.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c
index 77a3bd76cefa..eb4f2c16c60a 100644
--- a/drivers/watchdog/imxwd.c
+++ b/drivers/watchdog/imxwd.c
@@ -28,6 +28,7 @@ struct imx_wd_ops {
int (*set_timeout)(struct imx_wd *, unsigned);
void (*soc_reset)(struct imx_wd *);
int (*init)(struct imx_wd *);
+ bool (*is_running)(struct imx_wd *);
unsigned int timeout_max;
};
@@ -111,6 +112,11 @@ static void imx1_soc_reset(struct imx_wd *priv)
writew(IMX1_WDOG_WCR_WDE, priv->base + IMX1_WDOG_WCR);
}
+static inline bool imx21_watchdog_is_running(struct imx_wd *priv)
+{
+ return imxwd_read(priv, IMX21_WDOG_WCR) & IMX21_WDOG_WCR_WDE;
+}
+
static int imx21_watchdog_set_timeout(struct imx_wd *priv, unsigned timeout)
{
u16 val;
@@ -243,6 +249,12 @@ static int imx_wd_probe(struct device_d *dev)
"fsl,ext-reset-output");
if (IS_ENABLED(CONFIG_WATCHDOG_IMX)) {
+ if (priv->ops->is_running) {
+ set_bit(WDOG_HW_RUNNING, &priv->wd.status_supported);
+ if (priv->ops->is_running(priv))
+ set_bit(WDOG_HW_RUNNING, &priv->wd.status);
+ }
+
ret = watchdog_register(&priv->wd);
if (ret)
goto on_error;
@@ -277,6 +289,7 @@ static const struct imx_wd_ops imx21_wd_ops = {
.set_timeout = imx21_watchdog_set_timeout,
.soc_reset = imx21_soc_reset,
.init = imx21_wd_init,
+ .is_running = imx21_watchdog_is_running,
.timeout_max = 128,
};
--
2.24.0.rc1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 4/4] watchdog: f71808e: support .running device parameter
2019-11-04 18:25 [PATCH 1/4] watchdog: always populate watchdog priority from device tree if possible Ahmad Fatoum
2019-11-04 18:25 ` [PATCH 2/4] watchdog: implement generic support for .running device parameter Ahmad Fatoum
2019-11-04 18:25 ` [PATCH 3/4] watchdog: imxwd: support .running device parameter on i.MX2+ Ahmad Fatoum
@ 2019-11-04 18:25 ` Ahmad Fatoum
2 siblings, 0 replies; 4+ messages in thread
From: Ahmad Fatoum @ 2019-11-04 18:25 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The American Megatrends BIOS I am using can be configured to start the
Fintek watchdog prior to the UEFI payloads. To avoid BIOS updates that reset
this functionality going unnoticed, implement support for WDOG_HW_RUNNING.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/watchdog/f71808e_wdt.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c
index 4f881a1d02bc..2b2f98a12cca 100644
--- a/drivers/watchdog/f71808e_wdt.c
+++ b/drivers/watchdog/f71808e_wdt.c
@@ -222,7 +222,7 @@ static int f71808e_wdt_init(struct f71808e_wdt *wd, struct device_d *dev)
{
struct watchdog *wdd = &wd->wdd;
const char * const *names = pulse_width_names;
- int wdt_conf;
+ unsigned long wdt_conf;
int ret;
superio_enter(wd->sioaddr);
@@ -262,6 +262,10 @@ static int f71808e_wdt_init(struct f71808e_wdt *wd, struct device_d *dev)
dev_info(dev, "reset reason: %s\n", reset_source_name());
+ set_bit(WDOG_HW_RUNNING, &wdd->status_supported);
+ if (test_bit(F71808FG_FLAG_WD_EN, &wdt_conf))
+ set_bit(WDOG_HW_RUNNING, &wdd->status);
+
ret = watchdog_register(wdd);
if (ret)
return ret;
--
2.24.0.rc1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 4+ messages in thread