xref: /rk3399_ARM-atf/plat/arm/css/common/css_pm.c (revision 4731e8f0f1f43386b8280db81f5db588ae7b4ccc)
1 /*
2  * Copyright (c) 2015, 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 <assert.h>
32 #include <arch_helpers.h>
33 #include <arm_gic.h>
34 #include <cci.h>
35 #include <css_def.h>
36 #include <debug.h>
37 #include <errno.h>
38 #include <plat_arm.h>
39 #include <platform.h>
40 #include <platform_def.h>
41 #include <psci.h>
42 #include "css_scpi.h"
43 
44 /*******************************************************************************
45  * Private function to program the mailbox for a cpu before it is released
46  * from reset.
47  ******************************************************************************/
48 static void css_program_mailbox(uint64_t mpidr, uint64_t address)
49 {
50 	uint64_t linear_id;
51 	uint64_t mbox;
52 
53 	linear_id = platform_get_core_pos(mpidr);
54 	mbox = TRUSTED_MAILBOXES_BASE +	(linear_id << TRUSTED_MAILBOX_SHIFT);
55 	*((uint64_t *) mbox) = address;
56 	flush_dcache_range(mbox, sizeof(mbox));
57 }
58 
59 /*******************************************************************************
60  * Handler called when an affinity instance is about to be turned on. The
61  * level and mpidr determine the affinity instance.
62  ******************************************************************************/
63 int32_t css_affinst_on(uint64_t mpidr,
64 			uint64_t sec_entrypoint,
65 			uint32_t afflvl,
66 			uint32_t state)
67 {
68 	/*
69 	 * SCP takes care of powering up higher affinity levels so we
70 	 * only need to care about level 0
71 	 */
72 	if (afflvl != MPIDR_AFFLVL0)
73 		return PSCI_E_SUCCESS;
74 
75 	/*
76 	 * Setup mailbox with address for CPU entrypoint when it next powers up
77 	 */
78 	css_program_mailbox(mpidr, sec_entrypoint);
79 
80 	scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on,
81 				 scpi_power_on);
82 
83 	return PSCI_E_SUCCESS;
84 }
85 
86 /*******************************************************************************
87  * Handler called when an affinity instance has just been powered on after
88  * being turned off earlier. The level and mpidr determine the affinity
89  * instance. The 'state' arg. allows the platform to decide whether the cluster
90  * was turned off prior to wakeup and do what's necessary to setup it up
91  * correctly.
92  ******************************************************************************/
93 void css_affinst_on_finish(uint32_t afflvl, uint32_t state)
94 {
95 	unsigned long mpidr;
96 
97 	/* Determine if any platform actions need to be executed. */
98 	if (arm_do_affinst_actions(afflvl, state) == -EAGAIN)
99 		return;
100 
101 	/* Get the mpidr for this cpu */
102 	mpidr = read_mpidr_el1();
103 
104 	/*
105 	 * Perform the common cluster specific operations i.e enable coherency
106 	 * if this cluster was off.
107 	 */
108 	if (afflvl != MPIDR_AFFLVL0)
109 		cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
110 
111 	/* Enable the gic cpu interface */
112 	arm_gic_cpuif_setup();
113 
114 	/* todo: Is this setup only needed after a cold boot? */
115 	arm_gic_pcpu_distif_setup();
116 
117 	/* Clear the mailbox for this cpu. */
118 	css_program_mailbox(mpidr, 0);
119 }
120 
121 /*******************************************************************************
122  * Common function called while turning a cpu off or suspending it. It is called
123  * from css_off() or css_suspend() when these functions in turn are called for
124  * the highest affinity level which will be powered down. It performs the
125  * actions common to the OFF and SUSPEND calls.
126  ******************************************************************************/
127 static void css_power_down_common(uint32_t afflvl)
128 {
129 	uint32_t cluster_state = scpi_power_on;
130 
131 	/* Prevent interrupts from spuriously waking up this cpu */
132 	arm_gic_cpuif_deactivate();
133 
134 	/* Cluster is to be turned off, so disable coherency */
135 	if (afflvl > MPIDR_AFFLVL0) {
136 		cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
137 		cluster_state = scpi_power_off;
138 	}
139 
140 	/*
141 	 * Ask the SCP to power down the appropriate components depending upon
142 	 * their state.
143 	 */
144 	scpi_set_css_power_state(read_mpidr_el1(),
145 				 scpi_power_off,
146 				 cluster_state,
147 				 scpi_power_on);
148 }
149 
150 /*******************************************************************************
151  * Handler called when an affinity instance is about to be turned off. The
152  * level and mpidr determine the affinity instance. The 'state' arg. allows the
153  * platform to decide whether the cluster is being turned off and take
154  * appropriate actions.
155  *
156  * CAUTION: There is no guarantee that caches will remain turned on across calls
157  * to this function as each affinity level is dealt with. So do not write & read
158  * global variables across calls. It will be wise to do flush a write to the
159  * global to prevent unpredictable results.
160  ******************************************************************************/
161 static void css_affinst_off(uint32_t afflvl, uint32_t state)
162 {
163 	/* Determine if any platform actions need to be executed */
164 	if (arm_do_affinst_actions(afflvl, state) == -EAGAIN)
165 		return;
166 
167 	css_power_down_common(afflvl);
168 }
169 
170 /*******************************************************************************
171  * Handler called when an affinity instance is about to be suspended. The
172  * level and mpidr determine the affinity instance. The 'state' arg. allows the
173  * platform to decide whether the cluster is being turned off and take apt
174  * actions. The 'sec_entrypoint' determines the address in BL3-1 from where
175  * execution should resume.
176  *
177  * CAUTION: There is no guarantee that caches will remain turned on across calls
178  * to this function as each affinity level is dealt with. So do not write & read
179  * global variables across calls. It will be wise to do flush a write to the
180  * global to prevent unpredictable results.
181  ******************************************************************************/
182 static void css_affinst_suspend(uint64_t sec_entrypoint,
183 				    uint32_t afflvl,
184 				    uint32_t state)
185 {
186 	/* Determine if any platform actions need to be executed */
187 	if (arm_do_affinst_actions(afflvl, state) == -EAGAIN)
188 		return;
189 
190 	/*
191 	 * Setup mailbox with address for CPU entrypoint when it next powers up.
192 	 */
193 	css_program_mailbox(read_mpidr_el1(), sec_entrypoint);
194 
195 	css_power_down_common(afflvl);
196 }
197 
198 /*******************************************************************************
199  * Handler called when an affinity instance has just been powered on after
200  * having been suspended earlier. The level and mpidr determine the affinity
201  * instance.
202  * TODO: At the moment we reuse the on finisher and reinitialize the secure
203  * context. Need to implement a separate suspend finisher.
204  ******************************************************************************/
205 static void css_affinst_suspend_finish(uint32_t afflvl,
206 					   uint32_t state)
207 {
208 	css_affinst_on_finish(afflvl, state);
209 }
210 
211 /*******************************************************************************
212  * Handlers to shutdown/reboot the system
213  ******************************************************************************/
214 static void __dead2 css_system_off(void)
215 {
216 	uint32_t response;
217 
218 	/* Send the power down request to the SCP */
219 	response = scpi_sys_power_state(scpi_system_shutdown);
220 
221 	if (response != SCP_OK) {
222 		ERROR("CSS System Off: SCP error %u.\n", response);
223 		panic();
224 	}
225 	wfi();
226 	ERROR("CSS System Off: operation not handled.\n");
227 	panic();
228 }
229 
230 static void __dead2 css_system_reset(void)
231 {
232 	uint32_t response;
233 
234 	/* Send the system reset request to the SCP */
235 	response = scpi_sys_power_state(scpi_system_reboot);
236 
237 	if (response != SCP_OK) {
238 		ERROR("CSS System Reset: SCP error %u.\n", response);
239 		panic();
240 	}
241 	wfi();
242 	ERROR("CSS System Reset: operation not handled.\n");
243 	panic();
244 }
245 
246 /*******************************************************************************
247  * Handler called when an affinity instance is about to enter standby.
248  ******************************************************************************/
249 void css_affinst_standby(unsigned int power_state)
250 {
251 	unsigned int scr;
252 
253 	scr = read_scr_el3();
254 	/* Enable PhysicalIRQ bit for NS world to wake the CPU */
255 	write_scr_el3(scr | SCR_IRQ_BIT);
256 	isb();
257 	dsb();
258 	wfi();
259 
260 	/*
261 	 * Restore SCR to the original value, synchronisation of scr_el3 is
262 	 * done by eret while el3_exit to save some execution cycles.
263 	 */
264 	write_scr_el3(scr);
265 }
266 
267 /*******************************************************************************
268  * Export the platform handlers to enable psci to invoke them
269  ******************************************************************************/
270 static const plat_pm_ops_t css_ops = {
271 	.affinst_on		= css_affinst_on,
272 	.affinst_on_finish	= css_affinst_on_finish,
273 	.affinst_off		= css_affinst_off,
274 	.affinst_standby	= css_affinst_standby,
275 	.affinst_suspend	= css_affinst_suspend,
276 	.affinst_suspend_finish	= css_affinst_suspend_finish,
277 	.system_off		= css_system_off,
278 	.system_reset		= css_system_reset,
279 	.validate_power_state	= arm_validate_power_state
280 };
281 
282 /*******************************************************************************
283  * Export the platform specific power ops.
284  ******************************************************************************/
285 int32_t platform_setup_pm(const plat_pm_ops_t **plat_ops)
286 {
287 	*plat_ops = &css_ops;
288 	return 0;
289 }
290