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