• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
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 */
60ENTRY(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}
79skip_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
122scu_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
129skip_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]
165wait:
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
175l2x_sync:
176	bl	omap4_get_l2cache_base
177	mov	r2, r0
178	mov	r0, #0x0
179	str	r0, [r2, #L2X0_CACHE_SYNC]
180sync:
181	ldr	r0, [r2, #L2X0_CACHE_SYNC]
182	ands	r0, r0, #0x1
183	bne	sync
184#endif
185
186do_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
222scu_gp_clear:
223	bl	omap4_get_scu_base
224	mov	r1, #SCU_PM_NORMAL
225	bl	scu_power_mode
226skip_scu_gp_clear:
227	isb
228	dsb
229	ldmfd	sp!, {pc}
230ENDPROC(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 */
244ENTRY(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
260ppa_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
271enable_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
277skip_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
307set_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
312set_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
320skip_l2en:
321#endif
322
323	b	cpu_resume			@ Jump to generic resume
324ENDPROC(omap4_cpu_resume)
325#endif
326
327#ifndef CONFIG_OMAP4_ERRATA_I688
328ENTRY(omap_bus_sync)
329	mov	pc, lr
330ENDPROC(omap_bus_sync)
331#endif
332
333ENTRY(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}
378ENDPROC(omap_do_wfi)
379