tlk: 6/19 update
[3rdparty/ote_partner/tlk.git] / platform / tegra / common / pm.c
1 /*
2  * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23
24 #include <err.h>
25 #include <errno.h>
26 #include <debug.h>
27 #include <assert.h>
28 #include <malloc.h>
29 #include <string.h>
30 #include <platform.h>
31 #include <arch.h>
32 #include <stdlib.h>
33 #include <lib/heap.h>
34 #include <arch/outercache.h>
35 #include <platform/memmap.h>
36 #include <platform/tzrammap.h>
37 #include <platform/irqs.h>
38 #include <arch/arm.h>
39 #include <arch/arm/mmu.h>
40 #include <platform/platform_p.h>
41 #include <ote_intf.h>
42
43 #define MONITOR_MODE_STACK_SZ   4096
44
45 /* referenced APBDEV_PMC_SECURE registers */
46 #define PMC_SECURE_DISABLE2     0x2c4
47 #define PMC_SECURE_SCRATCH22    0x338
48
49 /*
50  * The PSCI spec from ARM states the following for power mgmt:
51  * SMC         (r0) - CPU_SUSPEND  = 0x84000001
52  * power_state (r1) - Bits [0:15]  = StateID
53  *                    Bit  [16]    = StateType <0=Stdby, 1=PwrDn>
54  *                    Bits [17:23] = MBZ
55  *                    Bits [24:25] = AffinityLevel <0=cpu, 1=cluster>
56  *                    Bits [26:31] = MBZ
57  * entry_addr  (r2) - CPU wake up addr
58  * context_id  (r3) - args in r0 when cpu wakes up from pwrdn state and enters
59  *                    exception level of caller
60  * returns     (r0) - SUCCESS/INVALID PARAM
61  */
62 #define LP0                             ((1 << 16) | (1 << 24) | 1)
63 #define LP1                             ((1 << 16) | 2)
64 #define LP1_MC_CLK_STOP                 ((1 << 16) | 3)
65 #define LP2_CLUSTER_PWR_DN              ((1 << 16) | (1 << 24) | 4)
66 #define LP2_CLUSTER_PWR_DN_LEGACY       ((1 << 16) | 4)
67 #define LP2_NO_FLUSH_LEGACY             ((1 << 16) | 5)
68
69 extern unsigned int monitor_vector_base;
70 extern unsigned long mon_stack_top;
71 extern unsigned long _ns_resume_addr;
72 extern unsigned long boot_secondary_cpu_addr;
73
74 /* location in NS to boot cpus */
75 unsigned long _ns_addr_secondary_cpus = 0;
76
77 unsigned int cpu_power_down_mode = 0;
78
79 /* tracks if we need to load resume handlers into tzram */
80 static bool load_tzram_lp1_resume_handler = true;
81
82 static void pm_set_monitor_stack(void)
83 {
84         void *stack_top_mon;
85         int stack_size = MONITOR_MODE_STACK_SZ;
86
87         stack_top_mon = heap_alloc(stack_size, 0);
88         if (stack_top_mon)
89         {
90                 __asm__ volatile (
91                         "mrs    r2, cpsr        \n" // save current mode
92                         "cps    #0x16           \n" // change to monitor mode
93                         "mov    sp, %0          \n" // set mon_sp
94                         "add    sp, sp, %1      \n" // set mon_sp
95                         "msr    cpsr, r2        \n" // restore previous mode
96                         : : "r" (stack_top_mon),
97                             "r" (stack_size / 2) : "memory"
98                 );
99         } else {
100                 panic("no memory available for monitor stack");
101         }
102
103         memset(stack_top_mon, 0, stack_size);
104         mon_stack_top = (unsigned long)(stack_top_mon + (stack_size / 2));
105 }
106
107 static void pm_set_mvbar(unsigned int val)
108 {
109         __asm__ volatile (
110                 "mcr    p15, 0, %0, c12, c0, 1          \n"
111                 : : "r" (val)
112         );
113 }
114
115 static void pm_set_reset_vector(unsigned long vector_addr)
116 {
117         uint32_t evp_cpu_reset = TEGRA_EXCEPTION_VECTORS_BASE + 0x100;
118         uint32_t sb_ctrl = TEGRA_SB_BASE;
119         uint32_t reg;
120
121         /* set new reset vector */
122         *(volatile uint32_t *)evp_cpu_reset = (uint32_t)vector_addr;
123         __asm__ volatile ("dmb" : : : "memory");
124
125         /* dummy read to ensure successful write */
126         reg = *(volatile uint32_t *)evp_cpu_reset;
127
128         /* lock reset vector */
129         reg = *(volatile uint32_t *)sb_ctrl;
130         reg |= 2;
131         *(volatile uint32_t *)sb_ctrl = reg;
132         __asm__ volatile ("dmb" : : : "memory");
133 }
134
135 static void pm_set_nsacr(void)
136 {
137         /* let normal world enable SMP, lock TLB, access CP10/11 */
138         __asm__ volatile (
139                 "mrc    p15, 0, r0, c1, c1, 2           @ NSACR \n"
140                 "orr    r0, r0, #(0x00000C00)                   \n"
141                 "orr    r0, r0, #(0x00060000)                   \n"
142                 "mcr    p15, 0, r0, c1, c1, 2           @ NSACR \n"
143                 ::: "r0"
144         );
145 }
146
147 void pm_early_init(void)
148 {
149         /* set monitor vector base address (use vaddr, since MMU's enabled) */
150         pm_set_mvbar((unsigned int)&monitor_vector_base);
151
152         /* populate the reset vector to boot all the secondary cpus */
153         pm_set_reset_vector(virtual_to_physical(boot_secondary_cpu_addr));
154 }
155
156 /* LP1 resume code */
157 extern uint32_t _lp1_resume;
158 extern uint32_t _lp1_resume_end;
159
160 #define LP1_RESUME_HANDLER_SIZE \
161         ((uint32_t)&_lp1_resume_end - (uint32_t)&_lp1_resume)
162
163 static void pm_load_tzram_lp1_resume_handler(void)
164 {
165         ASSERT(LP1_RESUME_HANDLER_SIZE < TEGRA_TZRAM_SIZE);
166
167         memcpy((void *)(TZRAM_LP1_RESUME_HANDLER),
168                (void *)&_lp1_resume,
169                LP1_RESUME_HANDLER_SIZE);
170 }
171
172 static void pm_save_lp1_context(void)
173 {
174         /* store any state needed for lp1 resume to tzram */
175         TZRAM_STORE(TZRAM_BOOT_SECONDARY_CPU_ADDR,
176                 virtual_to_physical(boot_secondary_cpu_addr));
177         TZRAM_STORE(TZRAM_MON_STACK_TOP, virtual_to_physical(mon_stack_top));
178         TZRAM_STORE(TZRAM_NS_RESUME_ADDR, _ns_resume_addr);
179         TZRAM_STORE(TZRAM_MVBAR, virtual_to_physical(&monitor_vector_base));
180
181         cpu_copy_context((void *)TZRAM_CPU_CONTEXT);
182 }
183
184 void pm_init(void)
185 {
186         extern unsigned long mon_p2v_offset;
187         extern uint32_t _boot_secondary_phys_base;
188         extern uint32_t __load_phys_size;
189         uint32_t reg;
190
191         pm_early_init();
192
193         /* set monitor vector stack */
194         pm_set_monitor_stack();
195
196         /* set normal world access in NSACR */
197         pm_set_nsacr();
198
199         /* save mmu setup used to bring up secondary cpus */
200         cpu_save_context();
201
202         /* save off values to help with v-to-p operations */
203         _boot_secondary_phys_base = __load_phys_base;
204         mon_p2v_offset = (VMEMBASE - __load_phys_base);
205
206         /* install the cpu resume handler to PMC_SEC_SCRATCH22 */
207         reg = readl(TEGRA_PMC_BASE + PMC_SECURE_DISABLE2);
208         writel(reg & ~(1 << 28), TEGRA_PMC_BASE + PMC_SECURE_DISABLE2); /* unlock */
209
210         writel(virtual_to_physical(boot_secondary_cpu_addr), TEGRA_PMC_BASE + PMC_SECURE_SCRATCH22);
211
212         reg = readl(TEGRA_PMC_BASE + PMC_SECURE_DISABLE2);
213         writel(reg | 1 << 28, TEGRA_PMC_BASE + PMC_SECURE_DISABLE2);    /* lock */
214
215         platform_init_memory(__load_phys_base, __load_phys_size);
216         platform_config_interrupts();
217 }
218
219 /*
220  * Stubs for routines not used by all platforms
221  */
222 __WEAK void pm_handle_smc_l2(unsigned int smc)
223 {
224         dprintf(CRITICAL, "stubbed L2 SMC handler (shouldn't have been issued)\n");
225         return;
226 }
227
228 __WEAK void pm_handle_smc_deep_sleep(void)
229 {
230         return;
231 }
232
233 /*
234  * Suspend-related SMCs.
235  */
236 static void pm_handle_lp0_suspend_smc(struct tz_monitor_frame *frame)
237 {
238         cpu_power_down_mode = CPU_IN_LP0;
239
240         /* store passed in non-secure resume handler address */
241         _ns_resume_addr = frame->r[2];
242
243         /* set our LP0 reset vector */
244         pm_set_reset_vector(virtual_to_physical(boot_secondary_cpu_addr));
245
246         /* save off current state */
247         cpu_save_context();
248
249         /* need to reload LP1 handler into tzram before next LP1 suspend */
250         load_tzram_lp1_resume_handler = true;
251
252         /* handle any chip-specific steps */
253         pm_handle_smc_deep_sleep();
254
255         platform_disable_debug_intf();
256
257         /* flush/disable dcache last */
258         arch_disable_cache(DCACHE);
259 }
260
261 static void pm_handle_lp1_suspend_smc(struct tz_monitor_frame *frame)
262 {
263         cpu_power_down_mode = CPU_IN_LP1;
264
265         /* store passed in non-secure resume handler address */
266         _ns_resume_addr = frame->r[2];
267
268         /* set our LP1 reset vector */
269         pm_set_reset_vector(TZRAM_LP1_RESUME_HANDLER);
270
271         /* save off current state */
272         cpu_save_context();
273
274         /* save off state needed by LP1 resume handler */
275         TZRAM_STORE(TZRAM_CPU_AVOID_CLKM_SWITCH,
276                 frame->r[1] == LP1_MC_CLK_STOP);
277         TZRAM_STORE(TZRAM_BOOT_SECONDARY_CPU_ADDR,
278                 virtual_to_physical(boot_secondary_cpu_addr));
279         pm_save_lp1_context();
280
281         /* load LP1 resume handler to TZRAM if necessary */
282         if (load_tzram_lp1_resume_handler) {
283                 pm_load_tzram_lp1_resume_handler();
284                 load_tzram_lp1_resume_handler = false;
285         }
286
287         /* flush/disable dcache last */
288         arch_disable_cache(DCACHE);
289 }
290
291 static void pm_handle_lp2_suspend_smc(struct tz_monitor_frame *frame)
292 {
293         cpu_power_down_mode = CPU_IN_LP2;
294
295         /* set our LP2 reset vector */
296         pm_set_reset_vector(virtual_to_physical(boot_secondary_cpu_addr));
297
298         /* save off current state */
299         cpu_save_context();
300
301         /* flush/disable dcache last */
302         arch_disable_cache(DCACHE);
303 }
304
305 /*
306  * System related SMCs handled on the current idle stack.
307  * These should be simple operations that can't block.
308  */
309 void pm_handle_platform_smc(struct tz_monitor_frame *frame)
310 {
311         int error = 0;
312
313         switch (frame->r[0]) {
314                 case SMC_SIP_L2_MANAGEMENT:
315                         pm_handle_smc_l2(frame->r[1]);
316                         break;
317
318                 case SMC_SIP_CPU_RESET_VECTOR_LEGACY:
319                 case SMC_SIP_CPU_RESET_VECTOR:
320                         _ns_addr_secondary_cpus = frame->r[1];
321                         if (frame->r[1] == 0)
322                                 _ns_addr_secondary_cpus = frame->r[2];
323 #if defined(ARM_USE_CPU_CACHING)
324                         platform_clean_invalidate_cache_range(
325                                 (vaddr_t)&_ns_addr_secondary_cpus,
326                                 sizeof(_ns_addr_secondary_cpus));
327 #endif
328                         platform_enable_debug_intf();
329                         break;
330
331                 case SMC_SIP_DEVICE_SUSPEND:
332                         switch (frame->r[1]) {
333                         case LP2_CLUSTER_PWR_DN:
334                         case LP2_CLUSTER_PWR_DN_LEGACY:
335                         case LP2_NO_FLUSH_LEGACY:
336                                 pm_handle_lp2_suspend_smc(frame);
337                                 break;
338                         case LP1:
339                         case LP1_MC_CLK_STOP:
340                                 pm_handle_lp1_suspend_smc(frame);
341                                 break;
342                         case LP0:
343                                 pm_handle_lp0_suspend_smc(frame);
344                                 break;
345                         default:
346                                 error = -EINVAL;
347                                 break;
348                         }
349                         break;
350         }
351         frame->r[0] = error;
352 }