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