diff options
author | Wenyou Yang <wenyou.yang@atmel.com> | 2013-02-01 02:06:21 -0500 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2013-03-01 06:49:53 -0500 |
commit | 490ac7af8b71069ba0c733052c5f448ac070c947 (patch) | |
tree | dc6a42af5b3241721c3dacd01c4c3aa759ea05ad /drivers/watchdog | |
parent | 2dd7b24467143c3fd17c6abcaf04fef7976b1528 (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/Kconfig | 1 | ||||
-rw-r--r-- | drivers/watchdog/at91sam9_wdt.c | 161 |
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 | |||
125 | config AT91SAM9X_WATCHDOG | 125 | config 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); | |||
68 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " | 66 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " |
69 | "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 67 | "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); |
70 | 68 | ||
69 | static struct watchdog_device at91_wdt_dev; | ||
71 | static void at91_ping(unsigned long data); | 70 | static void at91_ping(unsigned long data); |
72 | 71 | ||
73 | static struct { | 72 | static 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) | |||
95 | static void at91_ping(unsigned long data) | 91 | static 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 | /* | 101 | static int at91_wdt_ping(struct watchdog_device *wdd) |
106 | * Watchdog device is opened, and watchdog starts running. | ||
107 | */ | ||
108 | static 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; | 108 | static 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 | /* | 116 | static int at91_wdt_stop(struct watchdog_device *wdd) |
120 | * Close the watchdog device. | ||
121 | */ | ||
122 | static 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; | 122 | static 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 | |||
166 | static const struct watchdog_info at91_wdt_info = { | 162 | static 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 | /* | 168 | static const struct watchdog_ops at91_wdt_ops = { |
173 | * Handle commands from user-space. | 169 | .owner = THIS_MODULE, |
174 | */ | 170 | .start = at91_wdt_start, |
175 | static 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 | */ | ||
213 | static 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 | |||
243 | static 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 | ||
252 | static struct miscdevice at91wdt_miscdev = { | 176 | static 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 | ||
258 | static int __init at91wdt_probe(struct platform_device *pdev) | 183 | static 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 | ||
295 | static int __exit at91wdt_remove(struct platform_device *pdev) | 220 | static 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); | |||
326 | MODULE_AUTHOR("Renaud CERRATO <r.cerrato@til-technologies.fr>"); | 250 | MODULE_AUTHOR("Renaud CERRATO <r.cerrato@til-technologies.fr>"); |
327 | MODULE_DESCRIPTION("Watchdog driver for Atmel AT91SAM9x processors"); | 251 | MODULE_DESCRIPTION("Watchdog driver for Atmel AT91SAM9x processors"); |
328 | MODULE_LICENSE("GPL"); | 252 | MODULE_LICENSE("GPL"); |
329 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||