xref: /openbmc/linux/arch/arm/mach-omap2/sleep44xx.S (revision eb3fcf00)
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
32ppa_zero_params:
33	.word		0x0
34
35ppa_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 */
67ENTRY(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}
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
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
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
236	ldmfd	sp!, {r4-r12, pc}
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:
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
329
330	b	cpu_resume			@ Jump to generic resume
331ENDPROC(omap4_cpu_resume)
332#endif	/* CONFIG_ARCH_OMAP4 */
333
334#endif	/* defined(CONFIG_SMP) && defined(CONFIG_PM) */
335
336ENTRY(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}
383ENDPROC(omap_do_wfi)
384