2 * drivers/watchdog/tegra_wdt.c
4 * watchdog driver for NVIDIA tegra internal watchdog
6 * Copyright (c) 2012-2015, NVIDIA CORPORATION. All rights reserved.
8 * based on drivers/watchdog/softdog.c and drivers/watchdog/omap_wdt.c
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.
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
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.
25 #include <linux/kernel.h>
26 #include <linux/module.h>
28 #include <linux/interrupt.h>
30 #include <linux/kernel.h>
31 #include <linux/miscdevice.h>
32 #include <linux/notifier.h>
33 #include <linux/platform_device.h>
34 #include <linux/reboot.h>
35 #include <linux/slab.h>
36 #include <linux/spinlock.h>
37 #include <linux/uaccess.h>
38 #include <linux/watchdog.h>
39 #include <linux/nmi.h>
40 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
41 #include <mach/irqs.h>
44 /* minimum and maximum watchdog trigger periods, in seconds */
45 #define MIN_WDT_PERIOD 5
46 #define MAX_WDT_PERIOD 1000
47 /* Assign Timer 7 to Timer 10 for WDT0 to WDT3, respectively */
48 #define TMR_SRC_START 7
50 enum tegra_wdt_status {
51 WDT_DISABLED = 1 << 0,
53 WDT_ENABLED_AT_PROBE = 1 << 2,
57 struct miscdevice miscdev;
58 struct notifier_block notifier;
59 struct resource *res_src;
60 struct resource *res_wdt;
61 struct resource *res_int_base;
62 struct resource *res_pmc;
64 void __iomem *wdt_source;
65 void __iomem *wdt_timer;
66 void __iomem *int_base;
67 void __iomem *pmc_base;
72 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
73 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
74 struct resource *res_avp_src;
75 void __iomem *wdt_avp_source;
78 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
79 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
80 struct resource *res_avp_src;
81 void __iomem *wdt_avp_source;
86 * For spinlock lockup detection to work, the heartbeat should be 2*lockup
87 * for cases where the spinlock disabled irqs.
89 static int heartbeat = 80; /* must be greater than MIN_WDT_PERIOD and lower than MAX_WDT_PERIOD */
91 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
94 #define TIMER_EN (1 << 31)
95 #define TIMER_PERIODIC (1 << 30)
97 #define TIMER_PCR_INTR (1 << 30)
98 #define WDT_EN (1 << 5)
99 #define WDT_SEL_TMR1 (0 << 4)
100 #define WDT_SYS_RST (1 << 2)
102 static void tegra_wdt_enable(struct tegra_wdt *wdt)
106 /* since the watchdog reset occurs when a second interrupt
107 * is asserted before the first is processed, program the
108 * timer period to one-half of the watchdog period */
109 val = wdt->timeout * 1000000ul / 2;
110 val |= (TIMER_EN | TIMER_PERIODIC);
111 writel(val, wdt->wdt_timer + TIMER_PTV);
113 val = WDT_EN | WDT_SEL_TMR1 | WDT_SYS_RST;
114 writel(val, wdt->wdt_source);
117 static void tegra_wdt_disable(struct tegra_wdt *wdt)
119 writel(0, wdt->wdt_source);
120 writel(0, wdt->wdt_timer + TIMER_PTV);
123 static inline void tegra_wdt_ping(struct tegra_wdt *wdt)
128 static irqreturn_t tegra_wdt_interrupt(int irq, void *dev_id)
130 struct tegra_wdt *wdt = dev_id;
132 writel(TIMER_PCR_INTR, wdt->wdt_timer + TIMER_PCR);
135 #elif defined(CONFIG_ARCH_TEGRA_3x_SOC) || defined(CONFIG_ARCH_TEGRA_12x_SOC)
138 #define TIMER_EN (1 << 31)
139 #define TIMER_PERIODIC (1 << 30)
140 #define TIMER_PCR 0x4
141 #define TIMER_PCR_INTR (1 << 30)
143 #define WDT_CFG_PERIOD (1 << 4)
144 #define WDT_CFG_INT_EN (1 << 12)
145 #define WDT_CFG_FIQ_INT_EN (1 << 13)
146 #define WDT_CFG_SYS_RST_EN (1 << 14)
147 #define WDT_CFG_PMC2CAR_RST_EN (1 << 15)
148 #define WDT_STATUS (4)
149 #define WDT_INTR_STAT (1 << 1)
151 #define WDT_CMD_START_COUNTER (1 << 0)
152 #define WDT_CMD_DISABLE_COUNTER (1 << 1)
153 #define WDT_UNLOCK (0xC)
154 #define WDT_UNLOCK_PATTERN (0xC45A << 0)
155 #define ICTLR_IEP_CLASS 0x2C
156 #define MAX_NR_CPU_WDT 0x4
157 #define PMC_RST_STATUS 0x1b4
159 struct tegra_wdt *tegra_wdt[MAX_NR_CPU_WDT];
161 * In order to generate the stack dump for the CPU which has IRQ off, we must
162 * use the FIQ. TEGRA WDT can generate the FIQ if we do not ACK the IRQ.
164 bool wdt_nmi_ack_off;
166 static inline void tegra_wdt_ping(struct tegra_wdt *wdt)
168 writel(WDT_CMD_START_COUNTER, wdt->wdt_source + WDT_CMD);
169 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
170 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
171 /* Comment out to test FIQ debugger */
172 if (!watchdog_get_lockup_state())
173 writel(WDT_CMD_START_COUNTER, wdt->wdt_avp_source + WDT_CMD);
176 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
177 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
178 if (wdt_nmi_ack_off == false)
179 writel(WDT_CMD_START_COUNTER, wdt->wdt_avp_source + WDT_CMD);
184 #if !defined(CONFIG_ARCH_TEGRA_12x_SOC) || !defined(CONFIG_FIQ_DEBUGGER)
185 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
186 static void tegra_wdt_int_priority(struct tegra_wdt *wdt)
192 val = readl(wdt->int_base + ICTLR_IEP_CLASS);
193 val &= ~(1 << (INT_WDT_CPU & 31));
194 writel(val, wdt->int_base + ICTLR_IEP_CLASS);
199 #if defined(CONFIG_TRUSTED_FOUNDATIONS) || \
200 !defined(CONFIG_ARCH_TEGRA_12x_SOC) || !defined(CONFIG_FIQ_DEBUGGER)
201 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
202 static void tegra_wdt_int_priority(struct tegra_wdt *wdt)
208 val = readl(wdt->int_base + ICTLR_IEP_CLASS);
209 val &= ~(1 << (INT_WDT_CPU & 31));
210 writel(val, wdt->int_base + ICTLR_IEP_CLASS);
215 static void tegra_wdt_enable(struct tegra_wdt *wdt)
219 writel(TIMER_PCR_INTR, wdt->wdt_timer + TIMER_PCR);
220 val = (wdt->timeout * 1000000ul) / 4;
221 val |= (TIMER_EN | TIMER_PERIODIC);
222 writel(val, wdt->wdt_timer + TIMER_PTV);
224 /* Interrupt handler is not required for user space
225 * WDT accesses, since the caller is responsible to ping the
226 * WDT to reset the counter before expiration, through ioctls.
227 * SYS_RST_EN doesnt work as there is no external reset
230 val = wdt->tmrsrc | WDT_CFG_PERIOD | /*WDT_CFG_INT_EN |*/
231 /*WDT_CFG_SYS_RST_EN |*/ WDT_CFG_PMC2CAR_RST_EN;
233 #if !defined(CONFIG_ARCH_TEGRA_12x_SOC) || !defined(CONFIG_FIQ_DEBUGGER)
234 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
235 val |= WDT_CFG_FIQ_INT_EN;
239 #if defined(CONFIG_TRUSTED_FOUNDATIONS) || \
240 !defined(CONFIG_ARCH_TEGRA_12x_SOC) || !defined(CONFIG_FIQ_DEBUGGER)
241 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
242 val |= WDT_CFG_FIQ_INT_EN;
246 writel(val, wdt->wdt_source + WDT_CFG);
247 writel(WDT_CMD_START_COUNTER, wdt->wdt_source + WDT_CMD);
249 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
250 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
251 val = wdt->tmrsrc | (WDT_CFG_PERIOD << 1) | /*WDT_CFG_INT_EN |*/
252 /*WDT_CFG_SYS_RST_EN |*/ WDT_CFG_PMC2CAR_RST_EN;
253 writel(val, wdt->wdt_avp_source + WDT_CFG);
254 writel(WDT_CMD_START_COUNTER, wdt->wdt_avp_source + WDT_CMD);
258 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
259 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
260 val = wdt->tmrsrc | (WDT_CFG_PERIOD << 1) | /*WDT_CFG_INT_EN |*/
261 /*WDT_CFG_SYS_RST_EN |*/ WDT_CFG_PMC2CAR_RST_EN;
262 writel(val, wdt->wdt_avp_source + WDT_CFG);
263 writel(WDT_CMD_START_COUNTER, wdt->wdt_avp_source + WDT_CMD);
268 static void tegra_wdt_disable(struct tegra_wdt *wdt)
270 writel(WDT_UNLOCK_PATTERN, wdt->wdt_source + WDT_UNLOCK);
271 writel(WDT_CMD_DISABLE_COUNTER, wdt->wdt_source + WDT_CMD);
273 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
274 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
275 writel(WDT_UNLOCK_PATTERN, wdt->wdt_avp_source + WDT_UNLOCK);
276 writel(WDT_CMD_DISABLE_COUNTER, wdt->wdt_avp_source + WDT_CMD);
279 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
280 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
281 writel(WDT_UNLOCK_PATTERN, wdt->wdt_avp_source + WDT_UNLOCK);
282 writel(WDT_CMD_DISABLE_COUNTER, wdt->wdt_avp_source + WDT_CMD);
284 writel(0, wdt->wdt_timer + TIMER_PTV);
287 static irqreturn_t tegra_wdt_interrupt(int irq, void *dev_id)
291 for (i = 0; i < MAX_NR_CPU_WDT; i++) {
292 if (tegra_wdt[i] == NULL)
294 status = readl(tegra_wdt[i]->wdt_source + WDT_STATUS);
295 if ((tegra_wdt[i]->status & WDT_ENABLED) &&
296 (status & WDT_INTR_STAT))
297 tegra_wdt_ping(tegra_wdt[i]);
303 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
304 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
305 static irqreturn_t tegra_wdt_avp_interrupt(int irq, void *dev_id)
311 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
312 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
313 static irqreturn_t tegra_wdt_avp_interrupt(int irq, void *dev_id)
322 static int tegra_wdt_notify(struct notifier_block *this,
323 unsigned long code, void *dev)
325 struct tegra_wdt *wdt = container_of(this, struct tegra_wdt, notifier);
327 if (code == SYS_DOWN || code == SYS_HALT)
328 tegra_wdt_disable(wdt);
332 static int tegra_wdt_open(struct inode *inode, struct file *file)
334 struct miscdevice *mdev = file->private_data;
335 struct tegra_wdt *wdt = container_of(mdev, struct tegra_wdt,
338 if (test_and_set_bit(1, &wdt->users))
341 wdt->status |= WDT_ENABLED;
342 wdt->timeout = heartbeat;
343 tegra_wdt_enable(wdt);
344 file->private_data = wdt;
345 return nonseekable_open(inode, file);
348 static int tegra_wdt_release(struct inode *inode, struct file *file)
350 struct tegra_wdt *wdt = file->private_data;
352 if (wdt->status & WDT_ENABLED) {
353 #ifndef CONFIG_WATCHDOG_NOWAYOUT
354 tegra_wdt_disable(wdt);
355 wdt->status = WDT_DISABLED;
362 static long tegra_wdt_ioctl(struct file *file, unsigned int cmd,
365 struct tegra_wdt *wdt = file->private_data;
366 static DEFINE_SPINLOCK(lock);
368 #ifndef CONFIG_WATCHDOG_NOWAYOUT
371 static const struct watchdog_info ident = {
372 .identity = "Tegra Watchdog",
373 .options = WDIOF_SETTIMEOUT,
374 .firmware_version = 0,
378 case WDIOC_GETSUPPORT:
379 return copy_to_user((struct watchdog_info __user *)arg, &ident,
381 case WDIOC_GETSTATUS:
382 case WDIOC_GETBOOTSTATUS:
383 return put_user(0, (int __user *)arg);
385 case WDIOC_KEEPALIVE:
391 case WDIOC_SETTIMEOUT:
392 if (get_user(new_timeout, (int __user *)arg))
395 tegra_wdt_disable(wdt);
396 wdt->timeout = clamp(new_timeout, MIN_WDT_PERIOD, MAX_WDT_PERIOD);
397 tegra_wdt_enable(wdt);
399 case WDIOC_GETTIMEOUT:
400 return put_user(wdt->timeout, (int __user *)arg);
402 case WDIOC_SETOPTIONS:
403 #ifndef CONFIG_WATCHDOG_NOWAYOUT
404 if (get_user(option, (int __user *)arg))
407 if (option & WDIOS_DISABLECARD) {
408 wdt->status &= ~WDT_ENABLED;
409 wdt->status |= WDT_DISABLED;
410 tegra_wdt_disable(wdt);
411 } else if (option & WDIOS_ENABLECARD) {
412 tegra_wdt_enable(wdt);
413 wdt->status |= WDT_ENABLED;
414 wdt->status &= ~WDT_DISABLED;
428 static ssize_t tegra_wdt_write(struct file *file, const char __user *data,
429 size_t len, loff_t *ppos)
434 static void tegra_wdt_log_reset_reason(struct platform_device *pdev,
435 struct tegra_wdt *wdt)
438 #if defined(CONFIG_ARCH_TEGRA_3x_SOC) || defined(CONFIG_ARCH_TEGRA_12x_SOC)
440 * There are two pathes to make the WDT reset:
441 * (a) WDT -> PMC -> CAR
449 * Path (a) is enabled by WDT_CFG_PMC2CAR_RST_EN bit in the WDT
450 * configuration register, as it will reset the CAR module, and we
451 * cannot read back the reset reason from the CAR module. However, we
452 * can read back the reaset reason from the PMC module.
454 * Path (b) is enabled by the WDT_CFG_SYS_RST_EN bit, and we can
455 * read back the reset reason from the CAR moudle. However, this reset
456 * path will not reset the peripherals which might be the hard hang
457 * source. We will not use this path.
460 #define RESET_STR(REASON) "last reset is due to "#REASON"\n"
461 char *reset_reason[] = {
462 RESET_STR(power on reset),
463 RESET_STR(watchdog timeout),
465 RESET_STR(software reset),
466 RESET_STR(deep sleep reset),
469 /* report reset reason only once */
473 val = readl(wdt->pmc_base + PMC_RST_STATUS) & 0x7;
474 if (val >= ARRAY_SIZE(reset_reason))
475 dev_info(&pdev->dev, "last reset value is invalid 0x%x\n", val);
477 dev_info(&pdev->dev, reset_reason[val]);
482 val = readl(wdt->wdt_source);
484 dev_info(&pdev->dev, "last reset due to watchdog timeout\n");
488 static const struct file_operations tegra_wdt_fops = {
489 .owner = THIS_MODULE,
491 .write = tegra_wdt_write,
492 .unlocked_ioctl = tegra_wdt_ioctl,
493 .open = tegra_wdt_open,
494 .release = tegra_wdt_release,
497 static int tegra_wdt_probe(struct platform_device *pdev)
499 struct resource *res_src, *res_wdt, *res_irq, *res_pmc;
500 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
501 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
502 struct resource *res_avp_src, *res_avp_irq;
505 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
506 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
507 struct resource *res_avp_src, *res_avp_irq;
510 struct resource *res_int_base = NULL;
511 struct tegra_wdt *wdt;
514 if ((pdev->id < -1) || (pdev->id > 0)) {
515 dev_err(&pdev->dev, "Only support IDs -1 and 0\n");
519 res_src = platform_get_resource(pdev, IORESOURCE_MEM, 0);
520 res_wdt = platform_get_resource(pdev, IORESOURCE_MEM, 1);
521 res_pmc = platform_get_resource(pdev, IORESOURCE_MEM, 2);
522 res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
524 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
525 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
526 res_avp_src = platform_get_resource(pdev, IORESOURCE_MEM, 4);
527 res_avp_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
530 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
531 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
532 res_avp_src = platform_get_resource(pdev, IORESOURCE_MEM, 4);
533 res_avp_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
537 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
538 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
539 if (!res_src || !res_wdt || !res_avp_src || (!pdev->id && !res_irq) ||
543 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
544 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
545 if (!res_src || !res_wdt || !res_avp_src || (!pdev->id && !res_irq)) {
547 if (!res_src || !res_wdt || (!pdev->id && !res_irq) || !res_pmc) {
551 dev_err(&pdev->dev, "incorrect resources\n");
555 #if !defined(CONFIG_ARCH_TEGRA_12x_SOC) || !defined(CONFIG_FIQ_DEBUGGER)
556 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
557 res_int_base = platform_get_resource(pdev, IORESOURCE_MEM, 3);
558 if (!pdev->id && !res_int_base) {
559 dev_err(&pdev->dev, "FIQ_DBG: INT base not defined\n");
565 #if defined(CONFIG_TRUSTED_FOUNDATIONS) || \
566 !defined(CONFIG_ARCH_TEGRA_12x_SOC) || !defined(CONFIG_FIQ_DEBUGGER)
567 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
568 res_int_base = platform_get_resource(pdev, IORESOURCE_MEM, 3);
569 if (!pdev->id && !res_int_base) {
570 dev_err(&pdev->dev, "FIQ_DBG: INT base not defined\n");
577 if (pdev->id == -1 && !res_irq) {
578 dev_err(&pdev->dev, "incorrect irq\n");
582 wdt = kzalloc(sizeof(*wdt), GFP_KERNEL);
584 dev_err(&pdev->dev, "out of memory\n");
589 wdt->miscdev.parent = &pdev->dev;
590 if (pdev->id == -1) {
591 wdt->miscdev.minor = WATCHDOG_MINOR;
592 wdt->miscdev.name = "watchdog";
594 wdt->miscdev.minor = MISC_DYNAMIC_MINOR;
596 wdt->miscdev.name = "watchdog0";
597 else if (pdev->id == 1)
598 wdt->miscdev.name = "watchdog1";
599 else if (pdev->id == 2)
600 wdt->miscdev.name = "watchdog2";
601 else if (pdev->id == 3)
602 wdt->miscdev.name = "watchdog3";
604 wdt->miscdev.fops = &tegra_wdt_fops;
606 wdt->notifier.notifier_call = tegra_wdt_notify;
608 res_src = request_mem_region(res_src->start, resource_size(res_src),
610 res_wdt = request_mem_region(res_wdt->start, resource_size(res_wdt),
612 res_pmc = request_mem_region(res_pmc->start, resource_size(res_pmc),
615 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
616 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
617 res_avp_src = request_mem_region(res_avp_src->start,
618 resource_size(res_avp_src),
622 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
623 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
624 res_avp_src = request_mem_region(res_avp_src->start,
625 resource_size(res_avp_src),
629 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
630 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
631 if (!res_src || !res_wdt || !res_avp_src || !res_pmc) {
634 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
635 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
636 if (!res_src || !res_wdt || !res_avp_src || !res_pmc) {
638 if (!res_src || !res_wdt || !res_pmc) {
642 dev_err(&pdev->dev, "unable to request memory resources\n");
647 wdt->wdt_source = ioremap(res_src->start, resource_size(res_src));
648 wdt->wdt_timer = ioremap(res_wdt->start, resource_size(res_wdt));
649 wdt->pmc_base = ioremap(res_pmc->start, resource_size(res_pmc));
651 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
652 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
653 wdt->wdt_avp_source = ioremap(res_avp_src->start,
654 resource_size(res_avp_src));
657 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
658 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
659 wdt->wdt_avp_source = ioremap(res_avp_src->start,
660 resource_size(res_avp_src));
663 /* tmrsrc will be used to set WDT_CFG */
664 wdt->tmrsrc = (TMR_SRC_START + pdev->id) % 10;
666 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
667 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
668 if (!wdt->wdt_source || !wdt->wdt_timer || !wdt->wdt_avp_source ||
671 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
672 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
673 if (!wdt->wdt_source || !wdt->wdt_timer || !wdt->wdt_avp_source ||
676 if (!wdt->wdt_source || !wdt->wdt_timer || !wdt->pmc_base) {
680 dev_err(&pdev->dev, "unable to map registers\n");
685 tegra_wdt_log_reset_reason(pdev, wdt);
687 tegra_wdt_disable(wdt);
688 writel(TIMER_PCR_INTR, wdt->wdt_timer + TIMER_PCR);
690 if (res_irq != NULL) {
691 #if !defined(CONFIG_ARCH_TEGRA_12x_SOC) || !defined(CONFIG_FIQ_DEBUGGER)
692 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
693 /* FIQ debugger enables FIQ priority for INT_WDT_CPU.
694 * But that will disable IRQ on WDT expiration.
695 * Reset the priority back to IRQ on INT_WDT_CPU so
696 * that tegra_wdt_interrupt gets its chance to restart the
697 * counter before expiration.
699 res_int_base = request_mem_region(res_int_base->start,
700 resource_size(res_int_base),
704 wdt->int_base = ioremap(res_int_base->start,
705 resource_size(res_int_base));
708 tegra_wdt_int_priority(wdt);
712 #if defined(CONFIG_TRUSTED_FOUNDATIONS) || \
713 !defined(CONFIG_ARCH_TEGRA_12x_SOC) || !defined(CONFIG_FIQ_DEBUGGER)
714 #ifdef CONFIG_TEGRA_FIQ_DEBUGGER
715 /* FIQ debugger enables FIQ priority for INT_WDT_CPU.
716 * But that will disable IRQ on WDT expiration.
717 * Reset the priority back to IRQ on INT_WDT_CPU so
718 * that tegra_wdt_interrupt gets its chance to restart the
719 * counter before expiration.
721 res_int_base = request_mem_region(res_int_base->start,
722 resource_size(res_int_base),
726 wdt->int_base = ioremap(res_int_base->start,
727 resource_size(res_int_base));
730 tegra_wdt_int_priority(wdt);
733 ret = request_irq(res_irq->start, tegra_wdt_interrupt,
734 IRQF_DISABLED, dev_name(&pdev->dev), wdt);
736 dev_err(&pdev->dev, "unable to configure IRQ\n");
740 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
741 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
742 ret = request_irq(res_avp_irq->start, tegra_wdt_avp_interrupt,
743 IRQF_DISABLED, "avp_wdt", wdt);
745 dev_err(&pdev->dev, "unable to configure WDT AVP IRQ\n");
750 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
751 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
752 ret = request_irq(res_avp_irq->start, tegra_wdt_avp_interrupt,
753 IRQF_DISABLED, "avp_wdt", wdt);
755 dev_err(&pdev->dev, "unable to configure WDT AVP IRQ\n");
759 wdt->irq = res_irq->start;
762 wdt->res_src = res_src;
764 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
765 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
766 wdt->res_avp_src = res_avp_src;
768 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
769 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
770 wdt->res_avp_src = res_avp_src;
773 wdt->res_wdt = res_wdt;
774 wdt->res_int_base = res_int_base;
775 wdt->res_pmc = res_pmc;
776 wdt->status = WDT_DISABLED;
778 ret = register_reboot_notifier(&wdt->notifier);
780 dev_err(&pdev->dev, "cannot register reboot notifier\n");
784 ret = misc_register(&wdt->miscdev);
786 dev_err(&pdev->dev, "failed to register misc device\n");
787 unregister_reboot_notifier(&wdt->notifier);
791 platform_set_drvdata(pdev, wdt);
793 #ifndef CONFIG_ARCH_TEGRA_2x_SOC
794 #ifdef CONFIG_TEGRA_WATCHDOG_ENABLE_ON_PROBE
795 /* Init and enable watchdog on WDT0 with timer 8 during probe */
798 wdt->status = WDT_ENABLED | WDT_ENABLED_AT_PROBE;
799 wdt->timeout = heartbeat;
800 tegra_wdt_enable(wdt);
801 val = readl(wdt->wdt_source + WDT_CFG);
802 val |= WDT_CFG_INT_EN;
803 writel(val, wdt->wdt_source + WDT_CFG);
805 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
806 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
807 val = readl(wdt->wdt_avp_source + WDT_CFG);
808 val |= WDT_CFG_INT_EN;
809 writel(val, wdt->wdt_avp_source + WDT_CFG);
813 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
814 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
815 val = readl(wdt->wdt_avp_source + WDT_CFG);
816 val |= WDT_CFG_INT_EN;
817 writel(val, wdt->wdt_avp_source + WDT_CFG);
821 pr_info("WDT heartbeat enabled on probe\n");
824 tegra_wdt[pdev->id] = wdt;
826 pr_info("%s done\n", __func__);
830 free_irq(wdt->irq, wdt);
832 iounmap(wdt->wdt_source);
834 iounmap(wdt->wdt_timer);
836 iounmap(wdt->int_base);
838 iounmap(wdt->pmc_base);
840 release_mem_region(res_src->start, resource_size(res_src));
842 release_mem_region(res_wdt->start, resource_size(res_wdt));
844 release_mem_region(res_int_base->start,
845 resource_size(res_int_base));
847 release_mem_region(res_pmc->start, resource_size(res_pmc));
849 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
850 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
851 if (wdt->wdt_avp_source)
852 iounmap(wdt->wdt_avp_source);
854 release_mem_region(res_avp_src->start,
855 resource_size(res_avp_src));
858 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
859 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
860 if (wdt->wdt_avp_source)
861 iounmap(wdt->wdt_avp_source);
863 release_mem_region(res_avp_src->start,
864 resource_size(res_avp_src));
870 static int tegra_wdt_remove(struct platform_device *pdev)
872 struct tegra_wdt *wdt = platform_get_drvdata(pdev);
874 tegra_wdt_disable(wdt);
876 unregister_reboot_notifier(&wdt->notifier);
877 misc_deregister(&wdt->miscdev);
879 free_irq(wdt->irq, wdt);
880 iounmap(wdt->wdt_source);
882 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
883 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
884 iounmap(wdt->wdt_avp_source);
887 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
888 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
889 iounmap(wdt->wdt_avp_source);
891 iounmap(wdt->wdt_timer);
893 iounmap(wdt->int_base);
895 iounmap(wdt->pmc_base);
896 release_mem_region(wdt->res_src->start, resource_size(wdt->res_src));
898 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
899 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
900 release_mem_region(wdt->res_avp_src->start,
901 resource_size(wdt->res_avp_src));
904 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
905 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
906 release_mem_region(wdt->res_avp_src->start,
907 resource_size(wdt->res_avp_src));
910 release_mem_region(wdt->res_wdt->start, resource_size(wdt->res_wdt));
911 if (wdt->res_int_base)
912 release_mem_region(wdt->res_int_base->start,
913 resource_size(wdt->res_int_base));
915 release_mem_region(wdt->res_pmc->start,
916 resource_size(wdt->res_pmc));
918 platform_set_drvdata(pdev, NULL);
923 static int tegra_wdt_suspend(struct platform_device *pdev, pm_message_t state)
925 struct tegra_wdt *wdt = platform_get_drvdata(pdev);
927 tegra_wdt_disable(wdt);
931 static int tegra_wdt_resume(struct platform_device *pdev)
933 struct tegra_wdt *wdt = platform_get_drvdata(pdev);
935 if (wdt->status & WDT_ENABLED)
936 tegra_wdt_enable(wdt);
938 #ifndef CONFIG_ARCH_TEGRA_2x_SOC
939 /* Enable interrupt for WDT3 heartbeat watchdog */
940 if (wdt->status & WDT_ENABLED_AT_PROBE) {
942 val = readl(wdt->wdt_source + WDT_CFG);
943 val |= WDT_CFG_INT_EN;
944 writel(val, wdt->wdt_source + WDT_CFG);
946 #if defined(CONFIG_TRUSTED_LITTLE_KERNEL) && \
947 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
948 val = readl(wdt->wdt_avp_source + WDT_CFG);
949 val |= WDT_CFG_INT_EN;
950 writel(val, wdt->wdt_avp_source + WDT_CFG);
953 #if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
954 defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
955 val = readl(wdt->wdt_avp_source + WDT_CFG);
956 val |= WDT_CFG_INT_EN;
957 writel(val, wdt->wdt_avp_source + WDT_CFG);
960 pr_info("WDT heartbeat enabled on probe\n");
967 static struct platform_driver tegra_wdt_driver = {
968 .probe = tegra_wdt_probe,
969 .remove = tegra_wdt_remove,
971 .suspend = tegra_wdt_suspend,
972 .resume = tegra_wdt_resume,
975 .owner = THIS_MODULE,
980 static int __init tegra_wdt_init(void)
982 return platform_driver_register(&tegra_wdt_driver);
985 static void __exit tegra_wdt_exit(void)
987 platform_driver_unregister(&tegra_wdt_driver);
990 module_init(tegra_wdt_init);
991 module_exit(tegra_wdt_exit);
993 MODULE_AUTHOR("NVIDIA Corporation");
994 MODULE_DESCRIPTION("Tegra Watchdog Driver");
996 module_param(heartbeat, int, 0);
997 MODULE_PARM_DESC(heartbeat,
998 "Watchdog heartbeat period in seconds");
1000 MODULE_LICENSE("GPL");
1001 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
1002 MODULE_ALIAS("platform:tegra_wdt");