diff options
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/f71808e_wdt.c | 7 | ||||
-rw-r--r-- | drivers/watchdog/imxwd.c | 14 | ||||
-rw-r--r-- | drivers/watchdog/stm32_iwdg.c | 1 | ||||
-rw-r--r-- | drivers/watchdog/wd_core.c | 48 |
4 files changed, 52 insertions, 18 deletions
diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c index 4f881a1d02..5307ab0b3e 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,11 @@ static int f71808e_wdt_init(struct f71808e_wdt *wd, struct device_d *dev) dev_info(dev, "reset reason: %s\n", reset_source_name()); + if (test_bit(F71808FG_FLAG_WD_EN, &wdt_conf)) + wdd->running = WDOG_HW_RUNNING; + else + wdd->running = WDOG_HW_NOT_RUNNING; + ret = watchdog_register(wdd); if (ret) return ret; diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c index 77a3bd76ce..b2cfd1cd3a 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,13 @@ static int imx_wd_probe(struct device_d *dev) "fsl,ext-reset-output"); if (IS_ENABLED(CONFIG_WATCHDOG_IMX)) { + if (priv->ops->is_running) { + if (priv->ops->is_running(priv)) + priv->wd.running = WDOG_HW_RUNNING; + else + priv->wd.running = WDOG_HW_NOT_RUNNING; + } + ret = watchdog_register(&priv->wd); if (ret) goto on_error; @@ -277,6 +290,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, }; diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c index 808d7c8372..c7a5cb9caa 100644 --- a/drivers/watchdog/stm32_iwdg.c +++ b/drivers/watchdog/stm32_iwdg.c @@ -256,6 +256,7 @@ static int stm32_iwdg_probe(struct device_d *dev) wdd->set_timeout = stm32_iwdg_set_timeout; wdd->timeout_max = (RLR_MAX + 1) * data->max_prescaler * 1000; wdd->timeout_max /= wd->rate * 1000; + wdd->running = WDOG_HW_RUNNING_UNSUPPORTED; /* ONF bit not present in IP */ ret = watchdog_register(wdd); if (ret) { diff --git a/drivers/watchdog/wd_core.c b/drivers/watchdog/wd_core.c index 8b13950238..b6e2a37b1f 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,13 @@ 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; + + wd->running = timeout ? WDOG_HW_RUNNING : WDOG_HW_NOT_RUNNING; + + return 0; } EXPORT_SYMBOL(watchdog_set_timeout); @@ -127,6 +135,23 @@ static int watchdog_register_dev(struct watchdog *wd, const char *name, int id) return register_device(&wd->dev); } +/** + * dev_get_watchdog_priority() - get a device's desired watchdog priority + * @dev: The device, which device_node to read the property from + * + * return: The priority + */ +static unsigned int dev_get_watchdog_priority(struct device_d *dev) +{ + unsigned int priority = WATCHDOG_DEFAULT_PRIORITY; + + if (dev) + of_property_read_u32(dev->device_node, "watchdog-priority", + &priority); + + return priority; +} + int watchdog_register(struct watchdog *wd) { struct param_d *p; @@ -145,8 +170,12 @@ int watchdog_register(struct watchdog *wd) if (ret) return ret; + p = dev_add_param_tristate_ro(&wd->dev, "running", &wd->running); + if (IS_ERR(p)) + return PTR_ERR(p); + if (!wd->priority) - wd->priority = WATCHDOG_DEFAULT_PRIORITY; + wd->priority = dev_get_watchdog_priority(wd->hwdev); p = dev_add_param_uint32(&wd->dev, "priority", watchdog_set_priority, NULL, @@ -232,18 +261,3 @@ struct watchdog *watchdog_get_by_name(const char *name) return NULL; } EXPORT_SYMBOL(watchdog_get_by_name); - -/** - * of_get_watchdog_priority() - get the desired watchdog priority from device tree - * @node: The device_node to read the property from - * - * return: The priority - */ -unsigned int of_get_watchdog_priority(struct device_node *node) -{ - unsigned int priority = WATCHDOG_DEFAULT_PRIORITY; - - of_property_read_u32(node, "watchdog-priority", &priority); - - return priority; -} |