video: tegra: dc: Add quick for Vizio P series
[linux-3.10.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-2016, NVIDIA CORPORATION. All rights reserved.
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/module.h>
27 #include <linux/fs.h>
28 #include <linux/debugfs.h>
29 #include <linux/interrupt.h>
30 #include <linux/io.h>
31 #include <linux/kernel.h>
32 #include <linux/of.h>
33 #include <linux/platform_device.h>
34 #include <linux/slab.h>
35 #include <linux/spinlock.h>
36 #include <linux/syscore_ops.h>
37 #include <linux/uaccess.h>
38 #include <linux/watchdog.h>
39 #include <linux/tegra-soc.h>
40 #include <linux/suspend.h>
41
42 /* minimum and maximum watchdog trigger periods, in seconds */
43 #define MIN_WDT_PERIOD  5
44 #define MAX_WDT_PERIOD  1000
45
46 struct tegra_wdt {
47         struct platform_device  *pdev;
48         struct watchdog_device  wdt;
49         unsigned long           users;
50         void __iomem            *wdt_source;
51         void __iomem            *wdt_timer;
52         u32                     config;
53         int                     irq;
54         unsigned long           status;
55         struct notifier_block   wdt_pm_nb;
56         bool                    extended_suspend;
57 /* Bit numbers for status flags */
58 #define WDT_ENABLED             0
59 #define WDT_ENABLED_ON_INIT     1
60 #define WDT_ENABLED_USERSPACE   2
61 };
62
63 /*
64  * The total expiry count of Tegra WDTs is limited to HW design and depends
65  * on skip configuration if supported. To be safe, we set the default expiry
66  * count to 1. It should be updated later with value specified in device tree.
67  */
68 static int expiry_count = 1;
69
70 /*
71  * To detect lockup condition, the heartbeat should be expiry_count*lockup.
72  * It may be taken over later by timeout value requested by application.
73  * Must be greater than expiry_count*MIN_WDT_PERIOD and lower than
74  * expiry_count*MAX_WDT_PERIOD.
75  */
76 static int heartbeat = 120;
77
78 static bool nowayout = WATCHDOG_NOWAYOUT;
79 module_param(nowayout, bool, 0);
80 MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
81
82 static struct syscore_ops tegra_wdt_syscore_ops;
83
84 struct tegra_wdt *s_tegra_wdt;
85
86 static inline struct tegra_wdt *to_tegra_wdt(struct watchdog_device *wdt)
87 {
88         return container_of(wdt, struct tegra_wdt, wdt);
89 }
90
91 #define TIMER_PTV                       0
92 #define TIMER_EN                        (1 << 31)
93 #define TIMER_PERIODIC                  (1 << 30)
94 #define TIMER_PCR                       0x4
95 #define TIMER_PCR_INTR                  (1 << 30)
96 #define WDT_CFG                         (0)
97 #define WDT_CFG_PERIOD                  (1 << 4)
98 #define WDT_CFG_INT_EN                  (1 << 12)
99 #define WDT_CFG_FIQ_EN                  (1 << 13)
100 #define WDT_CFG_SYS_RST_EN              (1 << 14)
101 #define WDT_CFG_PMC2CAR_RST_EN          (1 << 15)
102 #define WDT_STATUS                      (4)
103 #define WDT_INTR_STAT                   (1 << 1)
104 #define WDT_CMD                         (8)
105 #define WDT_CMD_START_COUNTER           (1 << 0)
106 #define WDT_CMD_DISABLE_COUNTER         (1 << 1)
107 #define WDT_UNLOCK                      (0xC)
108 #define WDT_UNLOCK_PATTERN              (0xC45A << 0)
109 #define MAX_NR_CPU_WDT                  0x4
110
111 static int __tegra_wdt_ping(struct tegra_wdt *tegra_wdt)
112 {
113         u32 val;
114
115         /*
116          * Disable timer, load the timeout value and restart.
117          */
118         writel(WDT_UNLOCK_PATTERN, tegra_wdt->wdt_source + WDT_UNLOCK);
119         writel(WDT_CMD_DISABLE_COUNTER, tegra_wdt->wdt_source + WDT_CMD);
120
121         writel(TIMER_PCR_INTR, tegra_wdt->wdt_timer + TIMER_PCR);
122         val = (tegra_wdt->wdt.timeout * USEC_PER_SEC) / expiry_count;
123         val |= (TIMER_EN | TIMER_PERIODIC);
124         writel(val, tegra_wdt->wdt_timer + TIMER_PTV);
125
126         writel(WDT_CMD_START_COUNTER, tegra_wdt->wdt_source + WDT_CMD);
127
128         dev_dbg(tegra_wdt->wdt.dev, "wdt cleared\n");
129         return 0;
130 }
131
132 static irqreturn_t tegra_wdt_irq(int irq, void *data)
133 {
134         struct tegra_wdt *tegra_wdt = data;
135
136         __tegra_wdt_ping(tegra_wdt);
137
138         return IRQ_HANDLED;
139 }
140
141 static void tegra_wdt_ref(struct watchdog_device *wdt)
142 {
143         struct tegra_wdt *tegra_wdt = to_tegra_wdt(wdt);
144
145         if (tegra_wdt->irq <= 0)
146                 return;
147
148         /*
149          * Remove the interrupt handler if userspace is taking over WDT.
150          */
151         if (!test_and_set_bit(WDT_ENABLED_USERSPACE, &tegra_wdt->status) &&
152                         test_bit(WDT_ENABLED_ON_INIT, &tegra_wdt->status))
153                 devm_free_irq(&tegra_wdt->pdev->dev, tegra_wdt->irq,
154                         tegra_wdt);
155 }
156
157 static int __tegra_wdt_enable(struct tegra_wdt *tegra_wdt)
158 {
159         u32 val;
160
161         writel(TIMER_PCR_INTR, tegra_wdt->wdt_timer + TIMER_PCR);
162         /*
163          * The timeout needs to be divided by expiry_count here so as to
164          * keep the ultimate watchdog reset timeout the same as the program
165          * timeout requested by application. The program timeout should make
166          * sure WDT FIQ will never be asserted in a valid use case.
167          */
168         val = (tegra_wdt->wdt.timeout * USEC_PER_SEC) / expiry_count;
169         val |= (TIMER_EN | TIMER_PERIODIC);
170         writel(val, tegra_wdt->wdt_timer + TIMER_PTV);
171
172         writel(tegra_wdt->config, tegra_wdt->wdt_source + WDT_CFG);
173         writel(WDT_CMD_START_COUNTER, tegra_wdt->wdt_source + WDT_CMD);
174
175         set_bit(WDT_ENABLED, &tegra_wdt->status);
176
177         return 0;
178 }
179
180 static int __tegra_wdt_disable(struct tegra_wdt *tegra_wdt)
181 {
182         writel(WDT_UNLOCK_PATTERN, tegra_wdt->wdt_source + WDT_UNLOCK);
183         writel(WDT_CMD_DISABLE_COUNTER, tegra_wdt->wdt_source + WDT_CMD);
184
185         writel(0, tegra_wdt->wdt_timer + TIMER_PTV);
186
187         clear_bit(WDT_ENABLED, &tegra_wdt->status);
188
189         return 0;
190 }
191
192 static int tegra_wdt_enable(struct watchdog_device *wdt)
193 {
194         struct tegra_wdt *tegra_wdt = to_tegra_wdt(wdt);
195         return __tegra_wdt_enable(tegra_wdt);
196 }
197
198 static int tegra_wdt_disable(struct watchdog_device *wdt)
199 {
200         struct tegra_wdt *tegra_wdt = to_tegra_wdt(wdt);
201         return __tegra_wdt_disable(tegra_wdt);
202 }
203
204 static int tegra_wdt_ping(struct watchdog_device *wdt)
205 {
206         struct tegra_wdt *tegra_wdt = to_tegra_wdt(wdt);
207         return __tegra_wdt_ping(tegra_wdt);
208 }
209
210
211 static int tegra_wdt_set_timeout(struct watchdog_device *wdt,
212         unsigned int timeout)
213 {
214         tegra_wdt_disable(wdt);
215         wdt->timeout = timeout;
216         tegra_wdt_enable(wdt);
217
218         dev_info(wdt->dev, "wdt timeout set to %u seconds\n", timeout);
219         return 0;
220 }
221
222 static const struct watchdog_info tegra_wdt_info = {
223         .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
224         .identity = "Tegra WDT",
225         .firmware_version = 1,
226 };
227
228 static const struct watchdog_ops tegra_wdt_ops = {
229         .owner = THIS_MODULE,
230         .start = tegra_wdt_enable,
231         .stop  = tegra_wdt_disable,
232         .ping  = tegra_wdt_ping,
233         .set_timeout = tegra_wdt_set_timeout,
234         .ref   = tegra_wdt_ref,
235 };
236
237 static int tegra_pm_notify(struct notifier_block *nb,
238                         unsigned long event, void *data)
239 {
240         struct tegra_wdt *tegra_wdt;
241
242         tegra_wdt = container_of(nb, struct tegra_wdt, wdt_pm_nb);
243
244         switch (event) {
245         case PM_USERSPACE_FROZEN:
246                 __tegra_wdt_ping(tegra_wdt);
247                 break;
248         }
249
250         return NOTIFY_OK;
251 }
252
253 #ifdef CONFIG_DEBUG_FS
254
255 static int disable_wdt_reset_show(void *data, u64 *val)
256 {
257         struct tegra_wdt *tegra_wdt = data;
258
259         *val = tegra_wdt->config &
260                         (WDT_CFG_SYS_RST_EN | WDT_CFG_PMC2CAR_RST_EN)
261                         ? 0 : 1;
262         return 0;
263 }
264
265 static int disable_wdt_reset_store(void *data, u64 val)
266 {
267         struct tegra_wdt *tegra_wdt = data;
268
269         tegra_wdt->config = readl(tegra_wdt->wdt_source + WDT_CFG);
270         if (val)
271                 tegra_wdt->config &= ~(WDT_CFG_SYS_RST_EN | WDT_CFG_PMC2CAR_RST_EN);
272         else
273                 tegra_wdt->config |= WDT_CFG_PMC2CAR_RST_EN;
274
275         /* Apply config only if WDT is enabled */
276         if (test_bit(WDT_ENABLED, &tegra_wdt->status)) {
277                 __tegra_wdt_disable(tegra_wdt);
278                 __tegra_wdt_enable(tegra_wdt);
279         }
280
281         return 0;
282 }
283
284 DEFINE_SIMPLE_ATTRIBUTE(disable_wdt_reset_fops, disable_wdt_reset_show,
285         disable_wdt_reset_store, "%lld\n");
286
287 static void tegra_wdt_debugfs_init(struct tegra_wdt *tegra_wdt)
288 {
289         struct dentry *root;
290         struct dentry *retval;
291
292         root = debugfs_create_dir("tegra_wdt", NULL);
293         if (IS_ERR_OR_NULL(root))
294                 goto clean;
295
296         retval = debugfs_create_file("disable_wdt_reset", S_IRUGO | S_IWUSR,
297                                 root, (void *)tegra_wdt, &disable_wdt_reset_fops);
298         if (IS_ERR_OR_NULL(retval))
299                 goto clean;
300
301         return;
302 clean:
303         pr_warn("tegra_wdt: Failed to create debugfs!\n");
304         if (root)
305                 debugfs_remove_recursive(root);
306 }
307
308 #else /* !CONFIG_DEBUG_FS */
309 static inline void tegra_wdt_debugfs_init(struct tegra_wdt* tegra_wdt) { };
310 #endif /* CONFIG_DEBUG_FS */
311
312 static int tegra_wdt_probe(struct platform_device *pdev)
313 {
314         struct resource *res_src, *res_wdt;
315         struct tegra_wdt *tegra_wdt;
316         struct device_node *np = pdev->dev.of_node;
317         u32 pval = 0;
318         int ret = 0;
319         bool enable_on_init;
320         bool extended_suspend = false;
321
322         if (!np) {
323                 dev_err(&pdev->dev, "Supprot registration from DT only");
324                 return -EPERM;
325         }
326
327         enable_on_init = of_property_read_bool(np, "nvidia,enable-on-init");
328         ret = of_property_read_u32(np, "nvidia,heartbeat-init", &pval);
329         if (!ret)
330                 heartbeat = pval;
331
332         ret = of_property_read_u32(np, "nvidia,expiry-count", &pval);
333         if (!ret)
334                 expiry_count = pval;
335
336         extended_suspend = of_property_read_bool(np,
337                                         "nvidia,extend-watchdog-suspend");
338         tegra_wdt = devm_kzalloc(&pdev->dev, sizeof(*tegra_wdt), GFP_KERNEL);
339         if (!tegra_wdt) {
340                 dev_err(&pdev->dev, "out of memory\n");
341                 return -ENOMEM;
342         }
343
344         tegra_wdt->pdev = pdev;
345         tegra_wdt->extended_suspend = extended_suspend;
346         tegra_wdt->wdt.info = &tegra_wdt_info;
347         tegra_wdt->wdt.ops = &tegra_wdt_ops;
348         tegra_wdt->wdt.min_timeout = MIN_WDT_PERIOD * expiry_count;
349         tegra_wdt->wdt.max_timeout = MAX_WDT_PERIOD * expiry_count;
350         watchdog_init_timeout(&tegra_wdt->wdt, heartbeat, &pdev->dev);
351         watchdog_set_nowayout(&tegra_wdt->wdt, nowayout);
352
353         res_src = platform_get_resource(pdev, IORESOURCE_MEM, 0);
354         res_wdt = platform_get_resource(pdev, IORESOURCE_MEM, 1);
355
356         if (!res_src || !res_wdt) {
357                 dev_err(&pdev->dev, "incorrect resources\n");
358                 return -ENOENT;
359         }
360
361         tegra_wdt->wdt_source = devm_ioremap_resource(&pdev->dev, res_src);
362         if (IS_ERR(tegra_wdt->wdt_source)) {
363                 dev_err(&pdev->dev, "Cannot request memregion/iomap res_src\n");
364                 return PTR_ERR(tegra_wdt->wdt_source);
365         }
366
367         tegra_wdt->wdt_timer = devm_ioremap_resource(&pdev->dev, res_wdt);
368         if (IS_ERR(tegra_wdt->wdt_timer)) {
369                 dev_err(&pdev->dev, "Cannot request memregion/iomap res_wdt\n");
370                 return PTR_ERR(tegra_wdt->wdt_timer);
371         }
372
373 #ifdef CONFIG_PM
374         /* Register PM notifier*/
375         tegra_wdt->wdt_pm_nb.notifier_call = tegra_pm_notify;
376         ret = register_pm_notifier(&tegra_wdt->wdt_pm_nb);
377         if (ret)
378                 return ret;
379 #endif
380
381         /* Configure timer source */
382         if ((res_wdt->start & 0xff) < 0x50)
383                 tegra_wdt->config = 1 + (res_wdt->start & 0xf) / 8;
384         else
385                 tegra_wdt->config = ((int) (3 + ((res_wdt->start & 0xff) -
386                                                         0x50) / 8)) % 10;
387         /* Enable interrupts and reset events by default */
388         tegra_wdt->config |= WDT_CFG_PERIOD | WDT_CFG_INT_EN |
389                                 WDT_CFG_FIQ_EN | WDT_CFG_PMC2CAR_RST_EN;
390
391         tegra_wdt_disable(&tegra_wdt->wdt);
392         writel(TIMER_PCR_INTR, tegra_wdt->wdt_timer + TIMER_PCR);
393
394         /* Init and enable watchdog on WDT0 during probe */
395         if (enable_on_init) {
396                 if (of_machine_is_compatible("nvidia,tegra210")) {
397                         tegra_wdt->irq = platform_get_irq(pdev, 0);
398                         if (tegra_wdt->irq <= 0) {
399                                 dev_err(&pdev->dev, "failed to get WDT IRQ\n");
400                                 return -ENXIO;
401                         }
402
403                         ret = devm_request_threaded_irq(&pdev->dev,
404                                         tegra_wdt->irq, NULL, tegra_wdt_irq,
405                                         IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
406                                         dev_name(&pdev->dev), tegra_wdt);
407                         if (ret < 0) {
408                                 dev_err(&pdev->dev,
409                                         "failed to register irq %d err %d\n",
410                                         tegra_wdt->irq, ret);
411                                 return ret;
412                         }
413                 }
414
415                 tegra_wdt_enable(&tegra_wdt->wdt);
416                 set_bit(WDOG_ACTIVE, &tegra_wdt->wdt.status);
417                 set_bit(WDT_ENABLED_ON_INIT, &tegra_wdt->status);
418                 pr_info("Tegra WDT enabled on probe. Timeout = %u seconds.\n",
419                                                 tegra_wdt->wdt.timeout);
420         }
421
422         ret = watchdog_register_device(&tegra_wdt->wdt);
423         if (ret) {
424                 dev_err(&pdev->dev, "failed to register watchdog device\n");
425                 if (enable_on_init)
426                         tegra_wdt_disable(&tegra_wdt->wdt);
427                 return ret;
428         }
429
430         platform_set_drvdata(pdev, tegra_wdt);
431
432         tegra_wdt_debugfs_init(tegra_wdt);
433
434         if (tegra_wdt->extended_suspend)
435                 register_syscore_ops(&tegra_wdt_syscore_ops);
436
437         s_tegra_wdt = tegra_wdt;
438         dev_info(&pdev->dev, "%s done\n", __func__);
439         return 0;
440 }
441
442 static int tegra_wdt_remove(struct platform_device *pdev)
443 {
444         struct tegra_wdt *tegra_wdt = platform_get_drvdata(pdev);
445
446         tegra_wdt_disable(&tegra_wdt->wdt);
447
448 #ifdef CONFIG_PM
449         unregister_pm_notifier(&tegra_wdt->wdt_pm_nb);
450 #endif
451         watchdog_unregister_device(&tegra_wdt->wdt);
452         platform_set_drvdata(pdev, NULL);
453         return 0;
454 }
455
456 #ifdef CONFIG_PM_SLEEP
457 static int tegra_wdt_suspend(struct device *dev)
458 {
459         struct tegra_wdt *tegra_wdt = dev_get_drvdata(dev);
460
461         if (!tegra_wdt->extended_suspend)
462                 __tegra_wdt_disable(tegra_wdt);
463         else
464                 __tegra_wdt_ping(tegra_wdt);
465         return 0;
466 }
467
468 static int tegra_wdt_resume(struct device *dev)
469 {
470         struct tegra_wdt *tegra_wdt = dev_get_drvdata(dev);
471
472         if (watchdog_active(&tegra_wdt->wdt)) {
473                 if (tegra_wdt->extended_suspend)
474                         __tegra_wdt_ping(tegra_wdt);
475                 else
476                         __tegra_wdt_enable(tegra_wdt);
477         } else {
478                 if (tegra_wdt->extended_suspend)
479                         __tegra_wdt_disable(tegra_wdt);
480         }
481
482         return 0;
483 }
484
485 static int tegra_wdt_syscore_suspend(void)
486 {
487         if (!s_tegra_wdt->extended_suspend)
488                 return 0;
489
490         __tegra_wdt_disable(s_tegra_wdt);
491         return 0;
492 }
493
494 static void tegra_wdt_syscore_resume(void)
495 {
496         if (!s_tegra_wdt->extended_suspend)
497                 return;
498
499         __tegra_wdt_enable(s_tegra_wdt);
500 }
501 #else
502 static int tegra_wdt_syscore_suspend(void)
503 {
504         return 0;
505 }
506 static void tegra_wdt_syscore_resume(void) { }
507 #endif
508
509 static struct syscore_ops tegra_wdt_syscore_ops = {
510         .suspend =      tegra_wdt_syscore_suspend,
511         .resume =       tegra_wdt_syscore_resume,
512 };
513
514 static const struct dev_pm_ops tegra_wdt_pm_ops = {
515         SET_SYSTEM_SLEEP_PM_OPS(tegra_wdt_suspend, tegra_wdt_resume)
516 };
517
518 static const struct of_device_id tegra_wdt_match[] = {
519         { .compatible = "nvidia,tegra-wdt", },
520         {}
521 };
522 MODULE_DEVICE_TABLE(of, tegra_wdt_match);
523
524 static struct platform_driver tegra_wdt_driver = {
525         .probe          = tegra_wdt_probe,
526         .remove         = tegra_wdt_remove,
527         .driver         = {
528                 .owner  = THIS_MODULE,
529                 .name   = "tegra_wdt",
530                 .pm     = &tegra_wdt_pm_ops,
531                 .of_match_table = of_match_ptr(tegra_wdt_match),
532         },
533 };
534
535 static int __init tegra_wdt_init(void)
536 {
537         return platform_driver_register(&tegra_wdt_driver);
538 }
539
540 static void __exit tegra_wdt_exit(void)
541 {
542         platform_driver_unregister(&tegra_wdt_driver);
543 }
544
545 subsys_initcall(tegra_wdt_init);
546 module_exit(tegra_wdt_exit);
547
548 MODULE_AUTHOR("NVIDIA Corporation");
549 MODULE_DESCRIPTION("Tegra Watchdog Driver");
550
551 module_param(heartbeat, int, 0);
552 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat period in seconds");
553
554 MODULE_LICENSE("GPL");
555 MODULE_ALIAS("platform:tegra_wdt");