aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/pm.c49
-rw-r--r--arch/arm/mach-tegra/reset-handler.S26
-rw-r--r--arch/arm/mach-tegra/sleep.S14
3 files changed, 84 insertions, 5 deletions
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 1ad5719779b0..abf5f88778f4 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -33,11 +33,13 @@
33#include <soc/tegra/pmc.h> 33#include <soc/tegra/pmc.h>
34 34
35#include <asm/cacheflush.h> 35#include <asm/cacheflush.h>
36#include <asm/firmware.h>
36#include <asm/idmap.h> 37#include <asm/idmap.h>
37#include <asm/proc-fns.h> 38#include <asm/proc-fns.h>
38#include <asm/smp_plat.h> 39#include <asm/smp_plat.h>
39#include <asm/suspend.h> 40#include <asm/suspend.h>
40#include <asm/tlbflush.h> 41#include <asm/tlbflush.h>
42#include <asm/trusted_foundations.h>
41 43
42#include "iomap.h" 44#include "iomap.h"
43#include "pm.h" 45#include "pm.h"
@@ -159,6 +161,28 @@ int tegra_cpu_do_idle(void)
159 161
160static int tegra_sleep_cpu(unsigned long v2p) 162static int tegra_sleep_cpu(unsigned long v2p)
161{ 163{
164 /*
165 * L2 cache disabling using kernel API only allowed when all
166 * secondary CPU's are offline. Cache have to be disabled with
167 * MMU-on if cache maintenance is done via Trusted Foundations
168 * firmware. Note that CPUIDLE won't ever enter powergate on Tegra30
169 * if any of secondary CPU's is online and this is the LP2-idle
170 * code-path only for Tegra20/30.
171 */
172 if (trusted_foundations_registered())
173 outer_disable();
174
175 /*
176 * Note that besides of setting up CPU reset vector this firmware
177 * call may also do the following, depending on the FW version:
178 * 1) Disable L2. But this doesn't matter since we already
179 * disabled the L2.
180 * 2) Disable D-cache. This need to be taken into account in
181 * particular by the tegra_disable_clean_inv_dcache() which
182 * shall avoid the re-disable.
183 */
184 call_firmware_op(prepare_idle, TF_PM_MODE_LP2);
185
162 setup_mm_for_reboot(); 186 setup_mm_for_reboot();
163 tegra_sleep_cpu_finish(v2p); 187 tegra_sleep_cpu_finish(v2p);
164 188
@@ -197,6 +221,14 @@ void tegra_idle_lp2_last(void)
197 221
198 cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu); 222 cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
199 223
224 /*
225 * Resume L2 cache if it wasn't re-enabled early during resume,
226 * which is the case for Tegra30 that has to re-enable the cache
227 * via firmware call. In other cases cache is already enabled and
228 * hence re-enabling is a no-op. This is always a no-op on Tegra114+.
229 */
230 outer_resume();
231
200 restore_cpu_complex(); 232 restore_cpu_complex();
201 cpu_cluster_pm_exit(); 233 cpu_cluster_pm_exit();
202} 234}
@@ -215,6 +247,15 @@ enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
215 247
216static int tegra_sleep_core(unsigned long v2p) 248static int tegra_sleep_core(unsigned long v2p)
217{ 249{
250 /*
251 * Cache have to be disabled with MMU-on if cache maintenance is done
252 * via Trusted Foundations firmware. This is a no-op on Tegra114+.
253 */
254 if (trusted_foundations_registered())
255 outer_disable();
256
257 call_firmware_op(prepare_idle, TF_PM_MODE_LP1);
258
218 setup_mm_for_reboot(); 259 setup_mm_for_reboot();
219 tegra_sleep_core_finish(v2p); 260 tegra_sleep_core_finish(v2p);
220 261
@@ -342,6 +383,14 @@ static int tegra_suspend_enter(suspend_state_t state)
342 383
343 cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func); 384 cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func);
344 385
386 /*
387 * Resume L2 cache if it wasn't re-enabled early during resume,
388 * which is the case for Tegra30 that has to re-enable the cache
389 * via firmware call. In other cases cache is already enabled and
390 * hence re-enabling is a no-op.
391 */
392 outer_resume();
393
345 switch (mode) { 394 switch (mode) {
346 case TEGRA_SUSPEND_LP1: 395 case TEGRA_SUSPEND_LP1:
347 tegra_suspend_exit_lp1(); 396 tegra_suspend_exit_lp1();
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index 31fb53f9ce13..cd94d7c41fc0 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -20,6 +20,7 @@
20#include <soc/tegra/flowctrl.h> 20#include <soc/tegra/flowctrl.h>
21#include <soc/tegra/fuse.h> 21#include <soc/tegra/fuse.h>
22 22
23#include <asm/assembler.h>
23#include <asm/asm-offsets.h> 24#include <asm/asm-offsets.h>
24#include <asm/cache.h> 25#include <asm/cache.h>
25 26
@@ -76,6 +77,7 @@ ENTRY(tegra_resume)
76 orr r1, r1, #1 77 orr r1, r1, #1
77 str r1, [r0] 78 str r1, [r0]
78#endif 79#endif
80 bl tegra_resume_trusted_foundations
79 81
80#ifdef CONFIG_CACHE_L2X0 82#ifdef CONFIG_CACHE_L2X0
81 /* L2 cache resume & re-enable */ 83 /* L2 cache resume & re-enable */
@@ -88,6 +90,30 @@ end_ca9_scu_l2_resume:
88 90
89 b cpu_resume 91 b cpu_resume
90ENDPROC(tegra_resume) 92ENDPROC(tegra_resume)
93
94/*
95 * tegra_resume_trusted_foundations
96 *
97 * Trusted Foundations firmware initialization.
98 *
99 * Doesn't return if firmware presents.
100 * Corrupted registers: r1, r2
101 */
102ENTRY(tegra_resume_trusted_foundations)
103 /* Check whether Trusted Foundations firmware presents. */
104 mov32 r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
105 ldr r1, =__tegra_cpu_reset_handler_data_offset + \
106 RESET_DATA(TF_PRESENT)
107 ldr r1, [r2, r1]
108 cmp r1, #0
109 reteq lr
110
111 .arch_extension sec
112 /* First call after suspend wakes firmware. No arguments required. */
113 smc #0
114
115 b cpu_resume
116ENDPROC(tegra_resume_trusted_foundations)
91#endif 117#endif
92 118
93 .align L1_CACHE_SHIFT 119 .align L1_CACHE_SHIFT
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index 5e3496753df1..1735ded5a812 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -49,8 +49,9 @@ ENTRY(tegra_disable_clean_inv_dcache)
49 49
50 /* Disable the D-cache */ 50 /* Disable the D-cache */
51 mrc p15, 0, r2, c1, c0, 0 51 mrc p15, 0, r2, c1, c0, 0
52 tst r2, #CR_C @ see tegra_sleep_cpu()
52 bic r2, r2, #CR_C 53 bic r2, r2, #CR_C
53 mcr p15, 0, r2, c1, c0, 0 54 mcrne p15, 0, r2, c1, c0, 0
54 isb 55 isb
55 56
56 /* Flush the D-cache */ 57 /* Flush the D-cache */
@@ -132,10 +133,13 @@ ENTRY(tegra_shut_off_mmu)
132#ifdef CONFIG_CACHE_L2X0 133#ifdef CONFIG_CACHE_L2X0
133 /* Disable L2 cache */ 134 /* Disable L2 cache */
134 check_cpu_part_num 0xc09, r9, r10 135 check_cpu_part_num 0xc09, r9, r10
135 movweq r2, #:lower16:(TEGRA_ARM_PERIF_BASE + 0x3000) 136 retne r0
136 movteq r2, #:upper16:(TEGRA_ARM_PERIF_BASE + 0x3000) 137
137 moveq r3, #0 138 mov32 r2, TEGRA_ARM_PERIF_BASE + 0x3000
138 streq r3, [r2, #L2X0_CTRL] 139 ldr r3, [r2, #L2X0_CTRL]
140 tst r3, #L2X0_CTRL_EN @ see tegra_sleep_cpu()
141 mov r3, #0
142 strne r3, [r2, #L2X0_CTRL]
139#endif 143#endif
140 ret r0 144 ret r0
141ENDPROC(tegra_shut_off_mmu) 145ENDPROC(tegra_shut_off_mmu)