aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorMichal Simek <michal.simek@xilinx.com>2014-02-12 08:34:32 -0500
committerWim Van Sebroeck <wim@iguana.be>2014-03-31 07:28:56 -0400
commitd14fd9645501444f06034339118de56686e25dfb (patch)
tree9729037743b42ef0bf9e4dd99aa87493c37a7e1b /drivers/watchdog
parent70605d9bab216534a593f3ec8218ab8c015cb452 (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/Kconfig1
-rw-r--r--drivers/watchdog/of_xilinx_wdt.c204
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
1026config XILINX_WATCHDOG 1026config 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 @@
47struct xwdt_device { 45struct 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
55static struct xwdt_device xdev; 51static struct xwdt_device xdev;
56 52
57static u32 timeout; 53static u32 timeout;
58static u32 control_status_reg; 54static u32 control_status_reg;
59static u8 expect_close;
60static u8 no_timeout; 55static u8 no_timeout;
61static unsigned long driver_open;
62 56
63static DEFINE_SPINLOCK(spinlock); 57static DEFINE_SPINLOCK(spinlock);
64 58
65static void xwdt_start(void) 59static 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
81static void xwdt_stop(void) 77static 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
96static void xwdt_keepalive(void) 94static 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
107static void xwdt_get_status(int *status) 104 return 0;
108{ 105}
109 int new_status;
110 106
111 spin_lock(&spinlock); 107static 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); 114static 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; 121static 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
123static u32 xwdt_selftest(void) 126static 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
148static 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
164static 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 */
188static 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
212static 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 */
228static 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
266static 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
275static struct miscdevice xwdt_miscdev = {
276 .minor = WATCHDOG_MINOR,
277 .name = "watchdog",
278 .fops = &xwdt_fops,
279};
280
281static int xwdt_probe(struct platform_device *pdev) 151static 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
375static int xwdt_remove(struct platform_device *dev) 235static 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