blob: adf599f432d97d6794499cab14ccf4d4d8528474 [file] [log] [blame]
Sandrine Bailleux798140d2014-07-17 16:06:39 +01001/*
2 * Copyright (c) 2013, 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>
Juan Castillob3286c02014-10-20 12:29:58 +010033#include <arm_gic.h>
Juan Castillo75ed3562014-08-12 08:42:28 +010034#include <debug.h>
Sandrine Bailleux798140d2014-07-17 16:06:39 +010035#include <cci400.h>
36#include <errno.h>
37#include <platform.h>
38#include <platform_def.h>
39#include <psci.h>
40#include "juno_def.h"
41#include "juno_private.h"
42#include "scpi.h"
43
44/*******************************************************************************
45 * Private Juno function to program the mailbox for a cpu before it is released
46 * from reset.
47 ******************************************************************************/
48static void juno_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 * Private Juno function which is used to determine if any platform actions
61 * should be performed for the specified affinity instance given its
62 * state. Nothing needs to be done if the 'state' is not off or if this is not
63 * the highest affinity level which will enter the 'state'.
64 ******************************************************************************/
65static int32_t juno_do_plat_actions(uint32_t afflvl, uint32_t state)
66{
67 uint32_t max_phys_off_afflvl;
68
69 assert(afflvl <= MPIDR_AFFLVL1);
70
71 if (state != PSCI_STATE_OFF)
72 return -EAGAIN;
73
74 /*
75 * Find the highest affinity level which will be suspended and postpone
76 * all the platform specific actions until that level is hit.
77 */
78 max_phys_off_afflvl = psci_get_max_phys_off_afflvl();
79 assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
80 assert(psci_get_suspend_afflvl() >= max_phys_off_afflvl);
81 if (afflvl != max_phys_off_afflvl)
82 return -EAGAIN;
83
84 return 0;
85}
86
87/*******************************************************************************
88 * Juno handler called when an affinity instance is about to be turned on. The
89 * level and mpidr determine the affinity instance.
90 ******************************************************************************/
Achin Gupta89b70cd2014-08-18 14:40:27 +010091int32_t juno_affinst_on(uint64_t mpidr,
92 uint64_t sec_entrypoint,
93 uint64_t ns_entrypoint,
94 uint32_t afflvl,
95 uint32_t state)
Sandrine Bailleux798140d2014-07-17 16:06:39 +010096{
97 /*
98 * SCP takes care of powering up higher affinity levels so we
99 * only need to care about level 0
100 */
101 if (afflvl != MPIDR_AFFLVL0)
102 return PSCI_E_SUCCESS;
103
104 /*
105 * Setup mailbox with address for CPU entrypoint when it next powers up
106 */
107 juno_program_mailbox(mpidr, sec_entrypoint);
108
109 scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on,
110 scpi_power_on);
111
112 return PSCI_E_SUCCESS;
113}
114
115/*******************************************************************************
116 * Juno handler called when an affinity instance has just been powered on after
117 * being turned off earlier. The level and mpidr determine the affinity
118 * instance. The 'state' arg. allows the platform to decide whether the cluster
119 * was turned off prior to wakeup and do what's necessary to setup it up
120 * correctly.
121 ******************************************************************************/
Achin Gupta89b70cd2014-08-18 14:40:27 +0100122int32_t juno_affinst_on_finish(uint64_t mpidr, uint32_t afflvl, uint32_t state)
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100123{
124 /* Determine if any platform actions need to be executed. */
125 if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
126 return PSCI_E_SUCCESS;
127
128 /*
129 * Perform the common cluster specific operations i.e enable coherency
130 * if this cluster was off.
131 */
132 if (afflvl != MPIDR_AFFLVL0)
133 cci_enable_cluster_coherency(mpidr);
134
135
136 /* Enable the gic cpu interface */
Juan Castillob3286c02014-10-20 12:29:58 +0100137 arm_gic_cpuif_setup();
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100138
139 /* Juno todo: Is this setup only needed after a cold boot? */
Juan Castillob3286c02014-10-20 12:29:58 +0100140 arm_gic_pcpu_distif_setup();
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100141
142 /* Clear the mailbox for this cpu. */
143 juno_program_mailbox(mpidr, 0);
144
145 return PSCI_E_SUCCESS;
146}
147
148/*******************************************************************************
Achin Gupta89b70cd2014-08-18 14:40:27 +0100149 * Common function called while turning a cpu off or suspending it. It is called
150 * from juno_off() or juno_suspend() when these functions in turn are called for
151 * the highest affinity level which will be powered down. It performs the
152 * actions common to the OFF and SUSPEND calls.
153 ******************************************************************************/
154static int32_t juno_power_down_common(uint32_t afflvl)
155{
156 uint32_t cluster_state = scpi_power_on;
157
158 /* Prevent interrupts from spuriously waking up this cpu */
Juan Castillob3286c02014-10-20 12:29:58 +0100159 arm_gic_cpuif_deactivate();
Achin Gupta89b70cd2014-08-18 14:40:27 +0100160
161 /* Cluster is to be turned off, so disable coherency */
162 if (afflvl > MPIDR_AFFLVL0) {
163 cci_disable_cluster_coherency(read_mpidr_el1());
164 cluster_state = scpi_power_off;
165 }
166
167 /*
168 * Ask the SCP to power down the appropriate components depending upon
169 * their state.
170 */
171 scpi_set_css_power_state(read_mpidr_el1(),
172 scpi_power_off,
173 cluster_state,
174 scpi_power_on);
175
176 return PSCI_E_SUCCESS;
177}
178
179/*******************************************************************************
180 * Handler called when an affinity instance is about to be turned off. The
181 * level and mpidr determine the affinity instance. The 'state' arg. allows the
182 * platform to decide whether the cluster is being turned off and take
183 * appropriate actions.
184 *
185 * CAUTION: There is no guarantee that caches will remain turned on across calls
186 * to this function as each affinity level is dealt with. So do not write & read
187 * global variables across calls. It will be wise to do flush a write to the
188 * global to prevent unpredictable results.
189 ******************************************************************************/
190static int32_t juno_affinst_off(uint64_t mpidr, uint32_t afflvl, uint32_t state)
191{
192 /* Determine if any platform actions need to be executed */
193 if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
194 return PSCI_E_SUCCESS;
195
196 return juno_power_down_common(afflvl);
197}
198
199/*******************************************************************************
200 * Handler called when an affinity instance is about to be suspended. The
201 * level and mpidr determine the affinity instance. The 'state' arg. allows the
202 * platform to decide whether the cluster is being turned off and take apt
203 * actions. The 'sec_entrypoint' determines the address in BL3-1 from where
204 * execution should resume.
205 *
206 * CAUTION: There is no guarantee that caches will remain turned on across calls
207 * to this function as each affinity level is dealt with. So do not write & read
208 * global variables across calls. It will be wise to do flush a write to the
209 * global to prevent unpredictable results.
210 ******************************************************************************/
211static int32_t juno_affinst_suspend(uint64_t mpidr,
212 uint64_t sec_entrypoint,
213 uint64_t ns_entrypoint,
214 uint32_t afflvl,
215 uint32_t state)
216{
217 /* Determine if any platform actions need to be executed */
218 if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
219 return PSCI_E_SUCCESS;
220
221 /*
222 * Setup mailbox with address for CPU entrypoint when it next powers up.
223 */
224 juno_program_mailbox(mpidr, sec_entrypoint);
225
226 return juno_power_down_common(afflvl);
227}
228
229/*******************************************************************************
230 * Juno handler called when an affinity instance has just been powered on after
231 * having been suspended earlier. The level and mpidr determine the affinity
232 * instance.
233 * TODO: At the moment we reuse the on finisher and reinitialize the secure
234 * context. Need to implement a separate suspend finisher.
235 ******************************************************************************/
236static int32_t juno_affinst_suspend_finish(uint64_t mpidr,
237 uint32_t afflvl,
238 uint32_t state)
239{
240 return juno_affinst_on_finish(mpidr, afflvl, state);
241}
242
243/*******************************************************************************
Juan Castillo75ed3562014-08-12 08:42:28 +0100244 * Juno handlers to shutdown/reboot the system
245 ******************************************************************************/
246static void __dead2 juno_system_off(void)
247{
248 uint32_t response;
249
250 /* Send the power down request to the SCP */
251 response = scpi_sys_power_state(scpi_system_shutdown);
252
253 if (response != SCP_OK) {
254 ERROR("Juno System Off: SCP error %u.\n", response);
255 panic();
256 }
257 wfi();
258 ERROR("Juno System Off: operation not handled.\n");
259 panic();
260}
261
262static void __dead2 juno_system_reset(void)
263{
264 uint32_t response;
265
266 /* Send the system reset request to the SCP */
267 response = scpi_sys_power_state(scpi_system_reboot);
268
269 if (response != SCP_OK) {
270 ERROR("Juno System Reset: SCP error %u.\n", response);
271 panic();
272 }
273 wfi();
274 ERROR("Juno System Reset: operation not handled.\n");
275 panic();
276}
277
278/*******************************************************************************
Vikram Kanigiri58a185e2014-07-01 15:34:11 +0100279 * Handler called when an affinity instance is about to enter standby.
280 ******************************************************************************/
281int32_t juno_affinst_standby(unsigned int power_state)
282{
283 unsigned int target_afflvl;
284 unsigned int scr;
285
286 /* Sanity check the requested state */
287 target_afflvl = psci_get_pstate_afflvl(power_state);
288
289 /*
290 * It's possible to enter standby only on affinity level 0 i.e. a cpu
291 * on the Juno. Ignore any other affinity level.
292 */
293 if (target_afflvl != MPIDR_AFFLVL0)
294 return PSCI_E_INVALID_PARAMS;
295
296 scr = read_scr_el3();
297 /* Enable PhysicalIRQ bit for NS world to wake the CPU */
298 write_scr_el3(scr | SCR_IRQ_BIT);
299 isb();
300 dsb();
301 wfi();
302
303 /*
304 * Restore SCR to the original value, synchronisation of scr_el3 is
305 * done by eret while el3_exit to save some execution cycles.
306 */
307 write_scr_el3(scr);
308
309 return PSCI_E_SUCCESS;
310}
311
312/*******************************************************************************
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100313 * Export the platform handlers to enable psci to invoke them
314 ******************************************************************************/
315static const plat_pm_ops_t juno_ops = {
Achin Gupta89b70cd2014-08-18 14:40:27 +0100316 .affinst_on = juno_affinst_on,
317 .affinst_on_finish = juno_affinst_on_finish,
318 .affinst_off = juno_affinst_off,
Vikram Kanigiri58a185e2014-07-01 15:34:11 +0100319 .affinst_standby = juno_affinst_standby,
Achin Gupta89b70cd2014-08-18 14:40:27 +0100320 .affinst_suspend = juno_affinst_suspend,
Juan Castillo75ed3562014-08-12 08:42:28 +0100321 .affinst_suspend_finish = juno_affinst_suspend_finish,
322 .system_off = juno_system_off,
323 .system_reset = juno_system_reset
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100324};
325
326/*******************************************************************************
327 * Export the platform specific power ops.
328 ******************************************************************************/
329int32_t platform_setup_pm(const plat_pm_ops_t **plat_ops)
330{
331 *plat_ops = &juno_ops;
332 return 0;
333}