summaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/f71808e_wdt.c7
-rw-r--r--drivers/watchdog/imxwd.c14
-rw-r--r--drivers/watchdog/stm32_iwdg.c3
-rw-r--r--drivers/watchdog/stpmic1_wdt.c28
-rw-r--r--drivers/watchdog/wd_core.c48
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, &reg);
+ ret = regmap_read(map, RREQ_STATE_SR, &reg);
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;
-}