xref: /rk3399_ARM-atf/lib/psci/aarch32/psci_helpers.S (revision 9f3ee61c904e4b6d2038086718c5ec4237d544a8)
1/*
2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <asm_macros.S>
32#include <platform_def.h>
33#include <psci.h>
34
35	.globl	psci_do_pwrdown_cache_maintenance
36	.globl	psci_do_pwrup_cache_maintenance
37	.globl	psci_power_down_wfi
38
39/* -----------------------------------------------------------------------
40 * void psci_do_pwrdown_cache_maintenance(unsigned int power level);
41 *
42 * This function performs cache maintenance for the specified power
43 * level. The levels of cache affected are determined by the power
44 * level which is passed as the argument i.e. level 0 results
45 * in a flush of the L1 cache. Both the L1 and L2 caches are flushed
46 * for a higher power level.
47 *
48 * Additionally, this function also ensures that stack memory is correctly
49 * flushed out to avoid coherency issues due to a change in its memory
50 * attributes after the data cache is disabled.
51 * -----------------------------------------------------------------------
52 */
53func psci_do_pwrdown_cache_maintenance
54	push	{r4, lr}
55
56	/* ----------------------------------------------
57	 * Turn OFF cache and do stack maintenance
58	 * prior to cpu operations . This sequence is
59	 * different from AArch64 because in AArch32 the
60	 * assembler routines for cpu operations utilize
61	 * the stack whereas in AArch64 it doesn't.
62	 * ----------------------------------------------
63	 */
64	mov	r4, r0
65	bl	do_stack_maintenance
66
67	/* ---------------------------------------------
68	 * Determine how many levels of cache will be
69	 * subject to cache maintenance. Power level
70	 * 0 implies that only the cpu is being powered
71	 * down. Only the L1 data cache needs to be
72	 * flushed to the PoU in this case. For a higher
73	 * power level we are assuming that a flush
74	 * of L1 data and L2 unified cache is enough.
75	 * This information should be provided by the
76	 * platform.
77	 * ---------------------------------------------
78	 */
79	cmp	r4, #PSCI_CPU_PWR_LVL
80	pop	{r4,lr}
81
82	beq	prepare_core_pwr_dwn
83	b	prepare_cluster_pwr_dwn
84endfunc psci_do_pwrdown_cache_maintenance
85
86
87/* -----------------------------------------------------------------------
88 * void psci_do_pwrup_cache_maintenance(void);
89 *
90 * This function performs cache maintenance after this cpu is powered up.
91 * Currently, this involves managing the used stack memory before turning
92 * on the data cache.
93 * -----------------------------------------------------------------------
94 */
95func psci_do_pwrup_cache_maintenance
96	/* r12 is pushed to meet the 8 byte stack alignment requirement */
97	push	{r12, lr}
98
99	/* ---------------------------------------------
100	 * Ensure any inflight stack writes have made it
101	 * to main memory.
102	 * ---------------------------------------------
103	 */
104	dmb	st
105
106	/* ---------------------------------------------
107	 * Calculate and store the size of the used
108	 * stack memory in r1. Calculate and store the
109	 * stack base address in r0.
110	 * ---------------------------------------------
111	 */
112	bl	plat_get_my_stack
113	mov	r1, sp
114	sub	r1, r0, r1
115	mov	r0, sp
116	bl	inv_dcache_range
117
118	/* ---------------------------------------------
119	 * Enable the data cache.
120	 * ---------------------------------------------
121	 */
122	ldcopr	r0, SCTLR
123	orr	r0, r0, #SCTLR_C_BIT
124	stcopr	r0, SCTLR
125	isb
126
127	pop	{r12, pc}
128endfunc psci_do_pwrup_cache_maintenance
129
130	/* ---------------------------------------------
131	 * void do_stack_maintenance(void)
132	 * Do stack maintenance by flushing the used
133	 * stack to the main memory and invalidating the
134	 * remainder.
135	 * ---------------------------------------------
136	 */
137func do_stack_maintenance
138	push	{r4, lr}
139	bl	plat_get_my_stack
140
141	/* Turn off the D-cache */
142	ldcopr	r1, SCTLR
143	bic	r1, #SCTLR_C_BIT
144	stcopr	r1, SCTLR
145	isb
146
147	/* ---------------------------------------------
148	 * Calculate and store the size of the used
149	 * stack memory in r1.
150	 * ---------------------------------------------
151	 */
152	mov	r4, r0
153	mov	r1, sp
154	sub	r1, r0, r1
155	mov	r0, sp
156	bl	flush_dcache_range
157
158	/* ---------------------------------------------
159	 * Calculate and store the size of the unused
160	 * stack memory in r1. Calculate and store the
161	 * stack base address in r0.
162	 * ---------------------------------------------
163	 */
164	sub	r0, r4, #PLATFORM_STACK_SIZE
165	sub	r1, sp, r0
166	bl	inv_dcache_range
167
168	pop	{r4, pc}
169endfunc do_stack_maintenance
170
171/* -----------------------------------------------------------------------
172 * This function is called to indicate to the power controller that it
173 * is safe to power down this cpu. It should not exit the wfi and will
174 * be released from reset upon power up.
175 * -----------------------------------------------------------------------
176 */
177func psci_power_down_wfi
178	dsb	sy		// ensure write buffer empty
179	wfi
180	bl	plat_panic_handler
181endfunc psci_power_down_wfi
182