diff options
Diffstat (limited to 'arch/arm/mach-tegra/pm.h')
-rw-r--r-- | arch/arm/mach-tegra/pm.h | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h new file mode 100644 index 00000000000..421b21ac934 --- /dev/null +++ b/arch/arm/mach-tegra/pm.h | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/include/mach/pm.h | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * Copyright (C) 2010-2012 NVIDIA Corporation | ||
6 | * | ||
7 | * Author: | ||
8 | * Colin Cross <ccross@google.com> | ||
9 | * | ||
10 | * This software is licensed under the terms of the GNU General Public | ||
11 | * License version 2, as published by the Free Software Foundation, and | ||
12 | * may be copied, distributed, and modified under those terms. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | |||
22 | #ifndef _MACH_TEGRA_PM_H_ | ||
23 | #define _MACH_TEGRA_PM_H_ | ||
24 | |||
25 | #include <linux/mutex.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/clkdev.h> | ||
29 | |||
30 | #include <mach/iomap.h> | ||
31 | |||
32 | #define PMC_SCRATCH0 0x50 | ||
33 | #define PMC_SCRATCH1 0x54 | ||
34 | #define PMC_SCRATCH4 0x60 | ||
35 | |||
36 | enum tegra_suspend_mode { | ||
37 | TEGRA_SUSPEND_NONE = 0, | ||
38 | TEGRA_SUSPEND_LP2, /* CPU voltage off */ | ||
39 | TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */ | ||
40 | TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */ | ||
41 | TEGRA_MAX_SUSPEND_MODE, | ||
42 | }; | ||
43 | |||
44 | enum suspend_stage { | ||
45 | TEGRA_SUSPEND_BEFORE_PERIPHERAL, | ||
46 | TEGRA_SUSPEND_BEFORE_CPU, | ||
47 | }; | ||
48 | |||
49 | enum resume_stage { | ||
50 | TEGRA_RESUME_AFTER_PERIPHERAL, | ||
51 | TEGRA_RESUME_AFTER_CPU, | ||
52 | }; | ||
53 | |||
54 | struct tegra_suspend_platform_data { | ||
55 | unsigned long cpu_timer; /* CPU power good time in us, LP2/LP1 */ | ||
56 | unsigned long cpu_off_timer; /* CPU power off time us, LP2/LP1 */ | ||
57 | unsigned long core_timer; /* core power good time in ticks, LP0 */ | ||
58 | unsigned long core_off_timer; /* core power off time ticks, LP0 */ | ||
59 | bool corereq_high; /* Core power request active-high */ | ||
60 | bool sysclkreq_high; /* System clock request is active-high */ | ||
61 | bool combined_req; /* if core & CPU power requests are combined */ | ||
62 | enum tegra_suspend_mode suspend_mode; | ||
63 | unsigned long cpu_lp2_min_residency; /* Min LP2 state residency in us */ | ||
64 | void (*board_suspend)(int lp_state, enum suspend_stage stg); | ||
65 | /* lp_state = 0 for LP0 state, 1 for LP1 state, 2 for LP2 state */ | ||
66 | void (*board_resume)(int lp_state, enum resume_stage stg); | ||
67 | unsigned int cpu_resume_boost; /* CPU frequency resume boost in kHz */ | ||
68 | }; | ||
69 | |||
70 | /* Tegra io dpd entry - for each supported driver */ | ||
71 | struct tegra_io_dpd { | ||
72 | const char *name; /* driver name */ | ||
73 | u8 io_dpd_reg_index; /* io dpd register index */ | ||
74 | u8 io_dpd_bit; /* bit position for driver in dpd register */ | ||
75 | }; | ||
76 | |||
77 | unsigned long tegra_cpu_power_good_time(void); | ||
78 | unsigned long tegra_cpu_power_off_time(void); | ||
79 | unsigned long tegra_cpu_lp2_min_residency(void); | ||
80 | void tegra_clear_cpu_in_lp2(int cpu); | ||
81 | bool tegra_set_cpu_in_lp2(int cpu); | ||
82 | |||
83 | int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags); | ||
84 | |||
85 | #define FLOW_CTRL_CLUSTER_CONTROL \ | ||
86 | (IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x2c) | ||
87 | #define FLOW_CTRL_CPU_CSR_IMMEDIATE_WAKE (1<<3) | ||
88 | #define FLOW_CTRL_CPU_CSR_SWITCH_CLUSTER (1<<2) | ||
89 | |||
90 | #define FUSE_SKU_DIRECT_CONFIG \ | ||
91 | (IO_ADDRESS(TEGRA_FUSE_BASE) + 0x1F4) | ||
92 | #define FUSE_SKU_DISABLE_ALL_CPUS (1<<5) | ||
93 | #define FUSE_SKU_NUM_DISABLED_CPUS(x) (((x) >> 3) & 3) | ||
94 | |||
95 | void __init tegra_init_suspend(struct tegra_suspend_platform_data *plat); | ||
96 | |||
97 | u64 tegra_rtc_read_ms(void); | ||
98 | |||
99 | /* | ||
100 | * Callbacks for platform drivers to implement. | ||
101 | */ | ||
102 | extern void (*tegra_deep_sleep)(int); | ||
103 | |||
104 | unsigned int tegra_idle_lp2_last(unsigned int us, unsigned int flags); | ||
105 | |||
106 | #if defined(CONFIG_PM_SLEEP) && !defined(CONFIG_ARCH_TEGRA_2x_SOC) | ||
107 | void tegra_lp0_suspend_mc(void); | ||
108 | void tegra_lp0_resume_mc(void); | ||
109 | void tegra_lp0_cpu_mode(bool enter); | ||
110 | #else | ||
111 | static inline void tegra_lp0_suspend_mc(void) {} | ||
112 | static inline void tegra_lp0_resume_mc(void) {} | ||
113 | static inline void tegra_lp0_cpu_mode(bool enter) {} | ||
114 | #endif | ||
115 | |||
116 | #ifdef CONFIG_TEGRA_CLUSTER_CONTROL | ||
117 | #define INSTRUMENT_CLUSTER_SWITCH 0 /* Should be zero for shipping code */ | ||
118 | #define DEBUG_CLUSTER_SWITCH 0 /* Should be zero for shipping code */ | ||
119 | #define PARAMETERIZE_CLUSTER_SWITCH 1 /* Should be zero for shipping code */ | ||
120 | |||
121 | static inline bool is_g_cluster_present(void) | ||
122 | { | ||
123 | u32 fuse_sku = readl(FUSE_SKU_DIRECT_CONFIG); | ||
124 | if (fuse_sku & FUSE_SKU_DISABLE_ALL_CPUS) | ||
125 | return false; | ||
126 | return true; | ||
127 | } | ||
128 | static inline unsigned int is_lp_cluster(void) | ||
129 | { | ||
130 | unsigned int reg; | ||
131 | reg = readl(FLOW_CTRL_CLUSTER_CONTROL); | ||
132 | return (reg & 1); /* 0 == G, 1 == LP*/ | ||
133 | } | ||
134 | int tegra_cluster_control(unsigned int us, unsigned int flags); | ||
135 | void tegra_cluster_switch_prolog(unsigned int flags); | ||
136 | void tegra_cluster_switch_epilog(unsigned int flags); | ||
137 | #else | ||
138 | #define INSTRUMENT_CLUSTER_SWITCH 0 /* Must be zero for ARCH_TEGRA_2x_SOC */ | ||
139 | #define DEBUG_CLUSTER_SWITCH 0 /* Must be zero for ARCH_TEGRA_2x_SOC */ | ||
140 | #define PARAMETERIZE_CLUSTER_SWITCH 0 /* Must be zero for ARCH_TEGRA_2x_SOC */ | ||
141 | |||
142 | static inline bool is_g_cluster_present(void) { return true; } | ||
143 | static inline unsigned int is_lp_cluster(void) { return 0; } | ||
144 | static inline int tegra_cluster_control(unsigned int us, unsigned int flags) | ||
145 | { | ||
146 | return -EPERM; | ||
147 | } | ||
148 | static inline void tegra_cluster_switch_prolog(unsigned int flags) {} | ||
149 | static inline void tegra_cluster_switch_epilog(unsigned int flags) {} | ||
150 | #endif | ||
151 | |||
152 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | ||
153 | void tegra2_lp0_suspend_init(void); | ||
154 | void tegra2_lp2_set_trigger(unsigned long cycles); | ||
155 | unsigned long tegra2_lp2_timer_remain(void); | ||
156 | #endif | ||
157 | #ifdef CONFIG_ARCH_TEGRA_3x_SOC | ||
158 | void tegra3_lp2_set_trigger(unsigned long cycles); | ||
159 | unsigned long tegra3_lp2_timer_remain(void); | ||
160 | int tegra3_is_lp2_timer_ready(unsigned int cpu); | ||
161 | void tegra3_lp2_timer_cancel_secondary(void); | ||
162 | #endif | ||
163 | |||
164 | static inline void tegra_lp0_suspend_init(void) | ||
165 | { | ||
166 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | ||
167 | tegra2_lp0_suspend_init(); | ||
168 | #endif | ||
169 | } | ||
170 | |||
171 | static inline void tegra_lp2_set_trigger(unsigned long cycles) | ||
172 | { | ||
173 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | ||
174 | tegra2_lp2_set_trigger(cycles); | ||
175 | #endif | ||
176 | #ifdef CONFIG_ARCH_TEGRA_3x_SOC | ||
177 | tegra3_lp2_set_trigger(cycles); | ||
178 | #endif | ||
179 | } | ||
180 | |||
181 | static inline unsigned long tegra_lp2_timer_remain(void) | ||
182 | { | ||
183 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | ||
184 | return tegra2_lp2_timer_remain(); | ||
185 | #endif | ||
186 | #ifdef CONFIG_ARCH_TEGRA_3x_SOC | ||
187 | return tegra3_lp2_timer_remain(); | ||
188 | #endif | ||
189 | } | ||
190 | |||
191 | static inline int tegra_is_lp2_timer_ready(unsigned int cpu) | ||
192 | { | ||
193 | #if defined(CONFIG_TEGRA_LP2_ARM_TWD) || defined(CONFIG_ARCH_TEGRA_2x_SOC) | ||
194 | return 1; | ||
195 | #else | ||
196 | return tegra3_is_lp2_timer_ready(cpu); | ||
197 | #endif | ||
198 | } | ||
199 | |||
200 | static inline void tegra_lp2_timer_cancel_secondary(void) | ||
201 | { | ||
202 | #ifndef CONFIG_ARCH_TEGRA_2x_SOC | ||
203 | tegra3_lp2_timer_cancel_secondary(); | ||
204 | #endif | ||
205 | } | ||
206 | |||
207 | #if DEBUG_CLUSTER_SWITCH && 0 /* !!!FIXME!!! THIS IS BROKEN */ | ||
208 | extern unsigned int tegra_cluster_debug; | ||
209 | #define DEBUG_CLUSTER(x) do { if (tegra_cluster_debug) printk x; } while (0) | ||
210 | #else | ||
211 | #define DEBUG_CLUSTER(x) do { } while (0) | ||
212 | #endif | ||
213 | #if PARAMETERIZE_CLUSTER_SWITCH | ||
214 | void tegra_cluster_switch_set_parameters(unsigned int us, unsigned int flags); | ||
215 | #else | ||
216 | static inline void tegra_cluster_switch_set_parameters( | ||
217 | unsigned int us, unsigned int flags) | ||
218 | { } | ||
219 | #endif | ||
220 | |||
221 | #ifdef CONFIG_SMP | ||
222 | extern bool tegra_all_cpus_booted __read_mostly; | ||
223 | #else | ||
224 | #define tegra_all_cpus_booted (true) | ||
225 | #endif | ||
226 | |||
227 | #ifdef CONFIG_TRUSTED_FOUNDATIONS | ||
228 | void tegra_generic_smc(u32 type, u32 subtype, u32 arg); | ||
229 | #endif | ||
230 | |||
231 | /* The debug channel uart base physical address */ | ||
232 | extern unsigned long debug_uart_port_base; | ||
233 | |||
234 | extern struct clk *debug_uart_clk; | ||
235 | void tegra_console_uart_suspend(void); | ||
236 | void tegra_console_uart_resume(void); | ||
237 | |||
238 | #endif /* _MACH_TEGRA_PM_H_ */ | ||