~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-omap2/sleep44xx.S

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0-only */
  2 /*
  3  * OMAP44xx sleep code.
  4  *
  5  * Copyright (C) 2011 Texas Instruments, Inc.
  6  *      Santosh Shilimkar <santosh.shilimkar@ti.com>
  7  */
  8 
  9 #include <linux/linkage.h>
 10 #include <asm/assembler.h>
 11 #include <asm/smp_scu.h>
 12 #include <asm/page.h>
 13 #include <asm/hardware/cache-l2x0.h>
 14 
 15 #include "omap-secure.h"
 16 
 17 #include "common.h"
 18 #include "omap44xx.h"
 19 #include "omap4-sar-layout.h"
 20 
 21         .arch armv7-a
 22 
 23 #if defined(CONFIG_SMP) && defined(CONFIG_PM)
 24 
 25         .arch_extension sec
 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  */
 61 ENTRY(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}
 80 skip_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         bl      v7_invalidate_l1
 94 
 95         /*
 96          * Switch the CPU from Symmetric Multiprocessing (SMP) mode
 97          * to AsymmetricMultiprocessing (AMP) mode by programming
 98          * the SCU power status to DORMANT or OFF mode.
 99          * This enables the CPU to be taken out of coherency by
100          * preventing the CPU from receiving cache, TLB, or BTB
101          * maintenance operations broadcast by other CPUs in the cluster.
102          */
103         bl      omap4_get_sar_ram_base
104         mov     r8, r0
105         ldr     r9, [r8, #OMAP_TYPE_OFFSET]
106         cmp     r9, #0x1                        @ Check for HS device
107         bne     scu_gp_set
108         mrc     p15, 0, r0, c0, c0, 5           @ Read MPIDR
109         ands    r0, r0, #0x0f
110         ldreq   r0, [r8, #SCU_OFFSET0]
111         ldrne   r0, [r8, #SCU_OFFSET1]
112         mov     r1, #0x00
113         stmfd   r13!, {r4-r12, r14}
114         ldr     r12, =OMAP4_MON_SCU_PWR_INDEX
115         DO_SMC
116         ldmfd   r13!, {r4-r12, r14}
117         b       skip_scu_gp_set
118 scu_gp_set:
119         mrc     p15, 0, r0, c0, c0, 5           @ Read MPIDR
120         ands    r0, r0, #0x0f
121         ldreq   r1, [r8, #SCU_OFFSET0]
122         ldrne   r1, [r8, #SCU_OFFSET1]
123         bl      omap4_get_scu_base
124         bl      scu_power_mode
125 skip_scu_gp_set:
126         mrc     p15, 0, r0, c1, c1, 2           @ Read NSACR data
127         tst     r0, #(1 << 18)
128         mrcne   p15, 0, r0, c1, c0, 1
129         bicne   r0, r0, #(1 << 6)               @ Disable SMP bit
130         mcrne   p15, 0, r0, c1, c0, 1
131         isb
132         dsb
133 #ifdef CONFIG_CACHE_L2X0
134         /*
135          * Clean and invalidate the L2 cache.
136          * Common cache-l2x0.c functions can't be used here since it
137          * uses spinlocks. We are out of coherency here with data cache
138          * disabled. The spinlock implementation uses exclusive load/store
139          * instruction which can fail without data cache being enabled.
140          * OMAP4 hardware doesn't support exclusive monitor which can
141          * overcome exclusive access issue. Because of this, CPU can
142          * lead to deadlock.
143          */
144         bl      omap4_get_sar_ram_base
145         mov     r8, r0
146         mrc     p15, 0, r5, c0, c0, 5           @ Read MPIDR
147         ands    r5, r5, #0x0f
148         ldreq   r0, [r8, #L2X0_SAVE_OFFSET0]    @ Retrieve L2 state from SAR
149         ldrne   r0, [r8, #L2X0_SAVE_OFFSET1]    @ memory.
150         cmp     r0, #3
151         bne     do_WFI
152 #ifdef CONFIG_PL310_ERRATA_727915
153         mov     r0, #0x03
154         mov     r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
155         DO_SMC
156 #endif
157         bl      omap4_get_l2cache_base
158         mov     r2, r0
159         ldr     r0, =0xffff
160         str     r0, [r2, #L2X0_CLEAN_INV_WAY]
161 wait:
162         ldr     r0, [r2, #L2X0_CLEAN_INV_WAY]
163         ldr     r1, =0xffff
164         ands    r0, r0, r1
165         bne     wait
166 #ifdef CONFIG_PL310_ERRATA_727915
167         mov     r0, #0x00
168         mov     r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
169         DO_SMC
170 #endif
171 l2x_sync:
172         bl      omap4_get_l2cache_base
173         mov     r2, r0
174         mov     r0, #0x0
175         str     r0, [r2, #L2X0_CACHE_SYNC]
176 sync:
177         ldr     r0, [r2, #L2X0_CACHE_SYNC]
178         ands    r0, r0, #0x1
179         bne     sync
180 #endif
181 
182 do_WFI:
183         bl      omap_do_wfi
184 
185         /*
186          * CPU is here when it failed to enter OFF/DORMANT or
187          * no low power state was attempted.
188          */
189         mrc     p15, 0, r0, c1, c0, 0
190         tst     r0, #(1 << 2)                   @ Check C bit enabled?
191         orreq   r0, r0, #(1 << 2)               @ Enable the C bit
192         mcreq   p15, 0, r0, c1, c0, 0
193         isb
194 
195         /*
196          * Ensure the CPU power state is set to NORMAL in
197          * SCU power state so that CPU is back in coherency.
198          * In non-coherent mode CPU can lock-up and lead to
199          * system deadlock.
200          */
201         mrc     p15, 0, r0, c1, c0, 1
202         tst     r0, #(1 << 6)                   @ Check SMP bit enabled?
203         orreq   r0, r0, #(1 << 6)
204         mcreq   p15, 0, r0, c1, c0, 1
205         isb
206         bl      omap4_get_sar_ram_base
207         mov     r8, r0
208         ldr     r9, [r8, #OMAP_TYPE_OFFSET]
209         cmp     r9, #0x1                        @ Check for HS device
210         bne     scu_gp_clear
211         mov     r0, #SCU_PM_NORMAL
212         mov     r1, #0x00
213         stmfd   r13!, {r4-r12, r14}
214         ldr     r12, =OMAP4_MON_SCU_PWR_INDEX
215         DO_SMC
216         ldmfd   r13!, {r4-r12, r14}
217         b       skip_scu_gp_clear
218 scu_gp_clear:
219         bl      omap4_get_scu_base
220         mov     r1, #SCU_PM_NORMAL
221         bl      scu_power_mode
222 skip_scu_gp_clear:
223         isb
224         dsb
225         ldmfd   sp!, {r4-r12, pc}
226 ENDPROC(omap4_finish_suspend)
227 
228 /*
229  * ============================
230  * == CPU resume entry point ==
231  * ============================
232  *
233  * void omap4_cpu_resume(void)
234  *
235  * ROM code jumps to this function while waking up from CPU
236  * OFF or DORMANT state. Physical address of the function is
237  * stored in the SAR RAM while entering to OFF or DORMANT mode.
238  * The restore function pointer is stored at CPUx_WAKEUP_NS_PA_ADDR_OFFSET.
239  */
240 ENTRY(omap4_cpu_resume)
241         /*
242          * Configure ACTRL and enable NS SMP bit access on CPU1 on HS device.
243          * OMAP44XX EMU/HS devices - CPU0 SMP bit access is enabled in PPA
244          * init and for CPU1, a secure PPA API provided. CPU0 must be ON
245          * while executing NS_SMP API on CPU1 and PPA version must be 1.4.0+.
246          * OMAP443X GP devices- SMP bit isn't accessible.
247          * OMAP446X GP devices - SMP bit access is enabled on both CPUs.
248          */
249         ldr     r8, =OMAP44XX_SAR_RAM_BASE
250         ldr     r9, [r8, #OMAP_TYPE_OFFSET]
251         cmp     r9, #0x1                        @ Skip if GP device
252         bne     skip_ns_smp_enable
253         mrc     p15, 0, r0, c0, c0, 5
254         ands    r0, r0, #0x0f
255         beq     skip_ns_smp_enable
256 ppa_actrl_retry:
257         mov     r0, #OMAP4_PPA_CPU_ACTRL_SMP_INDEX
258         adr     r1, ppa_zero_params_offset
259         ldr     r3, [r1]
260         add     r3, r3, r1                      @ Pointer to ppa_zero_params
261         mov     r1, #0x0                        @ Process ID
262         mov     r2, #0x4                        @ Flag
263         mov     r6, #0xff
264         mov     r12, #0x00                      @ Secure Service ID
265         DO_SMC
266         cmp     r0, #0x0                        @ API returns 0 on success.
267         beq     enable_smp_bit
268         b       ppa_actrl_retry
269 enable_smp_bit:
270         mrc     p15, 0, r0, c1, c0, 1
271         tst     r0, #(1 << 6)                   @ Check SMP bit enabled?
272         orreq   r0, r0, #(1 << 6)
273         mcreq   p15, 0, r0, c1, c0, 1
274         isb
275 skip_ns_smp_enable:
276 #ifdef CONFIG_CACHE_L2X0
277         /*
278          * Restore the L2 AUXCTRL and enable the L2 cache.
279          * OMAP4_MON_L2X0_AUXCTRL_INDEX =  Program the L2X0 AUXCTRL
280          * OMAP4_MON_L2X0_CTRL_INDEX =  Enable the L2 using L2X0 CTRL
281          * register r0 contains value to be programmed.
282          * L2 cache is already invalidate by ROM code as part
283          * of MPUSS OFF wakeup path.
284          */
285         ldr     r2, =OMAP44XX_L2CACHE_BASE
286         ldr     r0, [r2, #L2X0_CTRL]
287         and     r0, #0x0f
288         cmp     r0, #1
289         beq     skip_l2en                       @ Skip if already enabled
290         ldr     r3, =OMAP44XX_SAR_RAM_BASE
291         ldr     r1, [r3, #OMAP_TYPE_OFFSET]
292         cmp     r1, #0x1                        @ Check for HS device
293         bne     set_gp_por
294         ldr     r0, =OMAP4_PPA_L2_POR_INDEX
295         ldr     r1, =OMAP44XX_SAR_RAM_BASE
296         ldr     r4, [r1, #L2X0_PREFETCH_CTRL_OFFSET]
297         adr     r1, ppa_por_params_offset
298         ldr     r3, [r1]
299         add     r3, r3, r1                      @ Pointer to 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
307 set_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
312 set_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
320 skip_l2en:
321 #endif
322 
323         b       cpu_resume                      @ Jump to generic resume
324 ppa_por_params_offset:
325         .long   ppa_por_params - .
326 ENDPROC(omap4_cpu_resume)
327 #endif  /* CONFIG_ARCH_OMAP4 */
328 
329 #endif  /* defined(CONFIG_SMP) && defined(CONFIG_PM) */
330 
331 ENTRY(omap_do_wfi)
332         stmfd   sp!, {lr}
333 #ifdef CONFIG_OMAP_INTERCONNECT_BARRIER
334         /* Drain interconnect write buffers. */
335         bl      omap_interconnect_sync
336 #endif
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}
378 ppa_zero_params_offset:
379         .long   ppa_zero_params - .
380 ENDPROC(omap_do_wfi)
381 
382         .data
383         .align  2
384 ppa_zero_params:
385         .word           0
386 
387 ppa_por_params:
388         .word           1, 0

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php