]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/arm/mach-omap2/sleep44xx.S
Merge branch 'cpuidle' into release
[karo-tx-linux.git] / arch / arm / mach-omap2 / sleep44xx.S
1 /*
2  * OMAP44xx sleep code.
3  *
4  * Copyright (C) 2011 Texas Instruments, Inc.
5  *      Santosh Shilimkar <santosh.shilimkar@ti.com>
6  *
7  * This program is free software,you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11
12 #include <linux/linkage.h>
13 #include <asm/assembler.h>
14 #include <asm/smp_scu.h>
15 #include <asm/memory.h>
16 #include <asm/hardware/cache-l2x0.h>
17
18 #include "omap-secure.h"
19
20 #include "common.h"
21 #include "omap44xx.h"
22 #include "omap4-sar-layout.h"
23
24 #if defined(CONFIG_SMP) && defined(CONFIG_PM)
25
26 .macro  DO_SMC
27         dsb
28         smc     #0
29         dsb
30 .endm
31
32 ppa_zero_params:
33         .word           0x0
34
35 ppa_por_params:
36         .word           1, 0
37
38 #ifdef CONFIG_ARCH_OMAP4
39
40 /*
41  * =============================
42  * == CPU suspend finisher ==
43  * =============================
44  *
45  * void omap4_finish_suspend(unsigned long cpu_state)
46  *
47  * This function code saves the CPU context and performs the CPU
48  * power down sequence. Calling WFI effectively changes the CPU
49  * power domains states to the desired target power state.
50  *
51  * @cpu_state : contains context save state (r0)
52  *      0 - No context lost
53  *      1 - CPUx L1 and logic lost: MPUSS CSWR
54  *      2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR
55  *      3 - CPUx L1 and logic lost + GIC + L2 lost: MPUSS OFF
56  * @return: This function never returns for CPU OFF and DORMANT power states.
57  * Post WFI, CPU transitions to DORMANT or OFF power state and on wake-up
58  * from this follows a full CPU reset path via ROM code to CPU restore code.
59  * The restore function pointer is stored at CPUx_WAKEUP_NS_PA_ADDR_OFFSET.
60  * It returns to the caller for CPU INACTIVE and ON power states or in case
61  * CPU failed to transition to targeted OFF/DORMANT state.
62  *
63  * omap4_finish_suspend() calls v7_flush_dcache_all() which doesn't save
64  * stack frame and it expects the caller to take care of it. Hence the entire
65  * stack frame is saved to avoid possible stack corruption.
66  */
67 ENTRY(omap4_finish_suspend)
68         stmfd   sp!, {r4-r12, lr}
69         cmp     r0, #0x0
70         beq     do_WFI                          @ No lowpower state, jump to WFI
71
72         /*
73          * Flush all data from the L1 data cache before disabling
74          * SCTLR.C bit.
75          */
76         bl      omap4_get_sar_ram_base
77         ldr     r9, [r0, #OMAP_TYPE_OFFSET]
78         cmp     r9, #0x1                        @ Check for HS device
79         bne     skip_secure_l1_clean
80         mov     r0, #SCU_PM_NORMAL
81         mov     r1, #0xFF                       @ clean seucre L1
82         stmfd   r13!, {r4-r12, r14}
83         ldr     r12, =OMAP4_MON_SCU_PWR_INDEX
84         DO_SMC
85         ldmfd   r13!, {r4-r12, r14}
86 skip_secure_l1_clean:
87         bl      v7_flush_dcache_all
88
89         /*
90          * Clear the SCTLR.C bit to prevent further data cache
91          * allocation. Clearing SCTLR.C would make all the data accesses
92          * strongly ordered and would not hit the cache.
93          */
94         mrc     p15, 0, r0, c1, c0, 0
95         bic     r0, r0, #(1 << 2)               @ Disable the C bit
96         mcr     p15, 0, r0, c1, c0, 0
97         isb
98
99         /*
100          * Invalidate L1 data cache. Even though only invalidate is
101          * necessary exported flush API is used here. Doing clean
102          * on already clean cache would be almost NOP.
103          */
104         bl      v7_flush_dcache_all
105
106         /*
107          * Switch the CPU from Symmetric Multiprocessing (SMP) mode
108          * to AsymmetricMultiprocessing (AMP) mode by programming
109          * the SCU power status to DORMANT or OFF mode.
110          * This enables the CPU to be taken out of coherency by
111          * preventing the CPU from receiving cache, TLB, or BTB
112          * maintenance operations broadcast by other CPUs in the cluster.
113          */
114         bl      omap4_get_sar_ram_base
115         mov     r8, r0
116         ldr     r9, [r8, #OMAP_TYPE_OFFSET]
117         cmp     r9, #0x1                        @ Check for HS device
118         bne     scu_gp_set
119         mrc     p15, 0, r0, c0, c0, 5           @ Read MPIDR
120         ands    r0, r0, #0x0f
121         ldreq   r0, [r8, #SCU_OFFSET0]
122         ldrne   r0, [r8, #SCU_OFFSET1]
123         mov     r1, #0x00
124         stmfd   r13!, {r4-r12, r14}
125         ldr     r12, =OMAP4_MON_SCU_PWR_INDEX
126         DO_SMC
127         ldmfd   r13!, {r4-r12, r14}
128         b       skip_scu_gp_set
129 scu_gp_set:
130         mrc     p15, 0, r0, c0, c0, 5           @ Read MPIDR
131         ands    r0, r0, #0x0f
132         ldreq   r1, [r8, #SCU_OFFSET0]
133         ldrne   r1, [r8, #SCU_OFFSET1]
134         bl      omap4_get_scu_base
135         bl      scu_power_mode
136 skip_scu_gp_set:
137         mrc     p15, 0, r0, c1, c1, 2           @ Read NSACR data
138         tst     r0, #(1 << 18)
139         mrcne   p15, 0, r0, c1, c0, 1
140         bicne   r0, r0, #(1 << 6)               @ Disable SMP bit
141         mcrne   p15, 0, r0, c1, c0, 1
142         isb
143         dsb
144 #ifdef CONFIG_CACHE_L2X0
145         /*
146          * Clean and invalidate the L2 cache.
147          * Common cache-l2x0.c functions can't be used here since it
148          * uses spinlocks. We are out of coherency here with data cache
149          * disabled. The spinlock implementation uses exclusive load/store
150          * instruction which can fail without data cache being enabled.
151          * OMAP4 hardware doesn't support exclusive monitor which can
152          * overcome exclusive access issue. Because of this, CPU can
153          * lead to deadlock.
154          */
155         bl      omap4_get_sar_ram_base
156         mov     r8, r0
157         mrc     p15, 0, r5, c0, c0, 5           @ Read MPIDR
158         ands    r5, r5, #0x0f
159         ldreq   r0, [r8, #L2X0_SAVE_OFFSET0]    @ Retrieve L2 state from SAR
160         ldrne   r0, [r8, #L2X0_SAVE_OFFSET1]    @ memory.
161         cmp     r0, #3
162         bne     do_WFI
163 #ifdef CONFIG_PL310_ERRATA_727915
164         mov     r0, #0x03
165         mov     r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
166         DO_SMC
167 #endif
168         bl      omap4_get_l2cache_base
169         mov     r2, r0
170         ldr     r0, =0xffff
171         str     r0, [r2, #L2X0_CLEAN_INV_WAY]
172 wait:
173         ldr     r0, [r2, #L2X0_CLEAN_INV_WAY]
174         ldr     r1, =0xffff
175         ands    r0, r0, r1
176         bne     wait
177 #ifdef CONFIG_PL310_ERRATA_727915
178         mov     r0, #0x00
179         mov     r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
180         DO_SMC
181 #endif
182 l2x_sync:
183         bl      omap4_get_l2cache_base
184         mov     r2, r0
185         mov     r0, #0x0
186         str     r0, [r2, #L2X0_CACHE_SYNC]
187 sync:
188         ldr     r0, [r2, #L2X0_CACHE_SYNC]
189         ands    r0, r0, #0x1
190         bne     sync
191 #endif
192
193 do_WFI:
194         bl      omap_do_wfi
195
196         /*
197          * CPU is here when it failed to enter OFF/DORMANT or
198          * no low power state was attempted.
199          */
200         mrc     p15, 0, r0, c1, c0, 0
201         tst     r0, #(1 << 2)                   @ Check C bit enabled?
202         orreq   r0, r0, #(1 << 2)               @ Enable the C bit
203         mcreq   p15, 0, r0, c1, c0, 0
204         isb
205
206         /*
207          * Ensure the CPU power state is set to NORMAL in
208          * SCU power state so that CPU is back in coherency.
209          * In non-coherent mode CPU can lock-up and lead to
210          * system deadlock.
211          */
212         mrc     p15, 0, r0, c1, c0, 1
213         tst     r0, #(1 << 6)                   @ Check SMP bit enabled?
214         orreq   r0, r0, #(1 << 6)
215         mcreq   p15, 0, r0, c1, c0, 1
216         isb
217         bl      omap4_get_sar_ram_base
218         mov     r8, r0
219         ldr     r9, [r8, #OMAP_TYPE_OFFSET]
220         cmp     r9, #0x1                        @ Check for HS device
221         bne     scu_gp_clear
222         mov     r0, #SCU_PM_NORMAL
223         mov     r1, #0x00
224         stmfd   r13!, {r4-r12, r14}
225         ldr     r12, =OMAP4_MON_SCU_PWR_INDEX
226         DO_SMC
227         ldmfd   r13!, {r4-r12, r14}
228         b       skip_scu_gp_clear
229 scu_gp_clear:
230         bl      omap4_get_scu_base
231         mov     r1, #SCU_PM_NORMAL
232         bl      scu_power_mode
233 skip_scu_gp_clear:
234         isb
235         dsb
236         ldmfd   sp!, {r4-r12, pc}
237 ENDPROC(omap4_finish_suspend)
238
239 /*
240  * ============================
241  * == CPU resume entry point ==
242  * ============================
243  *
244  * void omap4_cpu_resume(void)
245  *
246  * ROM code jumps to this function while waking up from CPU
247  * OFF or DORMANT state. Physical address of the function is
248  * stored in the SAR RAM while entering to OFF or DORMANT mode.
249  * The restore function pointer is stored at CPUx_WAKEUP_NS_PA_ADDR_OFFSET.
250  */
251 ENTRY(omap4_cpu_resume)
252         /*
253          * Configure ACTRL and enable NS SMP bit access on CPU1 on HS device.
254          * OMAP44XX EMU/HS devices - CPU0 SMP bit access is enabled in PPA
255          * init and for CPU1, a secure PPA API provided. CPU0 must be ON
256          * while executing NS_SMP API on CPU1 and PPA version must be 1.4.0+.
257          * OMAP443X GP devices- SMP bit isn't accessible.
258          * OMAP446X GP devices - SMP bit access is enabled on both CPUs.
259          */
260         ldr     r8, =OMAP44XX_SAR_RAM_BASE
261         ldr     r9, [r8, #OMAP_TYPE_OFFSET]
262         cmp     r9, #0x1                        @ Skip if GP device
263         bne     skip_ns_smp_enable
264         mrc     p15, 0, r0, c0, c0, 5
265         ands    r0, r0, #0x0f
266         beq     skip_ns_smp_enable
267 ppa_actrl_retry:
268         mov     r0, #OMAP4_PPA_CPU_ACTRL_SMP_INDEX
269         adr     r3, ppa_zero_params             @ Pointer to parameters
270         mov     r1, #0x0                        @ Process ID
271         mov     r2, #0x4                        @ Flag
272         mov     r6, #0xff
273         mov     r12, #0x00                      @ Secure Service ID
274         DO_SMC
275         cmp     r0, #0x0                        @ API returns 0 on success.
276         beq     enable_smp_bit
277         b       ppa_actrl_retry
278 enable_smp_bit:
279         mrc     p15, 0, r0, c1, c0, 1
280         tst     r0, #(1 << 6)                   @ Check SMP bit enabled?
281         orreq   r0, r0, #(1 << 6)
282         mcreq   p15, 0, r0, c1, c0, 1
283         isb
284 skip_ns_smp_enable:
285 #ifdef CONFIG_CACHE_L2X0
286         /*
287          * Restore the L2 AUXCTRL and enable the L2 cache.
288          * OMAP4_MON_L2X0_AUXCTRL_INDEX =  Program the L2X0 AUXCTRL
289          * OMAP4_MON_L2X0_CTRL_INDEX =  Enable the L2 using L2X0 CTRL
290          * register r0 contains value to be programmed.
291          * L2 cache is already invalidate by ROM code as part
292          * of MPUSS OFF wakeup path.
293          */
294         ldr     r2, =OMAP44XX_L2CACHE_BASE
295         ldr     r0, [r2, #L2X0_CTRL]
296         and     r0, #0x0f
297         cmp     r0, #1
298         beq     skip_l2en                       @ Skip if already enabled
299         ldr     r3, =OMAP44XX_SAR_RAM_BASE
300         ldr     r1, [r3, #OMAP_TYPE_OFFSET]
301         cmp     r1, #0x1                        @ Check for HS device
302         bne     set_gp_por
303         ldr     r0, =OMAP4_PPA_L2_POR_INDEX
304         ldr     r1, =OMAP44XX_SAR_RAM_BASE
305         ldr     r4, [r1, #L2X0_PREFETCH_CTRL_OFFSET]
306         adr     r3, ppa_por_params
307         str     r4, [r3, #0x04]
308         mov     r1, #0x0                        @ Process ID
309         mov     r2, #0x4                        @ Flag
310         mov     r6, #0xff
311         mov     r12, #0x00                      @ Secure Service ID
312         DO_SMC
313         b       set_aux_ctrl
314 set_gp_por:
315         ldr     r1, =OMAP44XX_SAR_RAM_BASE
316         ldr     r0, [r1, #L2X0_PREFETCH_CTRL_OFFSET]
317         ldr     r12, =OMAP4_MON_L2X0_PREFETCH_INDEX     @ Setup L2 PREFETCH
318         DO_SMC
319 set_aux_ctrl:
320         ldr     r1, =OMAP44XX_SAR_RAM_BASE
321         ldr     r0, [r1, #L2X0_AUXCTRL_OFFSET]
322         ldr     r12, =OMAP4_MON_L2X0_AUXCTRL_INDEX      @ Setup L2 AUXCTRL
323         DO_SMC
324         mov     r0, #0x1
325         ldr     r12, =OMAP4_MON_L2X0_CTRL_INDEX         @ Enable L2 cache
326         DO_SMC
327 skip_l2en:
328 #endif
329
330         b       cpu_resume                      @ Jump to generic resume
331 ENDPROC(omap4_cpu_resume)
332 #endif  /* CONFIG_ARCH_OMAP4 */
333
334 #endif  /* defined(CONFIG_SMP) && defined(CONFIG_PM) */
335
336 ENTRY(omap_do_wfi)
337         stmfd   sp!, {lr}
338 #ifdef CONFIG_OMAP_INTERCONNECT_BARRIER
339         /* Drain interconnect write buffers. */
340         bl      omap_interconnect_sync
341 #endif
342
343         /*
344          * Execute an ISB instruction to ensure that all of the
345          * CP15 register changes have been committed.
346          */
347         isb
348
349         /*
350          * Execute a barrier instruction to ensure that all cache,
351          * TLB and branch predictor maintenance operations issued
352          * by any CPU in the cluster have completed.
353          */
354         dsb
355         dmb
356
357         /*
358          * Execute a WFI instruction and wait until the
359          * STANDBYWFI output is asserted to indicate that the
360          * CPU is in idle and low power state. CPU can specualatively
361          * prefetch the instructions so add NOPs after WFI. Sixteen
362          * NOPs as per Cortex-A9 pipeline.
363          */
364         wfi                                     @ Wait For Interrupt
365         nop
366         nop
367         nop
368         nop
369         nop
370         nop
371         nop
372         nop
373         nop
374         nop
375         nop
376         nop
377         nop
378         nop
379         nop
380         nop
381
382         ldmfd   sp!, {pc}
383 ENDPROC(omap_do_wfi)