diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /arch/arm/mach-tegra/wdt-recovery.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'arch/arm/mach-tegra/wdt-recovery.c')
-rw-r--r-- | arch/arm/mach-tegra/wdt-recovery.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/wdt-recovery.c b/arch/arm/mach-tegra/wdt-recovery.c new file mode 100644 index 00000000000..537b1c0db85 --- /dev/null +++ b/arch/arm/mach-tegra/wdt-recovery.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/wdt-recovery.c | ||
3 | * | ||
4 | * Copyright (c) 2011, NVIDIA Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along | ||
16 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/suspend.h> | ||
23 | #include <linux/resource.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/syscore_ops.h> | ||
27 | #include <linux/io.h> | ||
28 | |||
29 | #include <asm/mach-types.h> | ||
30 | #include <asm/mach/time.h> | ||
31 | #include <asm/localtimer.h> | ||
32 | |||
33 | #include <mach/nvmap.h> | ||
34 | #include <mach/irqs.h> | ||
35 | #include <mach/iomap.h> | ||
36 | #include <mach/clk.h> | ||
37 | #include <mach/io.h> | ||
38 | |||
39 | static int wdt_heartbeat = 30; | ||
40 | |||
41 | #if defined(CONFIG_ARCH_TEGRA_3x_SOC) | ||
42 | #define TIMER_PTV 0 | ||
43 | #define TIMER_EN (1 << 31) | ||
44 | #define TIMER_PERIODIC (1 << 30) | ||
45 | #define TIMER_PCR 0x4 | ||
46 | #define TIMER_PCR_INTR (1 << 30) | ||
47 | #define WDT_CFG (0) | ||
48 | #define WDT_CFG_TMR_SRC (7 << 0) /* for TMR7. */ | ||
49 | #define WDT_CFG_PERIOD (1 << 4) | ||
50 | #define WDT_CFG_INT_EN (1 << 12) | ||
51 | #define WDT_CFG_SYS_RST_EN (1 << 14) | ||
52 | #define WDT_CFG_PMC2CAR_RST_EN (1 << 15) | ||
53 | #define WDT_CMD (8) | ||
54 | #define WDT_CMD_START_COUNTER (1 << 0) | ||
55 | #define WDT_CMD_DISABLE_COUNTER (1 << 1) | ||
56 | #define WDT_UNLOCK (0xC) | ||
57 | #define WDT_UNLOCK_PATTERN (0xC45A << 0) | ||
58 | |||
59 | static void __iomem *wdt_timer = IO_ADDRESS(TEGRA_TMR7_BASE); | ||
60 | static void __iomem *wdt_source = IO_ADDRESS(TEGRA_WDT0_BASE); | ||
61 | |||
62 | static void tegra_wdt_reset_enable(void) | ||
63 | { | ||
64 | u32 val; | ||
65 | |||
66 | writel(TIMER_PCR_INTR, wdt_timer + TIMER_PCR); | ||
67 | val = (wdt_heartbeat * 1000000ul) / 4; | ||
68 | val |= (TIMER_EN | TIMER_PERIODIC); | ||
69 | writel(val, wdt_timer + TIMER_PTV); | ||
70 | |||
71 | val = WDT_CFG_TMR_SRC | WDT_CFG_PERIOD | /*WDT_CFG_INT_EN |*/ | ||
72 | /*WDT_CFG_SYS_RST_EN |*/ WDT_CFG_PMC2CAR_RST_EN; | ||
73 | writel(val, wdt_source + WDT_CFG); | ||
74 | writel(WDT_CMD_START_COUNTER, wdt_source + WDT_CMD); | ||
75 | pr_info("%s: WDT Recovery Enabled\n", __func__); | ||
76 | } | ||
77 | |||
78 | static int tegra_wdt_reset_disable(void) | ||
79 | { | ||
80 | writel(TIMER_PCR_INTR, wdt_timer + TIMER_PCR); | ||
81 | writel(WDT_UNLOCK_PATTERN, wdt_source + WDT_UNLOCK); | ||
82 | writel(WDT_CMD_DISABLE_COUNTER, wdt_source + WDT_CMD); | ||
83 | |||
84 | writel(0, wdt_timer + TIMER_PTV); | ||
85 | pr_info("%s: WDT Recovery Disabled\n", __func__); | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | #elif defined(CONFIG_ARCH_TEGRA_2x_SOC) | ||
90 | |||
91 | static void tegra_wdt_reset_enable(void) | ||
92 | { | ||
93 | } | ||
94 | static int tegra_wdt_reset_disable(void) | ||
95 | { | ||
96 | return 0; | ||
97 | } | ||
98 | #endif | ||
99 | |||
100 | static int tegra_pm_notify(struct notifier_block *nb, | ||
101 | unsigned long event, void *nouse) | ||
102 | { | ||
103 | switch (event) { | ||
104 | case PM_SUSPEND_PREPARE: | ||
105 | tegra_wdt_reset_enable(); | ||
106 | break; | ||
107 | case PM_POST_SUSPEND: | ||
108 | tegra_wdt_reset_disable(); | ||
109 | break; | ||
110 | } | ||
111 | |||
112 | return NOTIFY_OK; | ||
113 | } | ||
114 | |||
115 | static struct notifier_block tegra_wdt_notify = { | ||
116 | .notifier_call = tegra_pm_notify, | ||
117 | }; | ||
118 | |||
119 | static struct syscore_ops tegra_wdt_syscore_ops = { | ||
120 | .suspend = tegra_wdt_reset_disable, | ||
121 | .resume = tegra_wdt_reset_enable, | ||
122 | }; | ||
123 | |||
124 | void __init tegra_wdt_recovery_init(void) | ||
125 | { | ||
126 | #ifdef CONFIG_PM | ||
127 | /* Register PM notifier. */ | ||
128 | register_pm_notifier(&tegra_wdt_notify); | ||
129 | #endif | ||
130 | register_syscore_ops(&tegra_wdt_syscore_ops); | ||
131 | } | ||