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 | 3 | ||||
-rw-r--r-- | drivers/watchdog/stpmic1_wdt.c | 28 | ||||
-rw-r--r-- | drivers/watchdog/wd_core.c | 48 |
5 files changed, 65 insertions, 35 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 4d252e558c..c7a5cb9caa 100644 --- a/drivers/watchdog/stm32_iwdg.c +++ b/drivers/watchdog/stm32_iwdg.c @@ -132,7 +132,7 @@ static int stm32_iwdg_set_timeout(struct watchdog *wdd, unsigned int timeout) int ret; if (!timeout) - return -EINVAL; /* can't disable */ + return -ENOSYS; /* can't disable */ if (timeout > wdd->timeout_max) return -EINVAL; @@ -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/stpmic1_wdt.c b/drivers/watchdog/stpmic1_wdt.c index 9b7a586387..40273ffc4c 100644 --- a/drivers/watchdog/stpmic1_wdt.c +++ b/drivers/watchdog/stpmic1_wdt.c @@ -14,22 +14,15 @@ #include <restart.h> #include <reset_source.h> -#define RESTART_SR 0x05 -#define MAIN_CR 0x10 -#define WCHDG_CR 0x1B -#define WCHDG_TIMER_CR 0x1C +#include <linux/mfd/stpmic1.h> -/* Restart Status Register (RESTART_SR) */ +/* Restart Status Register (RREQ_STATE_SR) */ #define R_RST BIT(0) #define R_SWOFF BIT(1) #define R_WDG BIT(2) #define R_PKEYLKP BIT(3) #define R_VINOK_FA BIT(4) -/* Main PMIC Control Register (MAIN_CR) */ -#define SWOFF BIT(0) -#define RREQ_EN BIT(1) - /* Watchdog Control Register (WCHDG_CR) */ #define WDT_START BIT(0) #define WDT_PING BIT(1) @@ -106,8 +99,9 @@ static void __noreturn stpmic1_restart_handler(struct restart_handler *rst) { struct stpmic1_wdt *wdt = container_of(rst, struct stpmic1_wdt, restart); - regmap_write_bits(wdt->regmap, MAIN_CR, - SWOFF | RREQ_EN, SWOFF | RREQ_EN); + regmap_write_bits(wdt->regmap, SWOFF_PWRCTRL_CR, + SOFTWARE_SWITCH_OFF_ENABLED | RESTART_REQUEST_ENABLED, + SOFTWARE_SWITCH_OFF_ENABLED | RESTART_REQUEST_ENABLED); mdelay(1000); hang(); @@ -119,8 +113,9 @@ static void __noreturn stpmic1_poweroff(struct poweroff_handler *handler) shutdown_barebox(); - regmap_write_bits(wdt->regmap, MAIN_CR, - SWOFF | RREQ_EN, SWOFF); + regmap_write_bits(wdt->regmap, SWOFF_PWRCTRL_CR, + SOFTWARE_SWITCH_OFF_ENABLED | RESTART_REQUEST_ENABLED, + SOFTWARE_SWITCH_OFF_ENABLED); mdelay(1000); hang(); @@ -142,7 +137,7 @@ static int stpmic1_set_reset_reason(struct regmap *map) int ret; int i, instance = 0; - ret = regmap_read(map, RESTART_SR, ®); + ret = regmap_read(map, RREQ_STATE_SR, ®); if (ret) return ret; @@ -156,7 +151,7 @@ static int stpmic1_set_reset_reason(struct regmap *map) reset_source_set_prinst(type, 400, instance); - pr_info("STPMIC1 reset reason %s (RESTART_SR: 0x%08x)\n", + pr_info("STPMIC1 reset reason %s (RREQ_STATE_SR: 0x%08x)\n", reset_source_name(), reg); return 0; @@ -180,7 +175,8 @@ static int stpmic1_wdt_probe(struct device_d *dev) wdd->timeout_max = PMIC_WDT_MAX_TIMEOUT; /* have the watchdog reset, not power-off the system */ - regmap_write_bits(wdt->regmap, MAIN_CR, RREQ_EN, RREQ_EN); + regmap_write_bits(wdt->regmap, SWOFF_PWRCTRL_CR, + RESTART_REQUEST_ENABLED, RESTART_REQUEST_ENABLED); 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; -} |