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