1bcd726ebbd60eefc7997c54d07c57244daa495c
[linux-2.6.git] / drivers / watchdog / tegra_wdt.c
1 /*
2  * drivers/watchdog/tegra_wdt.c
3  *
4  * watchdog driver for NVIDIA tegra internal watchdog
5  *
6  * Copyright (c) 2012, NVIDIA Corporation.
7  *
8  * based on drivers/watchdog/softdog.c and drivers/watchdog/omap_wdt.c
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18  * more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23  */
24
25 #include <linux/kernel.h>
26 #include <linux/fs.h>
27 #include <linux/interrupt.h>
28 #include <linux/io.h>
29 #include <linux/kernel.h>
30 #include <linux/miscdevice.h>
31 #include <linux/notifier.h>
32 #include <linux/platform_device.h>
33 #include <linux/reboot.h>
34 #include <linux/slab.h>
35 #include <linux/spinlock.h>
36 #include <linux/uaccess.h>
37 #include <linux/watchdog.h>
38 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
39 #include <mach/irqs.h>
40 #endif
41
42 /* minimum and maximum watchdog trigger periods, in seconds */
43 #define MIN_WDT_PERIOD  5
44 #define MAX_WDT_PERIOD  1000
45 /* Assign Timer 7 to Timer 10 for WDT0 to WDT3, respectively */
46 #define TMR_SRC_START   7
47
48 enum tegra_wdt_status {
49         WDT_DISABLED = 1 << 0,
50         WDT_ENABLED = 1 << 1,
51         WDT_ENABLED_AT_PROBE = 1 << 2,
52 };
53
54 struct tegra_wdt {
55         struct miscdevice       miscdev;
56         struct notifier_block   notifier;
57         struct resource         *res_src;
58         struct resource         *res_wdt;
59         struct resource         *res_int_base;
60         unsigned long           users;
61         void __iomem            *wdt_source;
62         void __iomem            *wdt_timer;
63         void __iomem            *int_base;
64         int                     irq;
65         int                     tmrsrc;
66         int                     timeout;
67         int                     status;
68 };
69
70 /*
71  * For spinlock lockup detection to work, the heartbeat should be 2*lockup
72  * for cases where the spinlock disabled irqs.
73  */
74 static int heartbeat = 120; /* must be greater than MIN_WDT_PERIOD and lower than MAX_WDT_PERIOD */
75
76 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
77
78 #define TIMER_PTV               0x0
79  #define TIMER_EN               (1 << 31)
80  #define TIMER_PERIODIC         (1 << 30)
81 #define TIMER_PCR               0x4
82  #define TIMER_PCR_INTR         (1 << 30)
83 #define WDT_EN                  (1 << 5)
84 #define WDT_SEL_TMR1            (0 << 4)
85 #define WDT_SYS_RST             (1 << 2)
86
87 static void tegra_wdt_enable(struct tegra_wdt *wdt)
88 {
89         u32 val;
90
91         /* since the watchdog reset occurs when a second interrupt
92          * is asserted before the first is processed, program the
93          * timer period to one-half of the watchdog period */
94         val = wdt->timeout * 1000000ul / 2;
95         val |= (TIMER_EN | TIMER_PERIODIC);
96         writel(val, wdt->wdt_timer + TIMER_PTV);
97
98         val = WDT_EN | WDT_SEL_TMR1 | WDT_SYS_RST;
99         writel(val, wdt->wdt_source);
100 }
101
102 static void tegra_wdt_disable(struct tegra_wdt *wdt)
103 {
104         writel(0, wdt->wdt_source);
105         writel(0, wdt->wdt_timer + TIMER_PTV);
106 }
107
108 static inline void tegra_wdt_ping(struct tegra_wdt *wdt)
109 {
110         return;
111 }
112
113 static irqreturn_t tegra_wdt_interrupt(int irq, void *dev_id)
114 {
115         struct tegra_wdt *wdt = dev_id;
116
117         writel(TIMER_PCR_INTR, wdt->wdt_timer + TIMER_PCR);
118         return IRQ_HANDLED;
119 }
120 #elif defined(CONFIG_ARCH_TEGRA_3x_SOC)
121
122 #define TIMER_PTV                       0
123  #define TIMER_EN                       (1 << 31)
124  #define TIMER_PERIODIC                 (1 << 30)
125 #define TIMER_PCR                       0x4
126  #define TIMER_PCR_INTR                 (1 << 30)
127 #define WDT_CFG                         (0)
128  #define WDT_CFG_PERIOD                 (1 << 4)
129  #define WDT_CFG_INT_EN                 (1 << 12)
130  #define WDT_CFG_FIQ_INT_EN             (1 << 13)
131  #define WDT_CFG_SYS_RST_EN             (1 << 14)
132  #define WDT_CFG_PMC2CAR_RST_EN         (1 << 15)
133 #define WDT_STATUS                      (4)
134  #define WDT_INTR_STAT                  (1 << 1)
135 #define WDT_CMD                         (8)
136  #define WDT_CMD_START_COUNTER          (1 << 0)
137  #define WDT_CMD_DISABLE_COUNTER        (1 << 1)
138 #define WDT_UNLOCK                      (0xC)
139  #define WDT_UNLOCK_PATTERN             (0xC45A << 0)
140 #define ICTLR_IEP_CLASS                 0x2C
141 #define MAX_NR_CPU_WDT                  0x4
142
143 struct tegra_wdt *tegra_wdt[MAX_NR_CPU_WDT];
144
145 static inline void tegra_wdt_ping(struct tegra_wdt *wdt)
146 {
147         writel(WDT_CMD_START_COUNTER, wdt->wdt_source + WDT_CMD);
148 }
149
150 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
151 static void tegra_wdt_int_priority(struct tegra_wdt *wdt)
152 {
153         unsigned val = 0;
154
155         if (!wdt->int_base)
156                 return;
157         val = readl(wdt->int_base + ICTLR_IEP_CLASS);
158         val &= ~(1 << (INT_WDT_CPU & 31));
159         writel(val, wdt->int_base + ICTLR_IEP_CLASS);
160 }
161 #endif
162
163 static void tegra_wdt_enable(struct tegra_wdt *wdt)
164 {
165         u32 val;
166
167         writel(TIMER_PCR_INTR, wdt->wdt_timer + TIMER_PCR);
168         val = (wdt->timeout * 1000000ul) / 4;
169         val |= (TIMER_EN | TIMER_PERIODIC);
170         writel(val, wdt->wdt_timer + TIMER_PTV);
171
172         /* Interrupt handler is not required for user space
173          * WDT accesses, since the caller is responsible to ping the
174          * WDT to reset the counter before expiration, through ioctls.
175          * SYS_RST_EN doesnt work as there is no external reset
176          * from Tegra.
177          */
178         val = wdt->tmrsrc | WDT_CFG_PERIOD | /*WDT_CFG_INT_EN |*/
179                 /*WDT_CFG_SYS_RST_EN |*/ WDT_CFG_PMC2CAR_RST_EN;
180 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
181         val |= WDT_CFG_FIQ_INT_EN;
182 #endif
183         writel(val, wdt->wdt_source + WDT_CFG);
184         writel(WDT_CMD_START_COUNTER, wdt->wdt_source + WDT_CMD);
185 }
186
187 static void tegra_wdt_disable(struct tegra_wdt *wdt)
188 {
189         writel(WDT_UNLOCK_PATTERN, wdt->wdt_source + WDT_UNLOCK);
190         writel(WDT_CMD_DISABLE_COUNTER, wdt->wdt_source + WDT_CMD);
191
192         writel(0, wdt->wdt_timer + TIMER_PTV);
193 }
194
195 static irqreturn_t tegra_wdt_interrupt(int irq, void *dev_id)
196 {
197         unsigned i, status;
198
199         for (i = 0; i < MAX_NR_CPU_WDT; i++) {
200                 if (tegra_wdt[i] == NULL)
201                         continue;
202                 status = readl(tegra_wdt[i]->wdt_source + WDT_STATUS);
203                 if ((tegra_wdt[i]->status & WDT_ENABLED) &&
204                     (status & WDT_INTR_STAT))
205                         tegra_wdt_ping(tegra_wdt[i]);
206         }
207
208         return IRQ_HANDLED;
209 }
210 #endif
211
212 static int tegra_wdt_notify(struct notifier_block *this,
213                             unsigned long code, void *dev)
214 {
215         struct tegra_wdt *wdt = container_of(this, struct tegra_wdt, notifier);
216
217         if (code == SYS_DOWN || code == SYS_HALT)
218                 tegra_wdt_disable(wdt);
219         return NOTIFY_DONE;
220 }
221
222 static int tegra_wdt_open(struct inode *inode, struct file *file)
223 {
224         struct miscdevice *mdev = file->private_data;
225         struct tegra_wdt *wdt = container_of(mdev, struct tegra_wdt,
226                                              miscdev);
227
228         if (test_and_set_bit(1, &wdt->users))
229                 return -EBUSY;
230
231         wdt->status |= WDT_ENABLED;
232         wdt->timeout = heartbeat;
233         tegra_wdt_enable(wdt);
234         file->private_data = wdt;
235         return nonseekable_open(inode, file);
236 }
237
238 static int tegra_wdt_release(struct inode *inode, struct file *file)
239 {
240         struct tegra_wdt *wdt = file->private_data;
241
242         if (wdt->status == WDT_ENABLED) {
243 #ifndef CONFIG_WATCHDOG_NOWAYOUT
244                 tegra_wdt_disable(wdt);
245                 wdt->status = WDT_DISABLED;
246 #endif
247         }
248         wdt->users = 0;
249         return 0;
250 }
251
252 static long tegra_wdt_ioctl(struct file *file, unsigned int cmd,
253                             unsigned long arg)
254 {
255         struct tegra_wdt *wdt = file->private_data;
256         static DEFINE_SPINLOCK(lock);
257         int new_timeout;
258         int option;
259         static const struct watchdog_info ident = {
260                 .identity = "Tegra Watchdog",
261                 .options = WDIOF_SETTIMEOUT,
262                 .firmware_version = 0,
263         };
264
265         switch (cmd) {
266         case WDIOC_GETSUPPORT:
267                 return copy_to_user((struct watchdog_info __user *)arg, &ident,
268                                     sizeof(ident));
269         case WDIOC_GETSTATUS:
270         case WDIOC_GETBOOTSTATUS:
271                 return put_user(0, (int __user *)arg);
272
273         case WDIOC_KEEPALIVE:
274                 spin_lock(&lock);
275                 tegra_wdt_ping(wdt);
276                 spin_unlock(&lock);
277                 return 0;
278
279         case WDIOC_SETTIMEOUT:
280                 if (get_user(new_timeout, (int __user *)arg))
281                         return -EFAULT;
282                 spin_lock(&lock);
283                 tegra_wdt_disable(wdt);
284                 wdt->timeout = clamp(new_timeout, MIN_WDT_PERIOD, MAX_WDT_PERIOD);
285                 tegra_wdt_enable(wdt);
286                 spin_unlock(&lock);
287         case WDIOC_GETTIMEOUT:
288                 return put_user(wdt->timeout, (int __user *)arg);
289
290         case WDIOC_SETOPTIONS:
291 #ifndef CONFIG_WATCHDOG_NOWAYOUT
292                 if (get_user(option, (int __user *)arg))
293                         return -EFAULT;
294                 spin_lock(&lock);
295                 if (option & WDIOS_DISABLECARD) {
296                         wdt->status &= ~WDT_ENABLED;
297                         wdt->status |= WDT_DISABLED;
298                         tegra_wdt_disable(wdt);
299                 } else if (option & WDIOS_ENABLECARD) {
300                         tegra_wdt_enable(wdt);
301                         wdt->status |= WDT_ENABLED;
302                         wdt->status &= ~WDT_DISABLED;
303                 } else {
304                         spin_unlock(&lock);
305                         return -EINVAL;
306                 }
307                 spin_unlock(&lock);
308                 return 0;
309 #else
310                 return -EINVAL;
311 #endif
312         }
313         return -ENOTTY;
314 }
315
316 static ssize_t tegra_wdt_write(struct file *file, const char __user *data,
317                                size_t len, loff_t *ppos)
318 {
319         return len;
320 }
321
322 static const struct file_operations tegra_wdt_fops = {
323         .owner          = THIS_MODULE,
324         .llseek         = no_llseek,
325         .write          = tegra_wdt_write,
326         .unlocked_ioctl = tegra_wdt_ioctl,
327         .open           = tegra_wdt_open,
328         .release        = tegra_wdt_release,
329 };
330
331 static int tegra_wdt_probe(struct platform_device *pdev)
332 {
333         struct resource *res_src, *res_wdt, *res_irq;
334         struct resource *res_int_base = NULL;
335         struct tegra_wdt *wdt;
336         u32 src;
337         int ret = 0;
338
339         if (pdev->id < -1 && pdev->id > 3) {
340                 dev_err(&pdev->dev, "only IDs 3:0 supported\n");
341                 return -ENODEV;
342         }
343
344         res_src = platform_get_resource(pdev, IORESOURCE_MEM, 0);
345         res_wdt = platform_get_resource(pdev, IORESOURCE_MEM, 1);
346         res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
347
348         if (!res_src || !res_wdt || (!pdev->id && !res_irq)) {
349                 dev_err(&pdev->dev, "incorrect resources\n");
350                 return -ENOENT;
351         }
352
353 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
354         res_int_base = platform_get_resource(pdev, IORESOURCE_MEM, 2);
355         if (!pdev->id && !res_int_base) {
356                 dev_err(&pdev->dev, "FIQ_DBG: INT base not defined\n");
357                 return -ENOENT;
358         }
359 #endif
360
361         if (pdev->id == -1 && !res_irq) {
362                 dev_err(&pdev->dev, "incorrect irq\n");
363                 return -ENOENT;
364         }
365
366         wdt = kzalloc(sizeof(*wdt), GFP_KERNEL);
367         if (!wdt) {
368                 dev_err(&pdev->dev, "out of memory\n");
369                 return -ENOMEM;
370         }
371
372         wdt->irq = -1;
373         wdt->miscdev.parent = &pdev->dev;
374         if (pdev->id == -1) {
375                 wdt->miscdev.minor = WATCHDOG_MINOR;
376                 wdt->miscdev.name = "watchdog";
377         } else {
378                 wdt->miscdev.minor = MISC_DYNAMIC_MINOR;
379                 if (pdev->id == 0)
380                         wdt->miscdev.name = "watchdog0";
381                 else if (pdev->id == 1)
382                         wdt->miscdev.name = "watchdog1";
383                 else if (pdev->id == 2)
384                         wdt->miscdev.name = "watchdog2";
385                 else if (pdev->id == 3)
386                         wdt->miscdev.name = "watchdog3";
387         }
388         wdt->miscdev.fops = &tegra_wdt_fops;
389
390         wdt->notifier.notifier_call = tegra_wdt_notify;
391
392         res_src = request_mem_region(res_src->start, resource_size(res_src),
393                                      pdev->name);
394         res_wdt = request_mem_region(res_wdt->start, resource_size(res_wdt),
395                                      pdev->name);
396
397         if (!res_src || !res_wdt) {
398                 dev_err(&pdev->dev, "unable to request memory resources\n");
399                 ret = -EBUSY;
400                 goto fail;
401         }
402
403         wdt->wdt_source = ioremap(res_src->start, resource_size(res_src));
404         wdt->wdt_timer = ioremap(res_wdt->start, resource_size(res_wdt));
405         /* tmrsrc will be used to set WDT_CFG */
406         wdt->tmrsrc = (TMR_SRC_START + pdev->id) % 10;
407         if (!wdt->wdt_source || !wdt->wdt_timer) {
408                 dev_err(&pdev->dev, "unable to map registers\n");
409                 ret = -ENOMEM;
410                 goto fail;
411         }
412
413         src = readl(wdt->wdt_source);
414         if (src & BIT(12))
415                 dev_info(&pdev->dev, "last reset due to watchdog timeout\n");
416
417         tegra_wdt_disable(wdt);
418         writel(TIMER_PCR_INTR, wdt->wdt_timer + TIMER_PCR);
419
420         if (res_irq != NULL) {
421 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
422                 /* FIQ debugger enables FIQ priority for INT_WDT_CPU.
423                  * But that will disable IRQ on WDT expiration.
424                  * Reset the priority back to IRQ on INT_WDT_CPU so
425                  * that tegra_wdt_interrupt gets its chance to restart the
426                  * counter before expiration.
427                  */
428                 res_int_base = request_mem_region(res_int_base->start,
429                                                   resource_size(res_int_base),
430                                                   pdev->name);
431                 if (!res_int_base)
432                         goto fail;
433                 wdt->int_base = ioremap(res_int_base->start,
434                                         resource_size(res_int_base));
435                 if (!wdt->int_base)
436                         goto fail;
437                 tegra_wdt_int_priority(wdt);
438 #endif
439                 ret = request_irq(res_irq->start, tegra_wdt_interrupt,
440                                   IRQF_DISABLED, dev_name(&pdev->dev), wdt);
441                 if (ret) {
442                         dev_err(&pdev->dev, "unable to configure IRQ\n");
443                         goto fail;
444                 }
445                 wdt->irq = res_irq->start;
446         }
447
448         wdt->res_src = res_src;
449         wdt->res_wdt = res_wdt;
450         wdt->res_int_base = res_int_base;
451         wdt->status = WDT_DISABLED;
452
453         ret = register_reboot_notifier(&wdt->notifier);
454         if (ret) {
455                 dev_err(&pdev->dev, "cannot register reboot notifier\n");
456                 goto fail;
457         }
458
459         ret = misc_register(&wdt->miscdev);
460         if (ret) {
461                 dev_err(&pdev->dev, "failed to register misc device\n");
462                 unregister_reboot_notifier(&wdt->notifier);
463                 goto fail;
464         }
465
466         platform_set_drvdata(pdev, wdt);
467
468 #ifndef CONFIG_ARCH_TEGRA_2x_SOC
469 #ifdef CONFIG_TEGRA_WATCHDOG_ENABLE_ON_PROBE
470         /* Init and enable watchdog on WDT0 with timer 8 during probe */
471         if (!(pdev->id)) {
472                 u32 val = 0;
473                 wdt->status = WDT_ENABLED | WDT_ENABLED_AT_PROBE;
474                 wdt->timeout = heartbeat;
475                 tegra_wdt_enable(wdt);
476                 val = readl(wdt->wdt_source + WDT_CFG);
477                 val |= WDT_CFG_INT_EN;
478                 writel(val, wdt->wdt_source + WDT_CFG);
479                 pr_info("WDT heartbeat enabled on probe\n");
480         }
481 #endif
482         tegra_wdt[pdev->id] = wdt;
483 #endif
484         pr_info("%s done\n", __func__);
485         return 0;
486 fail:
487         if (wdt->irq != -1)
488                 free_irq(wdt->irq, wdt);
489         if (wdt->wdt_source)
490                 iounmap(wdt->wdt_source);
491         if (wdt->wdt_timer)
492                 iounmap(wdt->wdt_timer);
493         if (wdt->int_base)
494                 iounmap(wdt->int_base);
495         if (res_src)
496                 release_mem_region(res_src->start, resource_size(res_src));
497         if (res_wdt)
498                 release_mem_region(res_wdt->start, resource_size(res_wdt));
499         if (res_int_base)
500                 release_mem_region(res_int_base->start,
501                                         resource_size(res_int_base));
502         kfree(wdt);
503         return ret;
504 }
505
506 static int tegra_wdt_remove(struct platform_device *pdev)
507 {
508         struct tegra_wdt *wdt = platform_get_drvdata(pdev);
509
510         tegra_wdt_disable(wdt);
511
512         unregister_reboot_notifier(&wdt->notifier);
513         misc_deregister(&wdt->miscdev);
514         if (wdt->irq != -1)
515                 free_irq(wdt->irq, wdt);
516         iounmap(wdt->wdt_source);
517         iounmap(wdt->wdt_timer);
518         if (wdt->int_base)
519                 iounmap(wdt->int_base);
520         release_mem_region(wdt->res_src->start, resource_size(wdt->res_src));
521         release_mem_region(wdt->res_wdt->start, resource_size(wdt->res_wdt));
522         if (wdt->res_int_base)
523                 release_mem_region(wdt->res_int_base->start,
524                                         resource_size(wdt->res_int_base));
525         kfree(wdt);
526         platform_set_drvdata(pdev, NULL);
527         return 0;
528 }
529
530 #ifdef CONFIG_PM
531 static int tegra_wdt_suspend(struct platform_device *pdev, pm_message_t state)
532 {
533         struct tegra_wdt *wdt = platform_get_drvdata(pdev);
534
535         tegra_wdt_disable(wdt);
536         return 0;
537 }
538
539 static int tegra_wdt_resume(struct platform_device *pdev)
540 {
541         struct tegra_wdt *wdt = platform_get_drvdata(pdev);
542
543         if (wdt->status & WDT_ENABLED)
544                 tegra_wdt_enable(wdt);
545
546 #ifndef CONFIG_ARCH_TEGRA_2x_SOC
547         /* Enable interrupt for WDT3 heartbeat watchdog */
548         if (wdt->status & WDT_ENABLED_AT_PROBE) {
549                 u32 val = 0;
550                 val = readl(wdt->wdt_source + WDT_CFG);
551                 val |= WDT_CFG_INT_EN;
552                 writel(val, wdt->wdt_source + WDT_CFG);
553                 pr_info("WDT heartbeat enabled on probe\n");
554         }
555 #endif
556         return 0;
557 }
558 #endif
559
560 static struct platform_driver tegra_wdt_driver = {
561         .probe          = tegra_wdt_probe,
562         .remove         = __devexit_p(tegra_wdt_remove),
563 #ifdef CONFIG_PM
564         .suspend        = tegra_wdt_suspend,
565         .resume         = tegra_wdt_resume,
566 #endif
567         .driver         = {
568                 .owner  = THIS_MODULE,
569                 .name   = "tegra_wdt",
570         },
571 };
572
573 static int __init tegra_wdt_init(void)
574 {
575         return platform_driver_register(&tegra_wdt_driver);
576 }
577
578 static void __exit tegra_wdt_exit(void)
579 {
580         platform_driver_unregister(&tegra_wdt_driver);
581 }
582
583 module_init(tegra_wdt_init);
584 module_exit(tegra_wdt_exit);
585
586 MODULE_AUTHOR("NVIDIA Corporation");
587 MODULE_DESCRIPTION("Tegra Watchdog Driver");
588
589 module_param(heartbeat, int, 0);
590 MODULE_PARM_DESC(heartbeat,
591                  "Watchdog heartbeat period in seconds");
592
593 MODULE_LICENSE("GPL");
594 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
595 MODULE_ALIAS("platform:tegra_wdt");