aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/at91sam9_wdt.c
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/at91sam9_wdt.c
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/at91sam9_wdt.c')
-rw-r--r--drivers/watchdog/at91sam9_wdt.c161
1 files changed, 42 insertions, 119 deletions
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);