]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - arch/arm/mach-omap2/sleep44xx.S
ARM: OMAP4: PM: Add CPUX OFF mode support
[mirror_ubuntu-bionic-kernel.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>
13#include <asm/system.h>
14#include <asm/smp_scu.h>
15#include <asm/memory.h>
16#include <asm/hardware/cache-l2x0.h>
17
18#include <plat/omap44xx.h>
19#include <mach/omap-secure.h>
20
21#include "common.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
35/*
36 * =============================
37 * == CPU suspend finisher ==
38 * =============================
39 *
40 * void omap4_finish_suspend(unsigned long cpu_state)
41 *
42 * This function code saves the CPU context and performs the CPU
43 * power down sequence. Calling WFI effectively changes the CPU
44 * power domains states to the desired target power state.
45 *
46 * @cpu_state : contains context save state (r0)
47 * 0 - No context lost
48 * 1 - CPUx L1 and logic lost: MPUSS CSWR
49 * 2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR
50 * 3 - CPUx L1 and logic lost + GIC + L2 lost: MPUSS OFF
51 * @return: This function never returns for CPU OFF and DORMANT power states.
52 * Post WFI, CPU transitions to DORMANT or OFF power state and on wake-up
53 * from this follows a full CPU reset path via ROM code to CPU restore code.
54 * The restore function pointer is stored at CPUx_WAKEUP_NS_PA_ADDR_OFFSET.
55 * It returns to the caller for CPU INACTIVE and ON power states or in case
56 * CPU failed to transition to targeted OFF/DORMANT state.
57 */
58ENTRY(omap4_finish_suspend)
59 stmfd sp!, {lr}
60 cmp r0, #0x0
61 beq do_WFI @ No lowpower state, jump to WFI
62
63 /*
64 * Flush all data from the L1 data cache before disabling
65 * SCTLR.C bit.
66 */
67 bl omap4_get_sar_ram_base
68 ldr r9, [r0, #OMAP_TYPE_OFFSET]
69 cmp r9, #0x1 @ Check for HS device
70 bne skip_secure_l1_clean
71 mov r0, #SCU_PM_NORMAL
72 mov r1, #0xFF @ clean seucre L1
73 stmfd r13!, {r4-r12, r14}
74 ldr r12, =OMAP4_MON_SCU_PWR_INDEX
75 DO_SMC
76 ldmfd r13!, {r4-r12, r14}
77skip_secure_l1_clean:
78 bl v7_flush_dcache_all
79
80 /*
81 * Clear the SCTLR.C bit to prevent further data cache
82 * allocation. Clearing SCTLR.C would make all the data accesses
83 * strongly ordered and would not hit the cache.
84 */
85 mrc p15, 0, r0, c1, c0, 0
86 bic r0, r0, #(1 << 2) @ Disable the C bit
87 mcr p15, 0, r0, c1, c0, 0
88 isb
89
90 /*
91 * Invalidate L1 data cache. Even though only invalidate is
92 * necessary exported flush API is used here. Doing clean
93 * on already clean cache would be almost NOP.
94 */
95 bl v7_flush_dcache_all
96
97 /*
98 * Switch the CPU from Symmetric Multiprocessing (SMP) mode
99 * to AsymmetricMultiprocessing (AMP) mode by programming
100 * the SCU power status to DORMANT or OFF mode.
101 * This enables the CPU to be taken out of coherency by
102 * preventing the CPU from receiving cache, TLB, or BTB
103 * maintenance operations broadcast by other CPUs in the cluster.
104 */
105 bl omap4_get_sar_ram_base
106 mov r8, r0
107 ldr r9, [r8, #OMAP_TYPE_OFFSET]
108 cmp r9, #0x1 @ Check for HS device
109 bne scu_gp_set
110 mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR
111 ands r0, r0, #0x0f
112 ldreq r0, [r8, #SCU_OFFSET0]
113 ldrne r0, [r8, #SCU_OFFSET1]
114 mov r1, #0x00
115 stmfd r13!, {r4-r12, r14}
116 ldr r12, =OMAP4_MON_SCU_PWR_INDEX
117 DO_SMC
118 ldmfd r13!, {r4-r12, r14}
119 b skip_scu_gp_set
120scu_gp_set:
121 mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR
122 ands r0, r0, #0x0f
123 ldreq r1, [r8, #SCU_OFFSET0]
124 ldrne r1, [r8, #SCU_OFFSET1]
125 bl omap4_get_scu_base
126 bl scu_power_mode
127skip_scu_gp_set:
128 mrc p15, 0, r0, c1, c1, 2 @ Read NSACR data
129 tst r0, #(1 << 18)
130 mrcne p15, 0, r0, c1, c0, 1
131 bicne r0, r0, #(1 << 6) @ Disable SMP bit
132 mcrne p15, 0, r0, c1, c0, 1
133 isb
134 dsb
135
136do_WFI:
137 bl omap_do_wfi
138
139 /*
140 * CPU is here when it failed to enter OFF/DORMANT or
141 * no low power state was attempted.
142 */
143 mrc p15, 0, r0, c1, c0, 0
144 tst r0, #(1 << 2) @ Check C bit enabled?
145 orreq r0, r0, #(1 << 2) @ Enable the C bit
146 mcreq p15, 0, r0, c1, c0, 0
147 isb
148
149 /*
150 * Ensure the CPU power state is set to NORMAL in
151 * SCU power state so that CPU is back in coherency.
152 * In non-coherent mode CPU can lock-up and lead to
153 * system deadlock.
154 */
155 mrc p15, 0, r0, c1, c0, 1
156 tst r0, #(1 << 6) @ Check SMP bit enabled?
157 orreq r0, r0, #(1 << 6)
158 mcreq p15, 0, r0, c1, c0, 1
159 isb
160 bl omap4_get_sar_ram_base
161 mov r8, r0
162 ldr r9, [r8, #OMAP_TYPE_OFFSET]
163 cmp r9, #0x1 @ Check for HS device
164 bne scu_gp_clear
165 mov r0, #SCU_PM_NORMAL
166 mov r1, #0x00
167 stmfd r13!, {r4-r12, r14}
168 ldr r12, =OMAP4_MON_SCU_PWR_INDEX
169 DO_SMC
170 ldmfd r13!, {r4-r12, r14}
171 b skip_scu_gp_clear
172scu_gp_clear:
173 bl omap4_get_scu_base
174 mov r1, #SCU_PM_NORMAL
175 bl scu_power_mode
176skip_scu_gp_clear:
177 isb
178 dsb
179 ldmfd sp!, {pc}
180ENDPROC(omap4_finish_suspend)
181
182/*
183 * ============================
184 * == CPU resume entry point ==
185 * ============================
186 *
187 * void omap4_cpu_resume(void)
188 *
189 * ROM code jumps to this function while waking up from CPU
190 * OFF or DORMANT state. Physical address of the function is
191 * stored in the SAR RAM while entering to OFF or DORMANT mode.
192 * The restore function pointer is stored at CPUx_WAKEUP_NS_PA_ADDR_OFFSET.
193 */
194ENTRY(omap4_cpu_resume)
195 /*
196 * Configure ACTRL and enable NS SMP bit access on CPU1 on HS device.
197 * OMAP44XX EMU/HS devices - CPU0 SMP bit access is enabled in PPA
198 * init and for CPU1, a secure PPA API provided. CPU0 must be ON
199 * while executing NS_SMP API on CPU1 and PPA version must be 1.4.0+.
200 * OMAP443X GP devices- SMP bit isn't accessible.
201 * OMAP446X GP devices - SMP bit access is enabled on both CPUs.
202 */
203 ldr r8, =OMAP44XX_SAR_RAM_BASE
204 ldr r9, [r8, #OMAP_TYPE_OFFSET]
205 cmp r9, #0x1 @ Skip if GP device
206 bne skip_ns_smp_enable
207 mrc p15, 0, r0, c0, c0, 5
208 ands r0, r0, #0x0f
209 beq skip_ns_smp_enable
210ppa_actrl_retry:
211 mov r0, #OMAP4_PPA_CPU_ACTRL_SMP_INDEX
212 adr r3, ppa_zero_params @ Pointer to parameters
213 mov r1, #0x0 @ Process ID
214 mov r2, #0x4 @ Flag
215 mov r6, #0xff
216 mov r12, #0x00 @ Secure Service ID
217 DO_SMC
218 cmp r0, #0x0 @ API returns 0 on success.
219 beq enable_smp_bit
220 b ppa_actrl_retry
221enable_smp_bit:
222 mrc p15, 0, r0, c1, c0, 1
223 tst r0, #(1 << 6) @ Check SMP bit enabled?
224 orreq r0, r0, #(1 << 6)
225 mcreq p15, 0, r0, c1, c0, 1
226 isb
227skip_ns_smp_enable:
228
229 b cpu_resume @ Jump to generic resume
230ENDPROC(omap4_cpu_resume)
231#endif
232
233ENTRY(omap_do_wfi)
234 stmfd sp!, {lr}
235
236 /*
237 * Execute an ISB instruction to ensure that all of the
238 * CP15 register changes have been committed.
239 */
240 isb
241
242 /*
243 * Execute a barrier instruction to ensure that all cache,
244 * TLB and branch predictor maintenance operations issued
245 * by any CPU in the cluster have completed.
246 */
247 dsb
248 dmb
249
250 /*
251 * Execute a WFI instruction and wait until the
252 * STANDBYWFI output is asserted to indicate that the
253 * CPU is in idle and low power state. CPU can specualatively
254 * prefetch the instructions so add NOPs after WFI. Sixteen
255 * NOPs as per Cortex-A9 pipeline.
256 */
257 wfi @ Wait For Interrupt
258 nop
259 nop
260 nop
261 nop
262 nop
263 nop
264 nop
265 nop
266 nop
267 nop
268 nop
269 nop
270 nop
271 nop
272 nop
273 nop
274
275 ldmfd sp!, {pc}
276ENDPROC(omap_do_wfi)