diff options
author | Michal Simek <michal.simek@xilinx.com> | 2014-02-12 08:34:32 -0500 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2014-03-31 07:28:56 -0400 |
commit | d14fd9645501444f06034339118de56686e25dfb (patch) | |
tree | 9729037743b42ef0bf9e4dd99aa87493c37a7e1b /drivers/watchdog | |
parent | 70605d9bab216534a593f3ec8218ab8c015cb452 (diff) |
watchdog: xilinx: Convert driver to the watchdog framework
- Remove uneeded headers, fops functions
- Use xilinx_wdt prefix in start/stop/keepalive functions
and in new structures
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/Kconfig | 1 | ||||
-rw-r--r-- | drivers/watchdog/of_xilinx_wdt.c | 204 |
2 files changed, 33 insertions, 172 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 79d25894343a..82ffa0fbbfa1 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -1026,6 +1026,7 @@ config M54xx_WATCHDOG | |||
1026 | config XILINX_WATCHDOG | 1026 | config XILINX_WATCHDOG |
1027 | tristate "Xilinx Watchdog timer" | 1027 | tristate "Xilinx Watchdog timer" |
1028 | depends on MICROBLAZE | 1028 | depends on MICROBLAZE |
1029 | select WATCHDOG_CORE | ||
1029 | ---help--- | 1030 | ---help--- |
1030 | Watchdog driver for the xps_timebase_wdt ip core. | 1031 | Watchdog driver for the xps_timebase_wdt ip core. |
1031 | 1032 | ||
diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c index 19fa92d01f5d..0e6c188f55ae 100644 --- a/drivers/watchdog/of_xilinx_wdt.c +++ b/drivers/watchdog/of_xilinx_wdt.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Watchdog Device Driver for Xilinx axi/xps_timebase_wdt | 2 | * Watchdog Device Driver for Xilinx axi/xps_timebase_wdt |
3 | * | 3 | * |
4 | * (C) Copyright 2013 - 2014 Xilinx, Inc. | ||
4 | * (C) Copyright 2011 (Alejandro Cabrera <aldaya@gmail.com>) | 5 | * (C) Copyright 2011 (Alejandro Cabrera <aldaya@gmail.com>) |
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
@@ -14,12 +15,9 @@ | |||
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
15 | #include <linux/types.h> | 16 | #include <linux/types.h> |
16 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
17 | #include <linux/fs.h> | ||
18 | #include <linux/miscdevice.h> | ||
19 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
20 | #include <linux/watchdog.h> | 19 | #include <linux/watchdog.h> |
21 | #include <linux/io.h> | 20 | #include <linux/io.h> |
22 | #include <linux/uaccess.h> | ||
23 | #include <linux/of.h> | 21 | #include <linux/of.h> |
24 | #include <linux/of_device.h> | 22 | #include <linux/of_device.h> |
25 | #include <linux/of_address.h> | 23 | #include <linux/of_address.h> |
@@ -47,22 +45,18 @@ | |||
47 | struct xwdt_device { | 45 | struct xwdt_device { |
48 | struct resource res; | 46 | struct resource res; |
49 | void __iomem *base; | 47 | void __iomem *base; |
50 | u32 nowayout; | ||
51 | u32 wdt_interval; | 48 | u32 wdt_interval; |
52 | u32 boot_status; | ||
53 | }; | 49 | }; |
54 | 50 | ||
55 | static struct xwdt_device xdev; | 51 | static struct xwdt_device xdev; |
56 | 52 | ||
57 | static u32 timeout; | 53 | static u32 timeout; |
58 | static u32 control_status_reg; | 54 | static u32 control_status_reg; |
59 | static u8 expect_close; | ||
60 | static u8 no_timeout; | 55 | static u8 no_timeout; |
61 | static unsigned long driver_open; | ||
62 | 56 | ||
63 | static DEFINE_SPINLOCK(spinlock); | 57 | static DEFINE_SPINLOCK(spinlock); |
64 | 58 | ||
65 | static void xwdt_start(void) | 59 | static int xilinx_wdt_start(struct watchdog_device *wdd) |
66 | { | 60 | { |
67 | spin_lock(&spinlock); | 61 | spin_lock(&spinlock); |
68 | 62 | ||
@@ -76,9 +70,11 @@ static void xwdt_start(void) | |||
76 | iowrite32(XWT_CSRX_EWDT2_MASK, xdev.base + XWT_TWCSR1_OFFSET); | 70 | iowrite32(XWT_CSRX_EWDT2_MASK, xdev.base + XWT_TWCSR1_OFFSET); |
77 | 71 | ||
78 | spin_unlock(&spinlock); | 72 | spin_unlock(&spinlock); |
73 | |||
74 | return 0; | ||
79 | } | 75 | } |
80 | 76 | ||
81 | static void xwdt_stop(void) | 77 | static int xilinx_wdt_stop(struct watchdog_device *wdd) |
82 | { | 78 | { |
83 | spin_lock(&spinlock); | 79 | spin_lock(&spinlock); |
84 | 80 | ||
@@ -91,9 +87,11 @@ static void xwdt_stop(void) | |||
91 | 87 | ||
92 | spin_unlock(&spinlock); | 88 | spin_unlock(&spinlock); |
93 | pr_info("Stopped!\n"); | 89 | pr_info("Stopped!\n"); |
90 | |||
91 | return 0; | ||
94 | } | 92 | } |
95 | 93 | ||
96 | static void xwdt_keepalive(void) | 94 | static int xilinx_wdt_keepalive(struct watchdog_device *wdd) |
97 | { | 95 | { |
98 | spin_lock(&spinlock); | 96 | spin_lock(&spinlock); |
99 | 97 | ||
@@ -102,23 +100,28 @@ static void xwdt_keepalive(void) | |||
102 | iowrite32(control_status_reg, xdev.base + XWT_TWCSR0_OFFSET); | 100 | iowrite32(control_status_reg, xdev.base + XWT_TWCSR0_OFFSET); |
103 | 101 | ||
104 | spin_unlock(&spinlock); | 102 | spin_unlock(&spinlock); |
105 | } | ||
106 | 103 | ||
107 | static void xwdt_get_status(int *status) | 104 | return 0; |
108 | { | 105 | } |
109 | int new_status; | ||
110 | 106 | ||
111 | spin_lock(&spinlock); | 107 | static const struct watchdog_info xilinx_wdt_ident = { |
108 | .options = WDIOF_MAGICCLOSE | | ||
109 | WDIOF_KEEPALIVEPING, | ||
110 | .firmware_version = 1, | ||
111 | .identity = WATCHDOG_NAME, | ||
112 | }; | ||
112 | 113 | ||
113 | control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET); | 114 | static const struct watchdog_ops xilinx_wdt_ops = { |
114 | new_status = ((control_status_reg & | 115 | .owner = THIS_MODULE, |
115 | (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK)) != 0); | 116 | .start = xilinx_wdt_start, |
116 | spin_unlock(&spinlock); | 117 | .stop = xilinx_wdt_stop, |
118 | .ping = xilinx_wdt_keepalive, | ||
119 | }; | ||
117 | 120 | ||
118 | *status = 0; | 121 | static struct watchdog_device xilinx_wdt_wdd = { |
119 | if (new_status & 1) | 122 | .info = &xilinx_wdt_ident, |
120 | *status |= WDIOF_CARDRESET; | 123 | .ops = &xilinx_wdt_ops, |
121 | } | 124 | }; |
122 | 125 | ||
123 | static u32 xwdt_selftest(void) | 126 | static u32 xwdt_selftest(void) |
124 | { | 127 | { |
@@ -145,139 +148,6 @@ static u32 xwdt_selftest(void) | |||
145 | return XWT_TIMER_FAILED; | 148 | return XWT_TIMER_FAILED; |
146 | } | 149 | } |
147 | 150 | ||
148 | static int xwdt_open(struct inode *inode, struct file *file) | ||
149 | { | ||
150 | /* Only one process can handle the wdt at a time */ | ||
151 | if (test_and_set_bit(0, &driver_open)) | ||
152 | return -EBUSY; | ||
153 | |||
154 | /* Make sure that the module are always loaded...*/ | ||
155 | if (xdev.nowayout) | ||
156 | __module_get(THIS_MODULE); | ||
157 | |||
158 | xwdt_start(); | ||
159 | pr_info("Started...\n"); | ||
160 | |||
161 | return nonseekable_open(inode, file); | ||
162 | } | ||
163 | |||
164 | static int xwdt_release(struct inode *inode, struct file *file) | ||
165 | { | ||
166 | if (expect_close == 42) { | ||
167 | xwdt_stop(); | ||
168 | } else { | ||
169 | pr_crit("Unexpected close, not stopping watchdog!\n"); | ||
170 | xwdt_keepalive(); | ||
171 | } | ||
172 | |||
173 | clear_bit(0, &driver_open); | ||
174 | expect_close = 0; | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * xwdt_write: | ||
180 | * @file: file handle to the watchdog | ||
181 | * @buf: buffer to write (unused as data does not matter here | ||
182 | * @count: count of bytes | ||
183 | * @ppos: pointer to the position to write. No seeks allowed | ||
184 | * | ||
185 | * A write to a watchdog device is defined as a keepalive signal. Any | ||
186 | * write of data will do, as we don't define content meaning. | ||
187 | */ | ||
188 | static ssize_t xwdt_write(struct file *file, const char __user *buf, | ||
189 | size_t len, loff_t *ppos) | ||
190 | { | ||
191 | if (len) { | ||
192 | if (!xdev.nowayout) { | ||
193 | size_t i; | ||
194 | |||
195 | /* In case it was set long ago */ | ||
196 | expect_close = 0; | ||
197 | |||
198 | for (i = 0; i != len; i++) { | ||
199 | char c; | ||
200 | |||
201 | if (get_user(c, buf + i)) | ||
202 | return -EFAULT; | ||
203 | if (c == 'V') | ||
204 | expect_close = 42; | ||
205 | } | ||
206 | } | ||
207 | xwdt_keepalive(); | ||
208 | } | ||
209 | return len; | ||
210 | } | ||
211 | |||
212 | static const struct watchdog_info ident = { | ||
213 | .options = WDIOF_MAGICCLOSE | | ||
214 | WDIOF_KEEPALIVEPING, | ||
215 | .firmware_version = 1, | ||
216 | .identity = WATCHDOG_NAME, | ||
217 | }; | ||
218 | |||
219 | /* | ||
220 | * xwdt_ioctl: | ||
221 | * @file: file handle to the device | ||
222 | * @cmd: watchdog command | ||
223 | * @arg: argument pointer | ||
224 | * | ||
225 | * The watchdog API defines a common set of functions for all watchdogs | ||
226 | * according to their available features. | ||
227 | */ | ||
228 | static long xwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
229 | { | ||
230 | int status; | ||
231 | |||
232 | union { | ||
233 | struct watchdog_info __user *ident; | ||
234 | int __user *i; | ||
235 | } uarg; | ||
236 | |||
237 | uarg.i = (int __user *)arg; | ||
238 | |||
239 | switch (cmd) { | ||
240 | case WDIOC_GETSUPPORT: | ||
241 | return copy_to_user(uarg.ident, &ident, | ||
242 | sizeof(ident)) ? -EFAULT : 0; | ||
243 | |||
244 | case WDIOC_GETBOOTSTATUS: | ||
245 | return put_user(xdev.boot_status, uarg.i); | ||
246 | |||
247 | case WDIOC_GETSTATUS: | ||
248 | xwdt_get_status(&status); | ||
249 | return put_user(status, uarg.i); | ||
250 | |||
251 | case WDIOC_KEEPALIVE: | ||
252 | xwdt_keepalive(); | ||
253 | return 0; | ||
254 | |||
255 | case WDIOC_GETTIMEOUT: | ||
256 | if (no_timeout) | ||
257 | return -ENOTTY; | ||
258 | else | ||
259 | return put_user(timeout, uarg.i); | ||
260 | |||
261 | default: | ||
262 | return -ENOTTY; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | static const struct file_operations xwdt_fops = { | ||
267 | .owner = THIS_MODULE, | ||
268 | .llseek = no_llseek, | ||
269 | .write = xwdt_write, | ||
270 | .open = xwdt_open, | ||
271 | .release = xwdt_release, | ||
272 | .unlocked_ioctl = xwdt_ioctl, | ||
273 | }; | ||
274 | |||
275 | static struct miscdevice xwdt_miscdev = { | ||
276 | .minor = WATCHDOG_MINOR, | ||
277 | .name = "watchdog", | ||
278 | .fops = &xwdt_fops, | ||
279 | }; | ||
280 | |||
281 | static int xwdt_probe(struct platform_device *pdev) | 151 | static int xwdt_probe(struct platform_device *pdev) |
282 | { | 152 | { |
283 | int rc; | 153 | int rc; |
@@ -313,7 +183,7 @@ static int xwdt_probe(struct platform_device *pdev) | |||
313 | "xlnx,wdt-enable-once", NULL); | 183 | "xlnx,wdt-enable-once", NULL); |
314 | if (tmptr == NULL) { | 184 | if (tmptr == NULL) { |
315 | pr_warn("Parameter \"xlnx,wdt-enable-once\" not found in device tree!\n"); | 185 | pr_warn("Parameter \"xlnx,wdt-enable-once\" not found in device tree!\n"); |
316 | xdev.nowayout = WATCHDOG_NOWAYOUT; | 186 | watchdog_set_nowayout(&xilinx_wdt_wdd, true); |
317 | } | 187 | } |
318 | 188 | ||
319 | /* | 189 | /* |
@@ -343,24 +213,14 @@ static int xwdt_probe(struct platform_device *pdev) | |||
343 | goto unmap_io; | 213 | goto unmap_io; |
344 | } | 214 | } |
345 | 215 | ||
346 | xwdt_get_status(&xdev.boot_status); | 216 | rc = watchdog_register_device(&xilinx_wdt_wdd); |
347 | |||
348 | rc = misc_register(&xwdt_miscdev); | ||
349 | if (rc) { | 217 | if (rc) { |
350 | pr_err("cannot register miscdev on minor=%d (err=%d)\n", | 218 | pr_err("cannot register watchdog (err=%d)\n", rc); |
351 | xwdt_miscdev.minor, rc); | ||
352 | goto unmap_io; | 219 | goto unmap_io; |
353 | } | 220 | } |
354 | 221 | ||
355 | if (no_timeout) | 222 | dev_info(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds\n", |
356 | pr_info("driver loaded (timeout=? sec, nowayout=%d)\n", | 223 | xdev.base, timeout); |
357 | xdev.nowayout); | ||
358 | else | ||
359 | pr_info("driver loaded (timeout=%d sec, nowayout=%d)\n", | ||
360 | timeout, xdev.nowayout); | ||
361 | |||
362 | expect_close = 0; | ||
363 | clear_bit(0, &driver_open); | ||
364 | 224 | ||
365 | return 0; | 225 | return 0; |
366 | 226 | ||
@@ -374,7 +234,7 @@ err_out: | |||
374 | 234 | ||
375 | static int xwdt_remove(struct platform_device *dev) | 235 | static int xwdt_remove(struct platform_device *dev) |
376 | { | 236 | { |
377 | misc_deregister(&xwdt_miscdev); | 237 | watchdog_unregister_device(&xilinx_wdt_wdd); |
378 | iounmap(xdev.base); | 238 | iounmap(xdev.base); |
379 | release_mem_region(xdev.res.start, resource_size(&xdev.res)); | 239 | release_mem_region(xdev.res.start, resource_size(&xdev.res)); |
380 | 240 | ||