blob: ec7b89f278d99bc3cb6cf79b26dd4867d0039941 [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Dan Handleye83b0ca2014-01-14 18:17:09 +00002 * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
Achin Gupta4f6ad662013-10-25 09:08:21 +01003 *
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 <stdio.h>
32#include <string.h>
33#include <assert.h>
Achin Gupta0a9f7472014-02-09 17:48:12 +000034#include <debug.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010035#include <arch_helpers.h>
36#include <console.h>
37#include <platform.h>
38#include <psci.h>
Achin Guptaef7a28c2014-02-01 08:59:56 +000039#include <context_mgmt.h>
Dan Handley714a0d22014-04-09 13:13:04 +010040#include "psci_private.h"
Achin Gupta4f6ad662013-10-25 09:08:21 +010041
42typedef int (*afflvl_suspend_handler)(unsigned long,
43 aff_map_node *,
44 unsigned long,
45 unsigned long,
46 unsigned int);
47
48/*******************************************************************************
Vikram Kanigirif100f412014-04-01 19:26:26 +010049 * This function sets the power state of the current cpu while
50 * powering down during a cpu_suspend call
Achin Guptaa45e3972013-12-05 15:10:48 +000051 ******************************************************************************/
Vikram Kanigirif100f412014-04-01 19:26:26 +010052void psci_set_suspend_power_state(aff_map_node *node, unsigned int power_state)
Achin Guptaa45e3972013-12-05 15:10:48 +000053{
54 /*
55 * Check that nobody else is calling this function on our behalf &
56 * this information is being set only in the cpu node
57 */
58 assert(node->mpidr == (read_mpidr() & MPIDR_AFFINITY_MASK));
59 assert(node->level == MPIDR_AFFLVL0);
60
Vikram Kanigirif100f412014-04-01 19:26:26 +010061 /* Save PSCI power state parameter for the core in suspend context */
62 psci_suspend_context[node->data].power_state = power_state;
63
Achin Guptaa45e3972013-12-05 15:10:48 +000064 /*
Vikram Kanigirif100f412014-04-01 19:26:26 +010065 * Flush the suspend data to PoC since it will be accessed while
66 * returning back from suspend with the caches turned off
Achin Guptaa45e3972013-12-05 15:10:48 +000067 */
Vikram Kanigirif100f412014-04-01 19:26:26 +010068 flush_dcache_range(
69 (unsigned long)&psci_suspend_context[node->data],
70 sizeof(suspend_context));
Achin Guptaa45e3972013-12-05 15:10:48 +000071}
72
73/*******************************************************************************
Vikram Kanigirif100f412014-04-01 19:26:26 +010074 * This function gets the affinity level till which a cpu is powered down
75 * during a cpu_suspend call. Returns PSCI_INVALID_DATA if the
76 * power state saved for the node is invalid
77 ******************************************************************************/
78int psci_get_suspend_afflvl(unsigned long mpidr)
79{
80 aff_map_node *node;
81
82 node = psci_get_aff_map_node(mpidr & MPIDR_AFFINITY_MASK,
83 MPIDR_AFFLVL0);
84 assert(node);
85
86 return psci_get_aff_map_node_suspend_afflvl(node);
87}
88
89
90/*******************************************************************************
Achin Guptaa45e3972013-12-05 15:10:48 +000091 * This function gets the affinity level till which the current cpu was powered
Vikram Kanigirif100f412014-04-01 19:26:26 +010092 * down during a cpu_suspend call. Returns PSCI_INVALID_DATA if the
93 * power state saved for the node is invalid
94 ******************************************************************************/
95int psci_get_aff_map_node_suspend_afflvl(aff_map_node *node)
96{
97 unsigned int power_state;
98
99 assert(node->level == MPIDR_AFFLVL0);
100
101 power_state = psci_suspend_context[node->data].power_state;
102 return ((power_state == PSCI_INVALID_DATA) ?
103 power_state : psci_get_pstate_afflvl(power_state));
104}
105
106/*******************************************************************************
107 * This function gets the state id of a cpu stored in suspend context
108 * while powering down during a cpu_suspend call. Returns 0xFFFFFFFF
109 * if the power state saved for the node is invalid
Achin Guptaa45e3972013-12-05 15:10:48 +0000110 ******************************************************************************/
Vikram Kanigirif100f412014-04-01 19:26:26 +0100111int psci_get_suspend_stateid(unsigned long mpidr)
Achin Guptaa45e3972013-12-05 15:10:48 +0000112{
Vikram Kanigirif100f412014-04-01 19:26:26 +0100113 aff_map_node *node;
114 unsigned int power_state;
115
116 node = psci_get_aff_map_node(mpidr & MPIDR_AFFINITY_MASK,
117 MPIDR_AFFLVL0);
118 assert(node);
119 assert(node->level == MPIDR_AFFLVL0);
120
121 power_state = psci_suspend_context[node->data].power_state;
122 return ((power_state == PSCI_INVALID_DATA) ?
123 power_state : psci_get_pstate_id(power_state));
Achin Guptaa45e3972013-12-05 15:10:48 +0000124}
125
126/*******************************************************************************
Achin Gupta4f6ad662013-10-25 09:08:21 +0100127 * The next three functions implement a handler for each supported affinity
128 * level which is called when that affinity level is about to be suspended.
129 ******************************************************************************/
130static int psci_afflvl0_suspend(unsigned long mpidr,
131 aff_map_node *cpu_node,
132 unsigned long ns_entrypoint,
133 unsigned long context_id,
134 unsigned int power_state)
135{
136 unsigned int index, plat_state;
Vikram Kanigiri78a6e0c2014-03-11 17:41:00 +0000137 unsigned long psci_entrypoint, sctlr;
Achin Gupta0a9f7472014-02-09 17:48:12 +0000138 el3_state *saved_el3_state;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100139 int rc = PSCI_E_SUCCESS;
140
141 /* Sanity check to safeguard against data corruption */
142 assert(cpu_node->level == MPIDR_AFFLVL0);
143
Vikram Kanigirif100f412014-04-01 19:26:26 +0100144 /* Save PSCI power state parameter for the core in suspend context */
145 psci_set_suspend_power_state(cpu_node, power_state);
146
Achin Gupta607084e2014-02-09 18:24:19 +0000147 /*
148 * Generic management: Store the re-entry information for the non-secure
149 * world and allow the secure world to suspend itself
150 */
151
152 /*
153 * Call the cpu suspend handler registered by the Secure Payload
154 * Dispatcher to let it do any bookeeping. If the handler encounters an
155 * error, it's expected to assert within
156 */
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000157 if (psci_spd_pm && psci_spd_pm->svc_suspend)
158 psci_spd_pm->svc_suspend(power_state);
Achin Gupta607084e2014-02-09 18:24:19 +0000159
Achin Gupta75f73672013-12-05 16:33:10 +0000160 /* State management: mark this cpu as suspended */
161 psci_set_state(cpu_node, PSCI_STATE_SUSPEND);
162
Achin Gupta4f6ad662013-10-25 09:08:21 +0100163 /*
164 * Generic management: Store the re-entry information for the
165 * non-secure world
166 */
167 index = cpu_node->data;
168 rc = psci_set_ns_entry_info(index, ns_entrypoint, context_id);
169 if (rc != PSCI_E_SUCCESS)
170 return rc;
171
172 /*
Achin Guptaef7a28c2014-02-01 08:59:56 +0000173 * Arch. management: Save the EL3 state in the 'cpu_context'
174 * structure that has been allocated for this cpu, flush the
Achin Gupta4f6ad662013-10-25 09:08:21 +0100175 * L1 caches and exit intra-cluster coherency et al
176 */
Achin Guptaef7a28c2014-02-01 08:59:56 +0000177 cm_el3_sysregs_context_save(NON_SECURE);
178 rc = PSCI_E_SUCCESS;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100179
Achin Gupta0a9f7472014-02-09 17:48:12 +0000180 /*
181 * The EL3 state to PoC since it will be accessed after a
182 * reset with the caches turned off
183 */
184 saved_el3_state = get_el3state_ctx(cm_get_context(mpidr, NON_SECURE));
185 flush_dcache_range((uint64_t) saved_el3_state, sizeof(*saved_el3_state));
186
Achin Gupta4f6ad662013-10-25 09:08:21 +0100187 /* Set the secure world (EL3) re-entry point after BL1 */
188 psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry;
189
190 /*
191 * Arch. management. Perform the necessary steps to flush all
192 * cpu caches.
193 *
194 * TODO: This power down sequence varies across cpus so it needs to be
195 * abstracted out on the basis of the MIDR like in cpu_reset_handler().
196 * Do the bare minimal for the time being. Fix this before porting to
197 * Cortex models.
198 */
Vikram Kanigiri78a6e0c2014-03-11 17:41:00 +0000199 sctlr = read_sctlr_el3();
Achin Gupta4f6ad662013-10-25 09:08:21 +0100200 sctlr &= ~SCTLR_C_BIT;
Vikram Kanigiri78a6e0c2014-03-11 17:41:00 +0000201 write_sctlr_el3(sctlr);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100202
203 /*
204 * CAUTION: This flush to the level of unification makes an assumption
205 * about the cache hierarchy at affinity level 0 (cpu) in the platform.
206 * Ideally the platform should tell psci which levels to flush to exit
207 * coherency.
208 */
209 dcsw_op_louis(DCCISW);
210
211 /*
212 * Plat. management: Allow the platform to perform the
213 * necessary actions to turn off this cpu e.g. set the
214 * platform defined mailbox with the psci entrypoint,
215 * program the power controller etc.
216 */
217 if (psci_plat_pm_ops->affinst_suspend) {
Achin Gupta75f73672013-12-05 16:33:10 +0000218 plat_state = psci_get_phys_state(cpu_node);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100219 rc = psci_plat_pm_ops->affinst_suspend(mpidr,
220 psci_entrypoint,
221 ns_entrypoint,
222 cpu_node->level,
223 plat_state);
224 }
225
226 return rc;
227}
228
229static int psci_afflvl1_suspend(unsigned long mpidr,
230 aff_map_node *cluster_node,
231 unsigned long ns_entrypoint,
232 unsigned long context_id,
233 unsigned int power_state)
234{
235 int rc = PSCI_E_SUCCESS;
236 unsigned int plat_state;
237 unsigned long psci_entrypoint;
238
239 /* Sanity check the cluster level */
240 assert(cluster_node->level == MPIDR_AFFLVL1);
241
Achin Gupta75f73672013-12-05 16:33:10 +0000242 /* State management: Decrement the cluster reference count */
243 psci_set_state(cluster_node, PSCI_STATE_SUSPEND);
244
Achin Gupta4f6ad662013-10-25 09:08:21 +0100245 /*
246 * Keep the physical state of this cluster handy to decide
247 * what action needs to be taken
248 */
Achin Gupta75f73672013-12-05 16:33:10 +0000249 plat_state = psci_get_phys_state(cluster_node);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100250
251 /*
252 * Arch. management: Flush all levels of caches to PoC if the
253 * cluster is to be shutdown
254 */
255 if (plat_state == PSCI_STATE_OFF)
256 dcsw_op_all(DCCISW);
257
258 /*
Achin Gupta3140a9e2013-12-02 16:23:12 +0000259 * Plat. Management. Allow the platform to do its cluster
Achin Gupta4f6ad662013-10-25 09:08:21 +0100260 * specific bookeeping e.g. turn off interconnect coherency,
261 * program the power controller etc.
262 */
263 if (psci_plat_pm_ops->affinst_suspend) {
264
265 /*
266 * Sending the psci entrypoint is currently redundant
267 * beyond affinity level 0 but one never knows what a
268 * platform might do. Also it allows us to keep the
269 * platform handler prototype the same.
270 */
271 psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100272 rc = psci_plat_pm_ops->affinst_suspend(mpidr,
273 psci_entrypoint,
274 ns_entrypoint,
275 cluster_node->level,
276 plat_state);
277 }
278
279 return rc;
280}
281
282
283static int psci_afflvl2_suspend(unsigned long mpidr,
284 aff_map_node *system_node,
285 unsigned long ns_entrypoint,
286 unsigned long context_id,
287 unsigned int power_state)
288{
289 int rc = PSCI_E_SUCCESS;
290 unsigned int plat_state;
291 unsigned long psci_entrypoint;
292
293 /* Cannot go beyond this */
294 assert(system_node->level == MPIDR_AFFLVL2);
295
Achin Gupta75f73672013-12-05 16:33:10 +0000296 /* State management: Decrement the system reference count */
297 psci_set_state(system_node, PSCI_STATE_SUSPEND);
298
Achin Gupta4f6ad662013-10-25 09:08:21 +0100299 /*
300 * Keep the physical state of the system handy to decide what
301 * action needs to be taken
302 */
Achin Gupta75f73672013-12-05 16:33:10 +0000303 plat_state = psci_get_phys_state(system_node);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100304
305 /*
Achin Gupta3140a9e2013-12-02 16:23:12 +0000306 * Plat. Management : Allow the platform to do its bookeeping
Achin Gupta4f6ad662013-10-25 09:08:21 +0100307 * at this affinity level
308 */
309 if (psci_plat_pm_ops->affinst_suspend) {
310
311 /*
312 * Sending the psci entrypoint is currently redundant
313 * beyond affinity level 0 but one never knows what a
314 * platform might do. Also it allows us to keep the
315 * platform handler prototype the same.
316 */
317 psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100318 rc = psci_plat_pm_ops->affinst_suspend(mpidr,
319 psci_entrypoint,
320 ns_entrypoint,
321 system_node->level,
322 plat_state);
323 }
324
325 return rc;
326}
327
328static const afflvl_suspend_handler psci_afflvl_suspend_handlers[] = {
329 psci_afflvl0_suspend,
330 psci_afflvl1_suspend,
331 psci_afflvl2_suspend,
332};
333
334/*******************************************************************************
Achin Gupta0959db52013-12-02 17:33:04 +0000335 * This function takes an array of pointers to affinity instance nodes in the
336 * topology tree and calls the suspend handler for the corresponding affinity
337 * levels
338 ******************************************************************************/
339static int psci_call_suspend_handlers(mpidr_aff_map_nodes mpidr_nodes,
340 int start_afflvl,
341 int end_afflvl,
342 unsigned long mpidr,
343 unsigned long entrypoint,
344 unsigned long context_id,
345 unsigned int power_state)
346{
347 int rc = PSCI_E_INVALID_PARAMS, level;
348 aff_map_node *node;
349
350 for (level = start_afflvl; level <= end_afflvl; level++) {
351 node = mpidr_nodes[level];
352 if (node == NULL)
353 continue;
354
355 /*
356 * TODO: In case of an error should there be a way
357 * of restoring what we might have torn down at
358 * lower affinity levels.
359 */
360 rc = psci_afflvl_suspend_handlers[level](mpidr,
361 node,
362 entrypoint,
363 context_id,
364 power_state);
365 if (rc != PSCI_E_SUCCESS)
366 break;
367 }
368
369 return rc;
370}
371
372/*******************************************************************************
373 * Top level handler which is called when a cpu wants to suspend its execution.
374 * It is assumed that along with turning the cpu off, higher affinity levels
375 * until the target affinity level will be turned off as well. It traverses
376 * through all the affinity levels performing generic, architectural, platform
377 * setup and state management e.g. for a cluster that's to be suspended, it will
378 * call the platform specific code which will disable coherency at the
379 * interconnect level if the cpu is the last in the cluster. For a cpu it could
380 * mean programming the power controller etc.
381 *
382 * The state of all the relevant affinity levels is changed prior to calling the
383 * affinity level specific handlers as their actions would depend upon the state
384 * the affinity level is about to enter.
385 *
386 * The affinity level specific handlers are called in ascending order i.e. from
387 * the lowest to the highest affinity level implemented by the platform because
388 * to turn off affinity level X it is neccesary to turn off affinity level X - 1
389 * first.
390 *
391 * CAUTION: This function is called with coherent stacks so that coherency can
392 * be turned off and caches can be flushed safely.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100393 ******************************************************************************/
394int psci_afflvl_suspend(unsigned long mpidr,
395 unsigned long entrypoint,
396 unsigned long context_id,
397 unsigned int power_state,
Achin Gupta0959db52013-12-02 17:33:04 +0000398 int start_afflvl,
399 int end_afflvl)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100400{
Achin Gupta0959db52013-12-02 17:33:04 +0000401 int rc = PSCI_E_SUCCESS;
Achin Gupta0959db52013-12-02 17:33:04 +0000402 mpidr_aff_map_nodes mpidr_nodes;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100403
404 mpidr &= MPIDR_AFFINITY_MASK;
405
406 /*
Achin Gupta0959db52013-12-02 17:33:04 +0000407 * Collect the pointers to the nodes in the topology tree for
408 * each affinity instance in the mpidr. If this function does
409 * not return successfully then either the mpidr or the affinity
410 * levels are incorrect.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100411 */
Achin Gupta0959db52013-12-02 17:33:04 +0000412 rc = psci_get_aff_map_nodes(mpidr,
413 start_afflvl,
414 end_afflvl,
415 mpidr_nodes);
416 if (rc != PSCI_E_SUCCESS)
417 return rc;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100418
419 /*
Achin Gupta0959db52013-12-02 17:33:04 +0000420 * This function acquires the lock corresponding to each affinity
421 * level so that by the time all locks are taken, the system topology
422 * is snapshot and state management can be done safely.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100423 */
Achin Gupta0959db52013-12-02 17:33:04 +0000424 psci_acquire_afflvl_locks(mpidr,
425 start_afflvl,
426 end_afflvl,
427 mpidr_nodes);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100428
Achin Gupta0959db52013-12-02 17:33:04 +0000429 /* Perform generic, architecture and platform specific handling */
430 rc = psci_call_suspend_handlers(mpidr_nodes,
431 start_afflvl,
432 end_afflvl,
433 mpidr,
434 entrypoint,
435 context_id,
436 power_state);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100437
438 /*
Achin Gupta0959db52013-12-02 17:33:04 +0000439 * Release the locks corresponding to each affinity level in the
440 * reverse order to which they were acquired.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100441 */
Achin Gupta0959db52013-12-02 17:33:04 +0000442 psci_release_afflvl_locks(mpidr,
443 start_afflvl,
444 end_afflvl,
445 mpidr_nodes);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100446
Achin Gupta4f6ad662013-10-25 09:08:21 +0100447 return rc;
448}
449
450/*******************************************************************************
451 * The following functions finish an earlier affinity suspend request. They
452 * are called by the common finisher routine in psci_common.c.
453 ******************************************************************************/
454static unsigned int psci_afflvl0_suspend_finish(unsigned long mpidr,
Achin Gupta0959db52013-12-02 17:33:04 +0000455 aff_map_node *cpu_node)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100456{
Achin Gupta0959db52013-12-02 17:33:04 +0000457 unsigned int index, plat_state, state, rc = PSCI_E_SUCCESS;
Achin Gupta607084e2014-02-09 18:24:19 +0000458 int32_t suspend_level;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100459
460 assert(cpu_node->level == MPIDR_AFFLVL0);
461
Achin Gupta0959db52013-12-02 17:33:04 +0000462 /* Ensure we have been woken up from a suspended state */
Achin Gupta75f73672013-12-05 16:33:10 +0000463 state = psci_get_state(cpu_node);
Achin Gupta0959db52013-12-02 17:33:04 +0000464 assert(state == PSCI_STATE_SUSPEND);
465
Achin Gupta4f6ad662013-10-25 09:08:21 +0100466 /*
467 * Plat. management: Perform the platform specific actions
468 * before we change the state of the cpu e.g. enabling the
469 * gic or zeroing the mailbox register. If anything goes
470 * wrong then assert as there is no way to recover from this
471 * situation.
472 */
473 if (psci_plat_pm_ops->affinst_suspend_finish) {
Achin Gupta0959db52013-12-02 17:33:04 +0000474
475 /* Get the physical state of this cpu */
Achin Gupta75f73672013-12-05 16:33:10 +0000476 plat_state = get_phys_state(state);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100477 rc = psci_plat_pm_ops->affinst_suspend_finish(mpidr,
478 cpu_node->level,
479 plat_state);
480 assert(rc == PSCI_E_SUCCESS);
481 }
482
483 /* Get the index for restoring the re-entry information */
484 index = cpu_node->data;
485
486 /*
Achin Guptaef7a28c2014-02-01 08:59:56 +0000487 * Arch. management: Restore the stashed EL3 architectural
488 * context from the 'cpu_context' structure for this cpu.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100489 */
Achin Guptaef7a28c2014-02-01 08:59:56 +0000490 cm_el3_sysregs_context_restore(NON_SECURE);
491 rc = PSCI_E_SUCCESS;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100492
493 /*
Achin Gupta607084e2014-02-09 18:24:19 +0000494 * Use the more complex exception vectors to enable SPD
495 * initialisation. SP_EL3 should point to a 'cpu_context'
496 * structure which has an exception stack allocated. The
497 * non-secure context should have been set on this cpu
498 * prior to suspension.
499 */
500 assert(cm_get_context(mpidr, NON_SECURE));
501 cm_set_next_eret_context(NON_SECURE);
502 write_vbar_el3((uint64_t) runtime_exceptions);
503
504 /*
505 * Call the cpu suspend finish handler registered by the Secure Payload
506 * Dispatcher to let it do any bookeeping. If the handler encounters an
507 * error, it's expected to assert within
508 */
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000509 if (psci_spd_pm && psci_spd_pm->svc_suspend) {
Vikram Kanigirif100f412014-04-01 19:26:26 +0100510 suspend_level = psci_get_aff_map_node_suspend_afflvl(cpu_node);
511 assert (suspend_level != PSCI_INVALID_DATA);
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000512 psci_spd_pm->svc_suspend_finish(suspend_level);
Achin Gupta607084e2014-02-09 18:24:19 +0000513 }
514
Vikram Kanigirif100f412014-04-01 19:26:26 +0100515 /* Invalidate the suspend context for the node */
516 psci_set_suspend_power_state(cpu_node, PSCI_INVALID_DATA);
517
Achin Gupta607084e2014-02-09 18:24:19 +0000518 /*
Achin Gupta4f6ad662013-10-25 09:08:21 +0100519 * Generic management: Now we just need to retrieve the
520 * information that we had stashed away during the suspend
Achin Gupta3140a9e2013-12-02 16:23:12 +0000521 * call to set this cpu on its way.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100522 */
Achin Guptac8afc782013-11-25 18:45:02 +0000523 psci_get_ns_entry_info(index);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100524
Achin Gupta75f73672013-12-05 16:33:10 +0000525 /* State management: mark this cpu as on */
526 psci_set_state(cpu_node, PSCI_STATE_ON);
527
Achin Gupta4f6ad662013-10-25 09:08:21 +0100528 /* Clean caches before re-entering normal world */
529 dcsw_op_louis(DCCSW);
530
531 return rc;
532}
533
534static unsigned int psci_afflvl1_suspend_finish(unsigned long mpidr,
Achin Gupta0959db52013-12-02 17:33:04 +0000535 aff_map_node *cluster_node)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100536{
Achin Gupta0959db52013-12-02 17:33:04 +0000537 unsigned int plat_state, rc = PSCI_E_SUCCESS;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100538
539 assert(cluster_node->level == MPIDR_AFFLVL1);
540
541 /*
542 * Plat. management: Perform the platform specific actions
543 * as per the old state of the cluster e.g. enabling
544 * coherency at the interconnect depends upon the state with
545 * which this cluster was powered up. If anything goes wrong
546 * then assert as there is no way to recover from this
547 * situation.
548 */
549 if (psci_plat_pm_ops->affinst_suspend_finish) {
Achin Gupta0959db52013-12-02 17:33:04 +0000550
551 /* Get the physical state of this cpu */
Achin Gupta75f73672013-12-05 16:33:10 +0000552 plat_state = psci_get_phys_state(cluster_node);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100553 rc = psci_plat_pm_ops->affinst_suspend_finish(mpidr,
554 cluster_node->level,
555 plat_state);
556 assert(rc == PSCI_E_SUCCESS);
557 }
558
Achin Gupta75f73672013-12-05 16:33:10 +0000559 /* State management: Increment the cluster reference count */
560 psci_set_state(cluster_node, PSCI_STATE_ON);
561
Achin Gupta4f6ad662013-10-25 09:08:21 +0100562 return rc;
563}
564
565
566static unsigned int psci_afflvl2_suspend_finish(unsigned long mpidr,
Achin Gupta0959db52013-12-02 17:33:04 +0000567 aff_map_node *system_node)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100568{
Achin Gupta0959db52013-12-02 17:33:04 +0000569 unsigned int plat_state, rc = PSCI_E_SUCCESS;;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100570
571 /* Cannot go beyond this affinity level */
572 assert(system_node->level == MPIDR_AFFLVL2);
573
574 /*
575 * Currently, there are no architectural actions to perform
576 * at the system level.
577 */
578
579 /*
580 * Plat. management: Perform the platform specific actions
581 * as per the old state of the cluster e.g. enabling
582 * coherency at the interconnect depends upon the state with
583 * which this cluster was powered up. If anything goes wrong
584 * then assert as there is no way to recover from this
585 * situation.
586 */
587 if (psci_plat_pm_ops->affinst_suspend_finish) {
Achin Gupta0959db52013-12-02 17:33:04 +0000588
589 /* Get the physical state of the system */
Achin Gupta75f73672013-12-05 16:33:10 +0000590 plat_state = psci_get_phys_state(system_node);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100591 rc = psci_plat_pm_ops->affinst_suspend_finish(mpidr,
592 system_node->level,
593 plat_state);
594 assert(rc == PSCI_E_SUCCESS);
595 }
596
Achin Gupta75f73672013-12-05 16:33:10 +0000597 /* State management: Increment the system reference count */
598 psci_set_state(system_node, PSCI_STATE_ON);
599
Achin Gupta4f6ad662013-10-25 09:08:21 +0100600 return rc;
601}
602
603const afflvl_power_on_finisher psci_afflvl_suspend_finishers[] = {
604 psci_afflvl0_suspend_finish,
605 psci_afflvl1_suspend_finish,
606 psci_afflvl2_suspend_finish,
607};
608