arm: tegra: sd: enable sd dpd
[linux-2.6.git] / arch / arm / mach-tegra / wdt-recovery.c
1 /*
2  * arch/arm/mach-tegra/wdt-recovery.c
3  *
4  * Copyright (c) 2012, 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 <linux/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                (0 << 0) /* for TMR10. */
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_TMR10_BASE);
60 static void __iomem *wdt_source = IO_ADDRESS(TEGRA_WDT3_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 }