Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetoot...
[deliverable/linux.git] / arch / arm / mach-omap2 / sleep44xx.S
CommitLineData
b2b9762f
SS
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>
6ebbf2ce 13#include <asm/assembler.h>
b2b9762f
SS
14#include <asm/smp_scu.h>
15#include <asm/memory.h>
16#include <asm/hardware/cache-l2x0.h>
17
c1db9d73 18#include "omap-secure.h"
b2b9762f
SS
19
20#include "common.h"
c49f34bc 21#include "omap44xx.h"
b2b9762f
SS
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
32ppa_zero_params:
33 .word 0x0
34
5e94c6e3
SS
35ppa_por_params:
36 .word 1, 0
37
b46355a9
NM
38#ifdef CONFIG_ARCH_OMAP4
39
b2b9762f
SS
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.
5b6e3eb5
SS
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.
b2b9762f
SS
66 */
67ENTRY(omap4_finish_suspend)
5b6e3eb5 68 stmfd sp!, {r4-r12, lr}
b2b9762f
SS
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}
86skip_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
129scu_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
136skip_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
5e94c6e3
SS
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]
172wait:
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
182l2x_sync:
183 bl omap4_get_l2cache_base
184 mov r2, r0
185 mov r0, #0x0
186 str r0, [r2, #L2X0_CACHE_SYNC]
187sync:
188 ldr r0, [r2, #L2X0_CACHE_SYNC]
189 ands r0, r0, #0x1
190 bne sync
191#endif
b2b9762f
SS
192
193do_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
229scu_gp_clear:
230 bl omap4_get_scu_base
231 mov r1, #SCU_PM_NORMAL
232 bl scu_power_mode
233skip_scu_gp_clear:
234 isb
235 dsb
5b6e3eb5 236 ldmfd sp!, {r4-r12, pc}
b2b9762f
SS
237ENDPROC(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 */
251ENTRY(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
267ppa_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
278enable_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
284skip_ns_smp_enable:
5e94c6e3
SS
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
314set_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
319set_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
327skip_l2en:
328#endif
b2b9762f
SS
329
330 b cpu_resume @ Jump to generic resume
331ENDPROC(omap4_cpu_resume)
b46355a9
NM
332#endif /* CONFIG_ARCH_OMAP4 */
333
334#endif /* defined(CONFIG_SMP) && defined(CONFIG_PM) */
b2b9762f
SS
335
336ENTRY(omap_do_wfi)
337 stmfd sp!, {lr}
3fa60975 338#ifdef CONFIG_OMAP_INTERCONNECT_BARRIER
137d105d 339 /* Drain interconnect write buffers. */
3fa60975
RK
340 bl omap_interconnect_sync
341#endif
b2b9762f
SS
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}
383ENDPROC(omap_do_wfi)
This page took 0.222345 seconds and 5 git commands to generate.