aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabio Porcedda <fabio.porcedda@gmail.com>2013-01-08 05:04:10 -0500
committerWim Van Sebroeck <wim@iguana.be>2013-03-01 06:48:36 -0500
commit3048253ed957fc6cdc34599178408559aa1e0062 (patch)
tree2e8fd94c3d64899dc4a48912f7ece62721047c68
parente3e83d0001a77cdb337be9170e58b55488835ba0 (diff)
watchdog: core: dt: add support for the timeout-sec dt property
Add support for watchdog drivers to initialize/set the timeout field of the watchdog_device structure. The timeout field is initialised either with the module timeout parameter value (if valid) or with the timeout-sec dt property (if valid). If both are invalid the initial value is unchanged. Signed-off-by: Fabio Porcedda <fabio.porcedda@gmail.com> Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
-rw-r--r--Documentation/watchdog/watchdog-kernel-api.txt14
-rw-r--r--drivers/watchdog/watchdog_core.c66
-rw-r--r--drivers/watchdog/watchdog_dev.c3
-rw-r--r--include/linux/watchdog.h9
4 files changed, 80 insertions, 12 deletions
diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index 086638f6c82d..a0438f3957ca 100644
--- a/Documentation/watchdog/watchdog-kernel-api.txt
+++ b/Documentation/watchdog/watchdog-kernel-api.txt
@@ -1,6 +1,6 @@
1The Linux WatchDog Timer Driver Core kernel API. 1The Linux WatchDog Timer Driver Core kernel API.
2=============================================== 2===============================================
3Last reviewed: 22-May-2012 3Last reviewed: 12-Feb-2013
4 4
5Wim Van Sebroeck <wim@iguana.be> 5Wim Van Sebroeck <wim@iguana.be>
6 6
@@ -212,3 +212,15 @@ driver specific data to and a pointer to the data itself.
212The watchdog_get_drvdata function allows you to retrieve driver specific data. 212The watchdog_get_drvdata function allows you to retrieve driver specific data.
213The argument of this function is the watchdog device where you want to retrieve 213The argument of this function is the watchdog device where you want to retrieve
214data from. The function returns the pointer to the driver specific data. 214data from. The function returns the pointer to the driver specific data.
215
216To initialize the timeout field, the following function can be used:
217
218extern int watchdog_init_timeout(struct watchdog_device *wdd,
219 unsigned int timeout_parm, struct device *dev);
220
221The watchdog_init_timeout function allows you to initialize the timeout field
222using the module timeout parameter or by retrieving the timeout-sec property from
223the device tree (if the module timeout parameter is invalid). Best practice is
224to set the default timeout value as timeout value in the watchdog_device and
225then use this function to set the user "preferred" timeout value.
226This routine returns zero on success and a negative errno code for failure.
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 3796434991fa..05d18b4c661b 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -36,12 +36,68 @@
36#include <linux/init.h> /* For __init/__exit/... */ 36#include <linux/init.h> /* For __init/__exit/... */
37#include <linux/idr.h> /* For ida_* macros */ 37#include <linux/idr.h> /* For ida_* macros */
38#include <linux/err.h> /* For IS_ERR macros */ 38#include <linux/err.h> /* For IS_ERR macros */
39#include <linux/of.h> /* For of_get_timeout_sec */
39 40
40#include "watchdog_core.h" /* For watchdog_dev_register/... */ 41#include "watchdog_core.h" /* For watchdog_dev_register/... */
41 42
42static DEFINE_IDA(watchdog_ida); 43static DEFINE_IDA(watchdog_ida);
43static struct class *watchdog_class; 44static struct class *watchdog_class;
44 45
46static void watchdog_check_min_max_timeout(struct watchdog_device *wdd)
47{
48 /*
49 * Check that we have valid min and max timeout values, if
50 * not reset them both to 0 (=not used or unknown)
51 */
52 if (wdd->min_timeout > wdd->max_timeout) {
53 pr_info("Invalid min and max timeout values, resetting to 0!\n");
54 wdd->min_timeout = 0;
55 wdd->max_timeout = 0;
56 }
57}
58
59/**
60 * watchdog_init_timeout() - initialize the timeout field
61 * @timeout_parm: timeout module parameter
62 * @dev: Device that stores the timeout-sec property
63 *
64 * Initialize the timeout field of the watchdog_device struct with either the
65 * timeout module parameter (if it is valid value) or the timeout-sec property
66 * (only if it is a valid value and the timeout_parm is out of bounds).
67 * If none of them are valid then we keep the old value (which should normally
68 * be the default timeout value.
69 *
70 * A zero is returned on success and -EINVAL for failure.
71 */
72int watchdog_init_timeout(struct watchdog_device *wdd,
73 unsigned int timeout_parm, struct device *dev)
74{
75 unsigned int t = 0;
76 int ret = 0;
77
78 watchdog_check_min_max_timeout(wdd);
79
80 /* try to get the tiemout module parameter first */
81 if (!watchdog_timeout_invalid(wdd, timeout_parm)) {
82 wdd->timeout = timeout_parm;
83 return ret;
84 }
85 if (timeout_parm)
86 ret = -EINVAL;
87
88 /* try to get the timeout_sec property */
89 if (dev == NULL || dev->of_node == NULL)
90 return ret;
91 of_property_read_u32(dev->of_node, "timeout-sec", &t);
92 if (!watchdog_timeout_invalid(wdd, t))
93 wdd->timeout = t;
94 else
95 ret = -EINVAL;
96
97 return ret;
98}
99EXPORT_SYMBOL_GPL(watchdog_init_timeout);
100
45/** 101/**
46 * watchdog_register_device() - register a watchdog device 102 * watchdog_register_device() - register a watchdog device
47 * @wdd: watchdog device 103 * @wdd: watchdog device
@@ -63,15 +119,7 @@ int watchdog_register_device(struct watchdog_device *wdd)
63 if (wdd->ops->start == NULL || wdd->ops->stop == NULL) 119 if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
64 return -EINVAL; 120 return -EINVAL;
65 121
66 /* 122 watchdog_check_min_max_timeout(wdd);
67 * Check that we have valid min and max timeout values, if
68 * not reset them both to 0 (=not used or unknown)
69 */
70 if (wdd->min_timeout > wdd->max_timeout) {
71 pr_info("Invalid min and max timeout values, resetting to 0!\n");
72 wdd->min_timeout = 0;
73 wdd->max_timeout = 0;
74 }
75 123
76 /* 124 /*
77 * Note: now that all watchdog_device data has been verified, we 125 * Note: now that all watchdog_device data has been verified, we
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index ef8edecfc526..08b48bbf9f4b 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -200,8 +200,7 @@ static int watchdog_set_timeout(struct watchdog_device *wddev,
200 !(wddev->info->options & WDIOF_SETTIMEOUT)) 200 !(wddev->info->options & WDIOF_SETTIMEOUT))
201 return -EOPNOTSUPP; 201 return -EOPNOTSUPP;
202 202
203 if ((wddev->max_timeout != 0) && 203 if (watchdog_timeout_invalid(wddev, timeout))
204 (timeout < wddev->min_timeout || timeout > wddev->max_timeout))
205 return -EINVAL; 204 return -EINVAL;
206 205
207 mutex_lock(&wddev->lock); 206 mutex_lock(&wddev->lock);
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index 3a9df2f43be6..2a3038ee17a3 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -118,6 +118,13 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
118 set_bit(WDOG_NO_WAY_OUT, &wdd->status); 118 set_bit(WDOG_NO_WAY_OUT, &wdd->status);
119} 119}
120 120
121/* Use the following function to check if a timeout value is invalid */
122static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
123{
124 return ((wdd->max_timeout != 0) &&
125 (t < wdd->min_timeout || t > wdd->max_timeout));
126}
127
121/* Use the following functions to manipulate watchdog driver specific data */ 128/* Use the following functions to manipulate watchdog driver specific data */
122static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data) 129static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
123{ 130{
@@ -130,6 +137,8 @@ static inline void *watchdog_get_drvdata(struct watchdog_device *wdd)
130} 137}
131 138
132/* drivers/watchdog/watchdog_core.c */ 139/* drivers/watchdog/watchdog_core.c */
140extern int watchdog_init_timeout(struct watchdog_device *wdd,
141 unsigned int timeout_parm, struct device *dev);
133extern int watchdog_register_device(struct watchdog_device *); 142extern int watchdog_register_device(struct watchdog_device *);
134extern void watchdog_unregister_device(struct watchdog_device *); 143extern void watchdog_unregister_device(struct watchdog_device *);
135 144