blob: a3907061bbc6a08eb2e140fbf75ad22e86591d23 [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,
Achin Gupta89b70cd2014-08-18 14:40:27 +010093 uint32_t afflvl,
94 uint32_t state)
Sandrine Bailleux798140d2014-07-17 16:06:39 +010095{
96 /*
97 * SCP takes care of powering up higher affinity levels so we
98 * only need to care about level 0
99 */
100 if (afflvl != MPIDR_AFFLVL0)
101 return PSCI_E_SUCCESS;
102
103 /*
104 * Setup mailbox with address for CPU entrypoint when it next powers up
105 */
106 juno_program_mailbox(mpidr, sec_entrypoint);
107
108 scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on,
109 scpi_power_on);
110
111 return PSCI_E_SUCCESS;
112}
113
114/*******************************************************************************
115 * Juno handler called when an affinity instance has just been powered on after
116 * being turned off earlier. The level and mpidr determine the affinity
117 * instance. The 'state' arg. allows the platform to decide whether the cluster
118 * was turned off prior to wakeup and do what's necessary to setup it up
119 * correctly.
120 ******************************************************************************/
Soby Mathewffb4ab12014-09-26 15:08:52 +0100121int32_t juno_affinst_on_finish(uint32_t afflvl, uint32_t state)
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100122{
Soby Mathewffb4ab12014-09-26 15:08:52 +0100123 unsigned long mpidr;
124
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100125 /* Determine if any platform actions need to be executed. */
126 if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
127 return PSCI_E_SUCCESS;
128
Soby Mathewffb4ab12014-09-26 15:08:52 +0100129 /* Get the mpidr for this cpu */
130 mpidr = read_mpidr_el1();
131
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100132 /*
133 * Perform the common cluster specific operations i.e enable coherency
134 * if this cluster was off.
135 */
136 if (afflvl != MPIDR_AFFLVL0)
137 cci_enable_cluster_coherency(mpidr);
138
139
140 /* Enable the gic cpu interface */
Juan Castillob3286c02014-10-20 12:29:58 +0100141 arm_gic_cpuif_setup();
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100142
143 /* Juno todo: Is this setup only needed after a cold boot? */
Juan Castillob3286c02014-10-20 12:29:58 +0100144 arm_gic_pcpu_distif_setup();
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100145
146 /* Clear the mailbox for this cpu. */
147 juno_program_mailbox(mpidr, 0);
148
149 return PSCI_E_SUCCESS;
150}
151
152/*******************************************************************************
Achin Gupta89b70cd2014-08-18 14:40:27 +0100153 * Common function called while turning a cpu off or suspending it. It is called
154 * from juno_off() or juno_suspend() when these functions in turn are called for
155 * the highest affinity level which will be powered down. It performs the
156 * actions common to the OFF and SUSPEND calls.
157 ******************************************************************************/
158static int32_t juno_power_down_common(uint32_t afflvl)
159{
160 uint32_t cluster_state = scpi_power_on;
161
162 /* Prevent interrupts from spuriously waking up this cpu */
Juan Castillob3286c02014-10-20 12:29:58 +0100163 arm_gic_cpuif_deactivate();
Achin Gupta89b70cd2014-08-18 14:40:27 +0100164
165 /* Cluster is to be turned off, so disable coherency */
166 if (afflvl > MPIDR_AFFLVL0) {
167 cci_disable_cluster_coherency(read_mpidr_el1());
168 cluster_state = scpi_power_off;
169 }
170
171 /*
172 * Ask the SCP to power down the appropriate components depending upon
173 * their state.
174 */
175 scpi_set_css_power_state(read_mpidr_el1(),
176 scpi_power_off,
177 cluster_state,
178 scpi_power_on);
179
180 return PSCI_E_SUCCESS;
181}
182
183/*******************************************************************************
184 * Handler called when an affinity instance is about to be turned off. The
185 * level and mpidr determine the affinity instance. The 'state' arg. allows the
186 * platform to decide whether the cluster is being turned off and take
187 * appropriate actions.
188 *
189 * CAUTION: There is no guarantee that caches will remain turned on across calls
190 * to this function as each affinity level is dealt with. So do not write & read
191 * global variables across calls. It will be wise to do flush a write to the
192 * global to prevent unpredictable results.
193 ******************************************************************************/
Soby Mathewffb4ab12014-09-26 15:08:52 +0100194static int32_t juno_affinst_off(uint32_t afflvl, uint32_t state)
Achin Gupta89b70cd2014-08-18 14:40:27 +0100195{
196 /* Determine if any platform actions need to be executed */
197 if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
198 return PSCI_E_SUCCESS;
199
200 return juno_power_down_common(afflvl);
201}
202
203/*******************************************************************************
204 * Handler called when an affinity instance is about to be suspended. The
205 * level and mpidr determine the affinity instance. The 'state' arg. allows the
206 * platform to decide whether the cluster is being turned off and take apt
207 * actions. The 'sec_entrypoint' determines the address in BL3-1 from where
208 * execution should resume.
209 *
210 * CAUTION: There is no guarantee that caches will remain turned on across calls
211 * to this function as each affinity level is dealt with. So do not write & read
212 * global variables across calls. It will be wise to do flush a write to the
213 * global to prevent unpredictable results.
214 ******************************************************************************/
Soby Mathewffb4ab12014-09-26 15:08:52 +0100215static int32_t juno_affinst_suspend(uint64_t sec_entrypoint,
Achin Gupta89b70cd2014-08-18 14:40:27 +0100216 uint32_t afflvl,
217 uint32_t state)
218{
219 /* Determine if any platform actions need to be executed */
220 if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
221 return PSCI_E_SUCCESS;
222
223 /*
224 * Setup mailbox with address for CPU entrypoint when it next powers up.
225 */
Soby Mathewffb4ab12014-09-26 15:08:52 +0100226 juno_program_mailbox(read_mpidr_el1(), sec_entrypoint);
Achin Gupta89b70cd2014-08-18 14:40:27 +0100227
228 return juno_power_down_common(afflvl);
229}
230
231/*******************************************************************************
232 * Juno handler called when an affinity instance has just been powered on after
233 * having been suspended earlier. The level and mpidr determine the affinity
234 * instance.
235 * TODO: At the moment we reuse the on finisher and reinitialize the secure
236 * context. Need to implement a separate suspend finisher.
237 ******************************************************************************/
Soby Mathewffb4ab12014-09-26 15:08:52 +0100238static int32_t juno_affinst_suspend_finish(uint32_t afflvl,
Achin Gupta89b70cd2014-08-18 14:40:27 +0100239 uint32_t state)
240{
Soby Mathewffb4ab12014-09-26 15:08:52 +0100241 return juno_affinst_on_finish(afflvl, state);
Achin Gupta89b70cd2014-08-18 14:40:27 +0100242}
243
244/*******************************************************************************
Juan Castillo75ed3562014-08-12 08:42:28 +0100245 * Juno handlers to shutdown/reboot the system
246 ******************************************************************************/
247static void __dead2 juno_system_off(void)
248{
249 uint32_t response;
250
251 /* Send the power down request to the SCP */
252 response = scpi_sys_power_state(scpi_system_shutdown);
253
254 if (response != SCP_OK) {
255 ERROR("Juno System Off: SCP error %u.\n", response);
256 panic();
257 }
258 wfi();
259 ERROR("Juno System Off: operation not handled.\n");
260 panic();
261}
262
263static void __dead2 juno_system_reset(void)
264{
265 uint32_t response;
266
267 /* Send the system reset request to the SCP */
268 response = scpi_sys_power_state(scpi_system_reboot);
269
270 if (response != SCP_OK) {
271 ERROR("Juno System Reset: SCP error %u.\n", response);
272 panic();
273 }
274 wfi();
275 ERROR("Juno System Reset: operation not handled.\n");
276 panic();
277}
278
279/*******************************************************************************
Vikram Kanigiri58a185e2014-07-01 15:34:11 +0100280 * Handler called when an affinity instance is about to enter standby.
281 ******************************************************************************/
282int32_t juno_affinst_standby(unsigned int power_state)
283{
284 unsigned int target_afflvl;
285 unsigned int scr;
286
287 /* Sanity check the requested state */
288 target_afflvl = psci_get_pstate_afflvl(power_state);
289
290 /*
291 * It's possible to enter standby only on affinity level 0 i.e. a cpu
292 * on the Juno. Ignore any other affinity level.
293 */
294 if (target_afflvl != MPIDR_AFFLVL0)
295 return PSCI_E_INVALID_PARAMS;
296
297 scr = read_scr_el3();
298 /* Enable PhysicalIRQ bit for NS world to wake the CPU */
299 write_scr_el3(scr | SCR_IRQ_BIT);
300 isb();
301 dsb();
302 wfi();
303
304 /*
305 * Restore SCR to the original value, synchronisation of scr_el3 is
306 * done by eret while el3_exit to save some execution cycles.
307 */
308 write_scr_el3(scr);
309
310 return PSCI_E_SUCCESS;
311}
312
313/*******************************************************************************
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100314 * Export the platform handlers to enable psci to invoke them
315 ******************************************************************************/
316static const plat_pm_ops_t juno_ops = {
Achin Gupta89b70cd2014-08-18 14:40:27 +0100317 .affinst_on = juno_affinst_on,
318 .affinst_on_finish = juno_affinst_on_finish,
319 .affinst_off = juno_affinst_off,
Vikram Kanigiri58a185e2014-07-01 15:34:11 +0100320 .affinst_standby = juno_affinst_standby,
Achin Gupta89b70cd2014-08-18 14:40:27 +0100321 .affinst_suspend = juno_affinst_suspend,
Juan Castillo75ed3562014-08-12 08:42:28 +0100322 .affinst_suspend_finish = juno_affinst_suspend_finish,
323 .system_off = juno_system_off,
324 .system_reset = juno_system_reset
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100325};
326
327/*******************************************************************************
328 * Export the platform specific power ops.
329 ******************************************************************************/
330int32_t platform_setup_pm(const plat_pm_ops_t **plat_ops)
331{
332 *plat_ops = &juno_ops;
333 return 0;
334}