watchdog: nowayout is bool
[cascardo/linux.git] / drivers / watchdog / sp805_wdt.c
1 /*
2  * drivers/char/watchdog/sp805-wdt.c
3  *
4  * Watchdog driver for ARM SP805 watchdog module
5  *
6  * Copyright (C) 2010 ST Microelectronics
7  * Viresh Kumar<viresh.kumar@st.com>
8  *
9  * This file is licensed under the terms of the GNU General Public
10  * License version 2 or later. This program is licensed "as is" without any
11  * warranty of any kind, whether express or implied.
12  */
13
14 #include <linux/device.h>
15 #include <linux/resource.h>
16 #include <linux/amba/bus.h>
17 #include <linux/bitops.h>
18 #include <linux/clk.h>
19 #include <linux/fs.h>
20 #include <linux/init.h>
21 #include <linux/io.h>
22 #include <linux/ioport.h>
23 #include <linux/kernel.h>
24 #include <linux/math64.h>
25 #include <linux/miscdevice.h>
26 #include <linux/module.h>
27 #include <linux/moduleparam.h>
28 #include <linux/pm.h>
29 #include <linux/slab.h>
30 #include <linux/spinlock.h>
31 #include <linux/types.h>
32 #include <linux/uaccess.h>
33 #include <linux/watchdog.h>
34
35 /* default timeout in seconds */
36 #define DEFAULT_TIMEOUT         60
37
38 #define MODULE_NAME             "sp805-wdt"
39
40 /* watchdog register offsets and masks */
41 #define WDTLOAD                 0x000
42         #define LOAD_MIN        0x00000001
43         #define LOAD_MAX        0xFFFFFFFF
44 #define WDTVALUE                0x004
45 #define WDTCONTROL              0x008
46         /* control register masks */
47         #define INT_ENABLE      (1 << 0)
48         #define RESET_ENABLE    (1 << 1)
49 #define WDTINTCLR               0x00C
50 #define WDTRIS                  0x010
51 #define WDTMIS                  0x014
52         #define INT_MASK        (1 << 0)
53 #define WDTLOCK                 0xC00
54         #define UNLOCK          0x1ACCE551
55         #define LOCK            0x00000001
56
57 /**
58  * struct sp805_wdt: sp805 wdt device structure
59  *
60  * lock: spin lock protecting dev structure and io access
61  * base: base address of wdt
62  * clk: clock structure of wdt
63  * dev: amba device structure of wdt
64  * status: current status of wdt
65  * load_val: load value to be set for current timeout
66  * timeout: current programmed timeout
67  */
68 struct sp805_wdt {
69         spinlock_t                      lock;
70         void __iomem                    *base;
71         struct clk                      *clk;
72         struct amba_device              *adev;
73         unsigned long                   status;
74         #define WDT_BUSY                0
75         #define WDT_CAN_BE_CLOSED       1
76         unsigned int                    load_val;
77         unsigned int                    timeout;
78 };
79
80 /* local variables */
81 static struct sp805_wdt *wdt;
82 static bool nowayout = WATCHDOG_NOWAYOUT;
83
84 /* This routine finds load value that will reset system in required timout */
85 static void wdt_setload(unsigned int timeout)
86 {
87         u64 load, rate;
88
89         rate = clk_get_rate(wdt->clk);
90
91         /*
92          * sp805 runs counter with given value twice, after the end of first
93          * counter it gives an interrupt and then starts counter again. If
94          * interrupt already occurred then it resets the system. This is why
95          * load is half of what should be required.
96          */
97         load = div_u64(rate, 2) * timeout - 1;
98
99         load = (load > LOAD_MAX) ? LOAD_MAX : load;
100         load = (load < LOAD_MIN) ? LOAD_MIN : load;
101
102         spin_lock(&wdt->lock);
103         wdt->load_val = load;
104         /* roundup timeout to closest positive integer value */
105         wdt->timeout = div_u64((load + 1) * 2 + (rate / 2), rate);
106         spin_unlock(&wdt->lock);
107 }
108
109 /* returns number of seconds left for reset to occur */
110 static u32 wdt_timeleft(void)
111 {
112         u64 load, rate;
113
114         rate = clk_get_rate(wdt->clk);
115
116         spin_lock(&wdt->lock);
117         load = readl(wdt->base + WDTVALUE);
118
119         /*If the interrupt is inactive then time left is WDTValue + WDTLoad. */
120         if (!(readl(wdt->base + WDTRIS) & INT_MASK))
121                 load += wdt->load_val + 1;
122         spin_unlock(&wdt->lock);
123
124         return div_u64(load, rate);
125 }
126
127 /* enables watchdog timers reset */
128 static void wdt_enable(void)
129 {
130         spin_lock(&wdt->lock);
131
132         writel(UNLOCK, wdt->base + WDTLOCK);
133         writel(wdt->load_val, wdt->base + WDTLOAD);
134         writel(INT_MASK, wdt->base + WDTINTCLR);
135         writel(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL);
136         writel(LOCK, wdt->base + WDTLOCK);
137
138         /* Flush posted writes. */
139         readl(wdt->base + WDTLOCK);
140         spin_unlock(&wdt->lock);
141 }
142
143 /* disables watchdog timers reset */
144 static void wdt_disable(void)
145 {
146         spin_lock(&wdt->lock);
147
148         writel(UNLOCK, wdt->base + WDTLOCK);
149         writel(0, wdt->base + WDTCONTROL);
150         writel(LOCK, wdt->base + WDTLOCK);
151
152         /* Flush posted writes. */
153         readl(wdt->base + WDTLOCK);
154         spin_unlock(&wdt->lock);
155 }
156
157 static ssize_t sp805_wdt_write(struct file *file, const char *data,
158                 size_t len, loff_t *ppos)
159 {
160         if (len) {
161                 if (!nowayout) {
162                         size_t i;
163
164                         clear_bit(WDT_CAN_BE_CLOSED, &wdt->status);
165
166                         for (i = 0; i != len; i++) {
167                                 char c;
168
169                                 if (get_user(c, data + i))
170                                         return -EFAULT;
171                                 /* Check for Magic Close character */
172                                 if (c == 'V') {
173                                         set_bit(WDT_CAN_BE_CLOSED,
174                                                         &wdt->status);
175                                         break;
176                                 }
177                         }
178                 }
179                 wdt_enable();
180         }
181         return len;
182 }
183
184 static const struct watchdog_info ident = {
185         .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
186         .identity = MODULE_NAME,
187 };
188
189 static long sp805_wdt_ioctl(struct file *file, unsigned int cmd,
190                 unsigned long arg)
191 {
192         int ret = -ENOTTY;
193         unsigned int timeout;
194
195         switch (cmd) {
196         case WDIOC_GETSUPPORT:
197                 ret = copy_to_user((struct watchdog_info *)arg, &ident,
198                                 sizeof(ident)) ? -EFAULT : 0;
199                 break;
200
201         case WDIOC_GETSTATUS:
202                 ret = put_user(0, (int *)arg);
203                 break;
204
205         case WDIOC_KEEPALIVE:
206                 wdt_enable();
207                 ret = 0;
208                 break;
209
210         case WDIOC_SETTIMEOUT:
211                 ret = get_user(timeout, (unsigned int *)arg);
212                 if (ret)
213                         break;
214
215                 wdt_setload(timeout);
216
217                 wdt_enable();
218                 /* Fall through */
219
220         case WDIOC_GETTIMEOUT:
221                 ret = put_user(wdt->timeout, (unsigned int *)arg);
222                 break;
223         case WDIOC_GETTIMELEFT:
224                 ret = put_user(wdt_timeleft(), (unsigned int *)arg);
225                 break;
226         }
227         return ret;
228 }
229
230 static int sp805_wdt_open(struct inode *inode, struct file *file)
231 {
232         int ret = 0;
233
234         if (test_and_set_bit(WDT_BUSY, &wdt->status))
235                 return -EBUSY;
236
237         ret = clk_enable(wdt->clk);
238         if (ret) {
239                 dev_err(&wdt->adev->dev, "clock enable fail");
240                 goto err;
241         }
242
243         wdt_enable();
244
245         /* can not be closed, once enabled */
246         clear_bit(WDT_CAN_BE_CLOSED, &wdt->status);
247         return nonseekable_open(inode, file);
248
249 err:
250         clear_bit(WDT_BUSY, &wdt->status);
251         return ret;
252 }
253
254 static int sp805_wdt_release(struct inode *inode, struct file *file)
255 {
256         if (!test_bit(WDT_CAN_BE_CLOSED, &wdt->status)) {
257                 clear_bit(WDT_BUSY, &wdt->status);
258                 dev_warn(&wdt->adev->dev, "Device closed unexpectedly\n");
259                 return 0;
260         }
261
262         wdt_disable();
263         clk_disable(wdt->clk);
264         clear_bit(WDT_BUSY, &wdt->status);
265
266         return 0;
267 }
268
269 static const struct file_operations sp805_wdt_fops = {
270         .owner = THIS_MODULE,
271         .llseek = no_llseek,
272         .write = sp805_wdt_write,
273         .unlocked_ioctl = sp805_wdt_ioctl,
274         .open = sp805_wdt_open,
275         .release = sp805_wdt_release,
276 };
277
278 static struct miscdevice sp805_wdt_miscdev = {
279         .minor = WATCHDOG_MINOR,
280         .name = "watchdog",
281         .fops = &sp805_wdt_fops,
282 };
283
284 static int __devinit
285 sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
286 {
287         int ret = 0;
288
289         if (!request_mem_region(adev->res.start, resource_size(&adev->res),
290                                 "sp805_wdt")) {
291                 dev_warn(&adev->dev, "Failed to get memory region resource\n");
292                 ret = -ENOENT;
293                 goto err;
294         }
295
296         wdt = kzalloc(sizeof(*wdt), GFP_KERNEL);
297         if (!wdt) {
298                 dev_warn(&adev->dev, "Kzalloc failed\n");
299                 ret = -ENOMEM;
300                 goto err_kzalloc;
301         }
302
303         wdt->clk = clk_get(&adev->dev, NULL);
304         if (IS_ERR(wdt->clk)) {
305                 dev_warn(&adev->dev, "Clock not found\n");
306                 ret = PTR_ERR(wdt->clk);
307                 goto err_clk_get;
308         }
309
310         wdt->base = ioremap(adev->res.start, resource_size(&adev->res));
311         if (!wdt->base) {
312                 ret = -ENOMEM;
313                 dev_warn(&adev->dev, "ioremap fail\n");
314                 goto err_ioremap;
315         }
316
317         wdt->adev = adev;
318         spin_lock_init(&wdt->lock);
319         wdt_setload(DEFAULT_TIMEOUT);
320
321         ret = misc_register(&sp805_wdt_miscdev);
322         if (ret < 0) {
323                 dev_warn(&adev->dev, "cannot register misc device\n");
324                 goto err_misc_register;
325         }
326
327         dev_info(&adev->dev, "registration successful\n");
328         return 0;
329
330 err_misc_register:
331         iounmap(wdt->base);
332 err_ioremap:
333         clk_put(wdt->clk);
334 err_clk_get:
335         kfree(wdt);
336         wdt = NULL;
337 err_kzalloc:
338         release_mem_region(adev->res.start, resource_size(&adev->res));
339 err:
340         dev_err(&adev->dev, "Probe Failed!!!\n");
341         return ret;
342 }
343
344 static int __devexit sp805_wdt_remove(struct amba_device *adev)
345 {
346         misc_deregister(&sp805_wdt_miscdev);
347         iounmap(wdt->base);
348         clk_put(wdt->clk);
349         kfree(wdt);
350         release_mem_region(adev->res.start, resource_size(&adev->res));
351
352         return 0;
353 }
354
355 #ifdef CONFIG_PM
356 static int sp805_wdt_suspend(struct device *dev)
357 {
358         if (test_bit(WDT_BUSY, &wdt->status)) {
359                 wdt_disable();
360                 clk_disable(wdt->clk);
361         }
362
363         return 0;
364 }
365
366 static int sp805_wdt_resume(struct device *dev)
367 {
368         int ret = 0;
369
370         if (test_bit(WDT_BUSY, &wdt->status)) {
371                 ret = clk_enable(wdt->clk);
372                 if (ret) {
373                         dev_err(dev, "clock enable fail");
374                         return ret;
375                 }
376                 wdt_enable();
377         }
378
379         return ret;
380 }
381 #endif /* CONFIG_PM */
382
383 static SIMPLE_DEV_PM_OPS(sp805_wdt_dev_pm_ops, sp805_wdt_suspend,
384                 sp805_wdt_resume);
385
386 static struct amba_id sp805_wdt_ids[] = {
387         {
388                 .id     = 0x00141805,
389                 .mask   = 0x00ffffff,
390         },
391         { 0, 0 },
392 };
393
394 MODULE_DEVICE_TABLE(amba, sp805_wdt_ids);
395
396 static struct amba_driver sp805_wdt_driver = {
397         .drv = {
398                 .name   = MODULE_NAME,
399                 .pm     = &sp805_wdt_dev_pm_ops,
400         },
401         .id_table       = sp805_wdt_ids,
402         .probe          = sp805_wdt_probe,
403         .remove = __devexit_p(sp805_wdt_remove),
404 };
405
406 module_amba_driver(sp805_wdt_driver);
407
408 module_param(nowayout, bool, 0);
409 MODULE_PARM_DESC(nowayout,
410                 "Set to 1 to keep watchdog running after device release");
411
412 MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
413 MODULE_DESCRIPTION("ARM SP805 Watchdog Driver");
414 MODULE_LICENSE("GPL");
415 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);