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