aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorWenyou Yang <wenyou.yang@atmel.com>2013-02-01 02:06:21 -0500
committerWim Van Sebroeck <wim@iguana.be>2013-03-01 06:49:53 -0500
commit490ac7af8b71069ba0c733052c5f448ac070c947 (patch)
treedc6a42af5b3241721c3dacd01c4c3aa759ea05ad /drivers/watchdog
parent2dd7b24467143c3fd17c6abcaf04fef7976b1528 (diff)
watchdog: at91sam9_wdt: Convert to use the watchdog framework
According to Documentation/watchdog/convert_drivers_to_kernel_api.txt, remove the file_operations struct, miscdevice, and obsolete includes Since the at91sam watchdog inherent characteristics, add the watchdog operations: at91wdt_start, at91wdt_stop and at91wdt_ping. Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com> Signed-off-by: Wim Van Sebroeck <wim@iguana.be> Cc: linux-watchdog@vger.kernel.org Cc: linux-kernel@vger.kernel.org
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/Kconfig1
-rw-r--r--drivers/watchdog/at91sam9_wdt.c161
2 files changed, 43 insertions, 119 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index f3aae8ccb6f0..83ac1f7ac32c 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -125,6 +125,7 @@ config AT91RM9200_WATCHDOG
125config AT91SAM9X_WATCHDOG 125config AT91SAM9X_WATCHDOG
126 tristate "AT91SAM9X / AT91CAP9 watchdog" 126 tristate "AT91SAM9X / AT91CAP9 watchdog"
127 depends on ARCH_AT91 && !ARCH_AT91RM9200 127 depends on ARCH_AT91 && !ARCH_AT91RM9200
128 select WATCHDOG_CORE
128 help 129 help
129 Watchdog timer embedded into AT91SAM9X and AT91CAP9 chips. This will 130 Watchdog timer embedded into AT91SAM9X and AT91CAP9 chips. This will
130 reboot your system when the timeout is reached. 131 reboot your system when the timeout is reached.
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index feb203f39e1a..8038b20284ce 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -18,11 +18,9 @@
18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19 19
20#include <linux/errno.h> 20#include <linux/errno.h>
21#include <linux/fs.h>
22#include <linux/init.h> 21#include <linux/init.h>
23#include <linux/io.h> 22#include <linux/io.h>
24#include <linux/kernel.h> 23#include <linux/kernel.h>
25#include <linux/miscdevice.h>
26#include <linux/module.h> 24#include <linux/module.h>
27#include <linux/moduleparam.h> 25#include <linux/moduleparam.h>
28#include <linux/platform_device.h> 26#include <linux/platform_device.h>
@@ -68,19 +66,17 @@ module_param(nowayout, bool, 0);
68MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " 66MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
69 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 67 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
70 68
69static struct watchdog_device at91_wdt_dev;
71static void at91_ping(unsigned long data); 70static void at91_ping(unsigned long data);
72 71
73static struct { 72static struct {
74 void __iomem *base; 73 void __iomem *base;
75 unsigned long next_heartbeat; /* the next_heartbeat for the timer */ 74 unsigned long next_heartbeat; /* the next_heartbeat for the timer */
76 unsigned long open;
77 char expect_close;
78 struct timer_list timer; /* The timer that pings the watchdog */ 75 struct timer_list timer; /* The timer that pings the watchdog */
79} at91wdt_private; 76} at91wdt_private;
80 77
81/* ......................................................................... */ 78/* ......................................................................... */
82 79
83
84/* 80/*
85 * Reload the watchdog timer. (ie, pat the watchdog) 81 * Reload the watchdog timer. (ie, pat the watchdog)
86 */ 82 */
@@ -95,39 +91,37 @@ static inline void at91_wdt_reset(void)
95static void at91_ping(unsigned long data) 91static void at91_ping(unsigned long data)
96{ 92{
97 if (time_before(jiffies, at91wdt_private.next_heartbeat) || 93 if (time_before(jiffies, at91wdt_private.next_heartbeat) ||
98 (!nowayout && !at91wdt_private.open)) { 94 (!watchdog_active(&at91_wdt_dev))) {
99 at91_wdt_reset(); 95 at91_wdt_reset();
100 mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT); 96 mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT);
101 } else 97 } else
102 pr_crit("I will reset your machine !\n"); 98 pr_crit("I will reset your machine !\n");
103} 99}
104 100
105/* 101static int at91_wdt_ping(struct watchdog_device *wdd)
106 * Watchdog device is opened, and watchdog starts running.
107 */
108static int at91_wdt_open(struct inode *inode, struct file *file)
109{ 102{
110 if (test_and_set_bit(0, &at91wdt_private.open)) 103 /* calculate when the next userspace timeout will be */
111 return -EBUSY; 104 at91wdt_private.next_heartbeat = jiffies + wdd->timeout * HZ;
105 return 0;
106}
112 107
113 at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; 108static int at91_wdt_start(struct watchdog_device *wdd)
109{
110 /* calculate the next userspace timeout and modify the timer */
111 at91_wdt_ping(wdd);
114 mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT); 112 mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT);
115 113 return 0;
116 return nonseekable_open(inode, file);
117} 114}
118 115
119/* 116static int at91_wdt_stop(struct watchdog_device *wdd)
120 * Close the watchdog device.
121 */
122static int at91_wdt_close(struct inode *inode, struct file *file)
123{ 117{
124 clear_bit(0, &at91wdt_private.open); 118 /* The watchdog timer hardware can not be stopped... */
125 119 return 0;
126 /* stop internal ping */ 120}
127 if (!at91wdt_private.expect_close)
128 del_timer(&at91wdt_private.timer);
129 121
130 at91wdt_private.expect_close = 0; 122static int at91_wdt_set_timeout(struct watchdog_device *wdd, unsigned int new_timeout)
123{
124 wdd->timeout = new_timeout;
131 return 0; 125 return 0;
132} 126}
133 127
@@ -163,96 +157,27 @@ static int at91_wdt_settimeout(unsigned int timeout)
163 return 0; 157 return 0;
164} 158}
165 159
160/* ......................................................................... */
161
166static const struct watchdog_info at91_wdt_info = { 162static const struct watchdog_info at91_wdt_info = {
167 .identity = DRV_NAME, 163 .identity = DRV_NAME,
168 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | 164 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
169 WDIOF_MAGICCLOSE, 165 WDIOF_MAGICCLOSE,
170}; 166};
171 167
172/* 168static const struct watchdog_ops at91_wdt_ops = {
173 * Handle commands from user-space. 169 .owner = THIS_MODULE,
174 */ 170 .start = at91_wdt_start,
175static long at91_wdt_ioctl(struct file *file, 171 .stop = at91_wdt_stop,
176 unsigned int cmd, unsigned long arg) 172 .ping = at91_wdt_ping,
177{ 173 .set_timeout = at91_wdt_set_timeout,
178 void __user *argp = (void __user *)arg;
179 int __user *p = argp;
180 int new_value;
181
182 switch (cmd) {
183 case WDIOC_GETSUPPORT:
184 return copy_to_user(argp, &at91_wdt_info,
185 sizeof(at91_wdt_info)) ? -EFAULT : 0;
186
187 case WDIOC_GETSTATUS:
188 case WDIOC_GETBOOTSTATUS:
189 return put_user(0, p);
190
191 case WDIOC_KEEPALIVE:
192 at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ;
193 return 0;
194
195 case WDIOC_SETTIMEOUT:
196 if (get_user(new_value, p))
197 return -EFAULT;
198
199 heartbeat = new_value;
200 at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ;
201
202 return put_user(new_value, p); /* return current value */
203
204 case WDIOC_GETTIMEOUT:
205 return put_user(heartbeat, p);
206 }
207 return -ENOTTY;
208}
209
210/*
211 * Pat the watchdog whenever device is written to.
212 */
213static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len,
214 loff_t *ppos)
215{
216 if (!len)
217 return 0;
218
219 /* Scan for magic character */
220 if (!nowayout) {
221 size_t i;
222
223 at91wdt_private.expect_close = 0;
224
225 for (i = 0; i < len; i++) {
226 char c;
227 if (get_user(c, data + i))
228 return -EFAULT;
229 if (c == 'V') {
230 at91wdt_private.expect_close = 42;
231 break;
232 }
233 }
234 }
235
236 at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ;
237
238 return len;
239}
240
241/* ......................................................................... */
242
243static const struct file_operations at91wdt_fops = {
244 .owner = THIS_MODULE,
245 .llseek = no_llseek,
246 .unlocked_ioctl = at91_wdt_ioctl,
247 .open = at91_wdt_open,
248 .release = at91_wdt_close,
249 .write = at91_wdt_write,
250}; 174};
251 175
252static struct miscdevice at91wdt_miscdev = { 176static struct watchdog_device at91_wdt_dev = {
253 .minor = WATCHDOG_MINOR, 177 .info = &at91_wdt_info,
254 .name = "watchdog", 178 .ops = &at91_wdt_ops,
255 .fops = &at91wdt_fops, 179 .min_timeout = 1,
180 .max_timeout = 0xFFFF,
256}; 181};
257 182
258static int __init at91wdt_probe(struct platform_device *pdev) 183static int __init at91wdt_probe(struct platform_device *pdev)
@@ -260,10 +185,6 @@ static int __init at91wdt_probe(struct platform_device *pdev)
260 struct resource *r; 185 struct resource *r;
261 int res; 186 int res;
262 187
263 if (at91wdt_miscdev.parent)
264 return -EBUSY;
265 at91wdt_miscdev.parent = &pdev->dev;
266
267 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 188 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
268 if (!r) 189 if (!r)
269 return -ENODEV; 190 return -ENODEV;
@@ -273,16 +194,20 @@ static int __init at91wdt_probe(struct platform_device *pdev)
273 return -ENOMEM; 194 return -ENOMEM;
274 } 195 }
275 196
197 at91_wdt_dev.timeout = heartbeat;
198 at91_wdt_dev.parent = &pdev->dev;
199 watchdog_set_nowayout(&at91_wdt_dev, nowayout);
200
276 /* Set watchdog */ 201 /* Set watchdog */
277 res = at91_wdt_settimeout(ms_to_ticks(WDT_HW_TIMEOUT * 1000)); 202 res = at91_wdt_settimeout(ms_to_ticks(WDT_HW_TIMEOUT * 1000));
278 if (res) 203 if (res)
279 return res; 204 return res;
280 205
281 res = misc_register(&at91wdt_miscdev); 206 res = watchdog_register_device(&at91_wdt_dev);
282 if (res) 207 if (res)
283 return res; 208 return res;
284 209
285 at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; 210 at91wdt_private.next_heartbeat = jiffies + at91_wdt_dev.timeout * HZ;
286 setup_timer(&at91wdt_private.timer, at91_ping, 0); 211 setup_timer(&at91wdt_private.timer, at91_ping, 0);
287 mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT); 212 mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT);
288 213
@@ -294,13 +219,12 @@ static int __init at91wdt_probe(struct platform_device *pdev)
294 219
295static int __exit at91wdt_remove(struct platform_device *pdev) 220static int __exit at91wdt_remove(struct platform_device *pdev)
296{ 221{
297 int res; 222 watchdog_unregister_device(&at91_wdt_dev);
298 223
299 res = misc_deregister(&at91wdt_miscdev); 224 pr_warn("I quit now, hardware will probably reboot!\n");
300 if (!res) 225 del_timer(&at91wdt_private.timer);
301 at91wdt_miscdev.parent = NULL;
302 226
303 return res; 227 return 0;
304} 228}
305 229
306#if defined(CONFIG_OF) 230#if defined(CONFIG_OF)
@@ -326,4 +250,3 @@ module_platform_driver_probe(at91wdt_driver, at91wdt_probe);
326MODULE_AUTHOR("Renaud CERRATO <r.cerrato@til-technologies.fr>"); 250MODULE_AUTHOR("Renaud CERRATO <r.cerrato@til-technologies.fr>");
327MODULE_DESCRIPTION("Watchdog driver for Atmel AT91SAM9x processors"); 251MODULE_DESCRIPTION("Watchdog driver for Atmel AT91SAM9x processors");
328MODULE_LICENSE("GPL"); 252MODULE_LICENSE("GPL");
329MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);