xref: /arm-trusted-firmware/lib/psci/aarch32/psci_helpers.S (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu/*
2*91f16700Schasinglulu * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu *
4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu */
6*91f16700Schasinglulu
7*91f16700Schasinglulu#include <asm_macros.S>
8*91f16700Schasinglulu#include <lib/psci/psci.h>
9*91f16700Schasinglulu#include <platform_def.h>
10*91f16700Schasinglulu
11*91f16700Schasinglulu	.globl	psci_do_pwrdown_cache_maintenance
12*91f16700Schasinglulu	.globl	psci_do_pwrup_cache_maintenance
13*91f16700Schasinglulu	.globl	psci_power_down_wfi
14*91f16700Schasinglulu
15*91f16700Schasinglulu/* -----------------------------------------------------------------------
16*91f16700Schasinglulu * void psci_do_pwrdown_cache_maintenance(unsigned int power level);
17*91f16700Schasinglulu *
18*91f16700Schasinglulu * This function performs cache maintenance for the specified power
19*91f16700Schasinglulu * level. The levels of cache affected are determined by the power
20*91f16700Schasinglulu * level which is passed as the argument i.e. level 0 results
21*91f16700Schasinglulu * in a flush of the L1 cache. Both the L1 and L2 caches are flushed
22*91f16700Schasinglulu * for a higher power level.
23*91f16700Schasinglulu *
24*91f16700Schasinglulu * Additionally, this function also ensures that stack memory is correctly
25*91f16700Schasinglulu * flushed out to avoid coherency issues due to a change in its memory
26*91f16700Schasinglulu * attributes after the data cache is disabled.
27*91f16700Schasinglulu * -----------------------------------------------------------------------
28*91f16700Schasinglulu */
29*91f16700Schasinglulufunc psci_do_pwrdown_cache_maintenance
30*91f16700Schasinglulu	push	{r4, lr}
31*91f16700Schasinglulu
32*91f16700Schasinglulu	/* ----------------------------------------------
33*91f16700Schasinglulu	 * Turn OFF cache and do stack maintenance
34*91f16700Schasinglulu	 * prior to cpu operations . This sequence is
35*91f16700Schasinglulu	 * different from AArch64 because in AArch32 the
36*91f16700Schasinglulu	 * assembler routines for cpu operations utilize
37*91f16700Schasinglulu	 * the stack whereas in AArch64 it doesn't.
38*91f16700Schasinglulu	 * ----------------------------------------------
39*91f16700Schasinglulu	 */
40*91f16700Schasinglulu	mov	r4, r0
41*91f16700Schasinglulu	bl	do_stack_maintenance
42*91f16700Schasinglulu
43*91f16700Schasinglulu	/* ---------------------------------------------
44*91f16700Schasinglulu	 * Invoke CPU-specifc power down operations for
45*91f16700Schasinglulu	 * the appropriate level
46*91f16700Schasinglulu	 * ---------------------------------------------
47*91f16700Schasinglulu	 */
48*91f16700Schasinglulu	mov	r0, r4
49*91f16700Schasinglulu	pop	{r4, lr}
50*91f16700Schasinglulu	b	prepare_cpu_pwr_dwn
51*91f16700Schasingluluendfunc psci_do_pwrdown_cache_maintenance
52*91f16700Schasinglulu
53*91f16700Schasinglulu
54*91f16700Schasinglulu/* -----------------------------------------------------------------------
55*91f16700Schasinglulu * void psci_do_pwrup_cache_maintenance(void);
56*91f16700Schasinglulu *
57*91f16700Schasinglulu * This function performs cache maintenance after this cpu is powered up.
58*91f16700Schasinglulu * Currently, this involves managing the used stack memory before turning
59*91f16700Schasinglulu * on the data cache.
60*91f16700Schasinglulu * -----------------------------------------------------------------------
61*91f16700Schasinglulu */
62*91f16700Schasinglulufunc psci_do_pwrup_cache_maintenance
63*91f16700Schasinglulu	/* r12 is pushed to meet the 8 byte stack alignment requirement */
64*91f16700Schasinglulu	push	{r12, lr}
65*91f16700Schasinglulu
66*91f16700Schasinglulu	/* ---------------------------------------------
67*91f16700Schasinglulu	 * Ensure any inflight stack writes have made it
68*91f16700Schasinglulu	 * to main memory.
69*91f16700Schasinglulu	 * ---------------------------------------------
70*91f16700Schasinglulu	 */
71*91f16700Schasinglulu	dmb	st
72*91f16700Schasinglulu
73*91f16700Schasinglulu	/* ---------------------------------------------
74*91f16700Schasinglulu	 * Calculate and store the size of the used
75*91f16700Schasinglulu	 * stack memory in r1. Calculate and store the
76*91f16700Schasinglulu	 * stack base address in r0.
77*91f16700Schasinglulu	 * ---------------------------------------------
78*91f16700Schasinglulu	 */
79*91f16700Schasinglulu	bl	plat_get_my_stack
80*91f16700Schasinglulu	mov	r1, sp
81*91f16700Schasinglulu	sub	r1, r0, r1
82*91f16700Schasinglulu	mov	r0, sp
83*91f16700Schasinglulu	bl	inv_dcache_range
84*91f16700Schasinglulu
85*91f16700Schasinglulu	/* ---------------------------------------------
86*91f16700Schasinglulu	 * Enable the data cache.
87*91f16700Schasinglulu	 * ---------------------------------------------
88*91f16700Schasinglulu	 */
89*91f16700Schasinglulu	ldcopr	r0, SCTLR
90*91f16700Schasinglulu	orr	r0, r0, #SCTLR_C_BIT
91*91f16700Schasinglulu	stcopr	r0, SCTLR
92*91f16700Schasinglulu	isb
93*91f16700Schasinglulu
94*91f16700Schasinglulu	pop	{r12, pc}
95*91f16700Schasingluluendfunc psci_do_pwrup_cache_maintenance
96*91f16700Schasinglulu
97*91f16700Schasinglulu	/* ---------------------------------------------
98*91f16700Schasinglulu	 * void do_stack_maintenance(void)
99*91f16700Schasinglulu	 * Do stack maintenance by flushing the used
100*91f16700Schasinglulu	 * stack to the main memory and invalidating the
101*91f16700Schasinglulu	 * remainder.
102*91f16700Schasinglulu	 * ---------------------------------------------
103*91f16700Schasinglulu	 */
104*91f16700Schasinglulufunc do_stack_maintenance
105*91f16700Schasinglulu	push	{r4, lr}
106*91f16700Schasinglulu	bl	plat_get_my_stack
107*91f16700Schasinglulu
108*91f16700Schasinglulu	/* Turn off the D-cache */
109*91f16700Schasinglulu	ldcopr	r1, SCTLR
110*91f16700Schasinglulu	bic	r1, #SCTLR_C_BIT
111*91f16700Schasinglulu	stcopr	r1, SCTLR
112*91f16700Schasinglulu	isb
113*91f16700Schasinglulu
114*91f16700Schasinglulu	/* ---------------------------------------------
115*91f16700Schasinglulu	 * Calculate and store the size of the used
116*91f16700Schasinglulu	 * stack memory in r1.
117*91f16700Schasinglulu	 * ---------------------------------------------
118*91f16700Schasinglulu	 */
119*91f16700Schasinglulu	mov	r4, r0
120*91f16700Schasinglulu	mov	r1, sp
121*91f16700Schasinglulu	sub	r1, r0, r1
122*91f16700Schasinglulu	mov	r0, sp
123*91f16700Schasinglulu	bl	flush_dcache_range
124*91f16700Schasinglulu
125*91f16700Schasinglulu	/* ---------------------------------------------
126*91f16700Schasinglulu	 * Calculate and store the size of the unused
127*91f16700Schasinglulu	 * stack memory in r1. Calculate and store the
128*91f16700Schasinglulu	 * stack base address in r0.
129*91f16700Schasinglulu	 * ---------------------------------------------
130*91f16700Schasinglulu	 */
131*91f16700Schasinglulu	sub	r0, r4, #PLATFORM_STACK_SIZE
132*91f16700Schasinglulu	sub	r1, sp, r0
133*91f16700Schasinglulu	bl	inv_dcache_range
134*91f16700Schasinglulu
135*91f16700Schasinglulu	pop	{r4, pc}
136*91f16700Schasingluluendfunc do_stack_maintenance
137*91f16700Schasinglulu
138*91f16700Schasinglulu/* -----------------------------------------------------------------------
139*91f16700Schasinglulu * This function is called to indicate to the power controller that it
140*91f16700Schasinglulu * is safe to power down this cpu. It should not exit the wfi and will
141*91f16700Schasinglulu * be released from reset upon power up.
142*91f16700Schasinglulu * -----------------------------------------------------------------------
143*91f16700Schasinglulu */
144*91f16700Schasinglulufunc psci_power_down_wfi
145*91f16700Schasinglulu	dsb	sy		// ensure write buffer empty
146*91f16700Schasinglulu1:
147*91f16700Schasinglulu	wfi
148*91f16700Schasinglulu	b	1b
149*91f16700Schasingluluendfunc psci_power_down_wfi
150