blob: 942e9a122fcdd9388f3cedcee5f41175b33cc12c [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
Achin Gupta4f6ad662013-10-25 09:08:21 +010031#include <assert.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010032#include <bl_common.h>
33#include <arch.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010034#include <arch_helpers.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010035#include <context.h>
Achin Guptaef7a28c2014-02-01 08:59:56 +000036#include <context_mgmt.h>
Achin Guptaf3ccbab2014-07-25 14:52:47 +010037#include <cpu_data.h>
Soby Mathew2ed46e92014-07-04 16:02:26 +010038#include <platform.h>
Dan Handleybcd60ba2014-04-17 18:53:42 +010039#include <runtime_svc.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010040#include <stddef.h>
Dan Handley714a0d22014-04-09 13:13:04 +010041#include "psci_private.h"
Achin Gupta4f6ad662013-10-25 09:08:21 +010042
Soby Mathewf5121572014-09-30 11:19:51 +010043typedef int (*afflvl_suspend_handler_t)(aff_map_node_t *node);
Achin Gupta4f6ad662013-10-25 09:08:21 +010044
45/*******************************************************************************
Achin Guptaf3ccbab2014-07-25 14:52:47 +010046 * This function saves the power state parameter passed in the current PSCI
47 * cpu_suspend call in the per-cpu data array.
Achin Guptaa45e3972013-12-05 15:10:48 +000048 ******************************************************************************/
Achin Guptaf3ccbab2014-07-25 14:52:47 +010049void psci_set_suspend_power_state(unsigned int power_state)
Achin Guptaa45e3972013-12-05 15:10:48 +000050{
Achin Guptaf3ccbab2014-07-25 14:52:47 +010051 set_cpu_data(psci_svc_cpu_data.power_state, power_state);
52 flush_cpu_data(psci_svc_cpu_data.power_state);
Achin Guptaa45e3972013-12-05 15:10:48 +000053}
54
55/*******************************************************************************
Achin Guptaf3ccbab2014-07-25 14:52:47 +010056 * This function gets the affinity level till which the current cpu could be
57 * powered down during a cpu_suspend call. Returns PSCI_INVALID_DATA if the
58 * power state is invalid.
Vikram Kanigirif100f412014-04-01 19:26:26 +010059 ******************************************************************************/
Achin Guptaf3ccbab2014-07-25 14:52:47 +010060int psci_get_suspend_afflvl()
Vikram Kanigirif100f412014-04-01 19:26:26 +010061{
Achin Guptaf3ccbab2014-07-25 14:52:47 +010062 unsigned int power_state;
Vikram Kanigirif100f412014-04-01 19:26:26 +010063
Achin Guptaf3ccbab2014-07-25 14:52:47 +010064 power_state = get_cpu_data(psci_svc_cpu_data.power_state);
Vikram Kanigirif100f412014-04-01 19:26:26 +010065
Achin Guptaf3ccbab2014-07-25 14:52:47 +010066 return ((power_state == PSCI_INVALID_DATA) ?
67 power_state : psci_get_pstate_afflvl(power_state));
Vikram Kanigirif100f412014-04-01 19:26:26 +010068}
69
Vikram Kanigirif100f412014-04-01 19:26:26 +010070/*******************************************************************************
Achin Guptaf3ccbab2014-07-25 14:52:47 +010071 * This function gets the state id of the current cpu from the power state
72 * parameter saved in the per-cpu data array. Returns PSCI_INVALID_DATA if the
73 * power state saved is invalid.
Vikram Kanigirif100f412014-04-01 19:26:26 +010074 ******************************************************************************/
Achin Guptaf3ccbab2014-07-25 14:52:47 +010075int psci_get_suspend_stateid()
Vikram Kanigirif100f412014-04-01 19:26:26 +010076{
77 unsigned int power_state;
78
Achin Guptaf3ccbab2014-07-25 14:52:47 +010079 power_state = get_cpu_data(psci_svc_cpu_data.power_state);
Vikram Kanigirif100f412014-04-01 19:26:26 +010080
Vikram Kanigirif100f412014-04-01 19:26:26 +010081 return ((power_state == PSCI_INVALID_DATA) ?
Achin Guptaf3ccbab2014-07-25 14:52:47 +010082 power_state : psci_get_pstate_id(power_state));
Vikram Kanigirif100f412014-04-01 19:26:26 +010083}
84
85/*******************************************************************************
Achin Guptaf3ccbab2014-07-25 14:52:47 +010086 * This function gets the state id of the cpu specified by the 'mpidr' parameter
87 * from the power state parameter saved in the per-cpu data array. Returns
88 * PSCI_INVALID_DATA if the power state saved is invalid.
Achin Guptaa45e3972013-12-05 15:10:48 +000089 ******************************************************************************/
Achin Guptaf3ccbab2014-07-25 14:52:47 +010090int psci_get_suspend_stateid_by_mpidr(unsigned long mpidr)
Achin Guptaa45e3972013-12-05 15:10:48 +000091{
Vikram Kanigirif100f412014-04-01 19:26:26 +010092 unsigned int power_state;
93
Achin Guptaf3ccbab2014-07-25 14:52:47 +010094 power_state = get_cpu_data_by_mpidr(mpidr,
95 psci_svc_cpu_data.power_state);
Vikram Kanigirif100f412014-04-01 19:26:26 +010096
Vikram Kanigirif100f412014-04-01 19:26:26 +010097 return ((power_state == PSCI_INVALID_DATA) ?
Achin Guptaf3ccbab2014-07-25 14:52:47 +010098 power_state : psci_get_pstate_id(power_state));
Achin Guptaa45e3972013-12-05 15:10:48 +000099}
100
101/*******************************************************************************
Achin Gupta4f6ad662013-10-25 09:08:21 +0100102 * The next three functions implement a handler for each supported affinity
103 * level which is called when that affinity level is about to be suspended.
104 ******************************************************************************/
Soby Mathewf5121572014-09-30 11:19:51 +0100105static int psci_afflvl0_suspend(aff_map_node_t *cpu_node)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100106{
Achin Guptae1aa5162014-06-26 09:58:52 +0100107 unsigned long psci_entrypoint;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100108
109 /* Sanity check to safeguard against data corruption */
110 assert(cpu_node->level == MPIDR_AFFLVL0);
111
Achin Gupta607084e2014-02-09 18:24:19 +0000112 /*
Soby Mathew8595b872015-01-06 15:36:38 +0000113 * Generic management: Allow the Secure world to suspend itself
Achin Gupta607084e2014-02-09 18:24:19 +0000114 */
115
116 /*
117 * Call the cpu suspend handler registered by the Secure Payload
118 * Dispatcher to let it do any bookeeping. If the handler encounters an
119 * error, it's expected to assert within
120 */
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000121 if (psci_spd_pm && psci_spd_pm->svc_suspend)
Soby Mathewf5121572014-09-30 11:19:51 +0100122 psci_spd_pm->svc_suspend(0);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100123
Achin Gupta4f6ad662013-10-25 09:08:21 +0100124 /* Set the secure world (EL3) re-entry point after BL1 */
125 psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry;
126
127 /*
128 * Arch. management. Perform the necessary steps to flush all
129 * cpu caches.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100130 */
Achin Guptae1aa5162014-06-26 09:58:52 +0100131 psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL0);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100132
Achin Gupta56bcdc22014-07-28 00:15:23 +0100133 if (!psci_plat_pm_ops->affinst_suspend)
134 return PSCI_E_SUCCESS;
135
Achin Gupta4f6ad662013-10-25 09:08:21 +0100136 /*
Achin Gupta4f6ad662013-10-25 09:08:21 +0100137 * Plat. management: Allow the platform to perform the
138 * necessary actions to turn off this cpu e.g. set the
139 * platform defined mailbox with the psci entrypoint,
140 * program the power controller etc.
141 */
Soby Mathewffb4ab12014-09-26 15:08:52 +0100142 return psci_plat_pm_ops->affinst_suspend(psci_entrypoint,
Achin Gupta56bcdc22014-07-28 00:15:23 +0100143 cpu_node->level,
144 psci_get_phys_state(cpu_node));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100145}
146
Soby Mathewf5121572014-09-30 11:19:51 +0100147static int psci_afflvl1_suspend(aff_map_node_t *cluster_node)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100148{
Achin Gupta4f6ad662013-10-25 09:08:21 +0100149 unsigned int plat_state;
150 unsigned long psci_entrypoint;
151
152 /* Sanity check the cluster level */
153 assert(cluster_node->level == MPIDR_AFFLVL1);
154
155 /*
Achin Gupta4f6ad662013-10-25 09:08:21 +0100156 * Arch. management: Flush all levels of caches to PoC if the
Achin Guptaf6b9e992014-07-31 11:19:11 +0100157 * cluster is to be shutdown.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100158 */
Achin Guptaf6b9e992014-07-31 11:19:11 +0100159 psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL1);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100160
Achin Gupta56bcdc22014-07-28 00:15:23 +0100161 if (!psci_plat_pm_ops->affinst_suspend)
162 return PSCI_E_SUCCESS;
163
Achin Gupta4f6ad662013-10-25 09:08:21 +0100164 /*
Achin Gupta56bcdc22014-07-28 00:15:23 +0100165 * Plat. Management. Allow the platform to do its cluster specific
166 * bookeeping e.g. turn off interconnect coherency, program the power
167 * controller etc. Sending the psci entrypoint is currently redundant
168 * beyond affinity level 0 but one never knows what a platform might
169 * do. Also it allows us to keep the platform handler prototype the
170 * same.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100171 */
Achin Gupta56bcdc22014-07-28 00:15:23 +0100172 plat_state = psci_get_phys_state(cluster_node);
173 psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry;
Soby Mathewffb4ab12014-09-26 15:08:52 +0100174 return psci_plat_pm_ops->affinst_suspend(psci_entrypoint,
Achin Gupta56bcdc22014-07-28 00:15:23 +0100175 cluster_node->level,
176 plat_state);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100177}
178
179
Soby Mathewf5121572014-09-30 11:19:51 +0100180static int psci_afflvl2_suspend(aff_map_node_t *system_node)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100181{
Achin Gupta4f6ad662013-10-25 09:08:21 +0100182 unsigned int plat_state;
183 unsigned long psci_entrypoint;
184
185 /* Cannot go beyond this */
186 assert(system_node->level == MPIDR_AFFLVL2);
187
188 /*
189 * Keep the physical state of the system handy to decide what
190 * action needs to be taken
191 */
Achin Gupta75f73672013-12-05 16:33:10 +0000192 plat_state = psci_get_phys_state(system_node);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100193
194 /*
Achin Guptaf6b9e992014-07-31 11:19:11 +0100195 * Arch. management: Flush all levels of caches to PoC if the
196 * system is to be shutdown.
197 */
198 psci_do_pwrdown_cache_maintenance(MPIDR_AFFLVL2);
199
200 /*
Achin Gupta3140a9e2013-12-02 16:23:12 +0000201 * Plat. Management : Allow the platform to do its bookeeping
Achin Gupta4f6ad662013-10-25 09:08:21 +0100202 * at this affinity level
203 */
Achin Gupta56bcdc22014-07-28 00:15:23 +0100204 if (!psci_plat_pm_ops->affinst_suspend)
205 return PSCI_E_SUCCESS;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100206
Achin Gupta56bcdc22014-07-28 00:15:23 +0100207 /*
208 * Sending the psci entrypoint is currently redundant
209 * beyond affinity level 0 but one never knows what a
210 * platform might do. Also it allows us to keep the
211 * platform handler prototype the same.
212 */
213 plat_state = psci_get_phys_state(system_node);
214 psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry;
Soby Mathewffb4ab12014-09-26 15:08:52 +0100215 return psci_plat_pm_ops->affinst_suspend(psci_entrypoint,
Achin Gupta56bcdc22014-07-28 00:15:23 +0100216 system_node->level,
217 plat_state);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100218}
219
Dan Handleye2712bc2014-04-10 15:37:22 +0100220static const afflvl_suspend_handler_t psci_afflvl_suspend_handlers[] = {
Achin Gupta4f6ad662013-10-25 09:08:21 +0100221 psci_afflvl0_suspend,
222 psci_afflvl1_suspend,
223 psci_afflvl2_suspend,
224};
225
226/*******************************************************************************
Achin Gupta0959db52013-12-02 17:33:04 +0000227 * This function takes an array of pointers to affinity instance nodes in the
228 * topology tree and calls the suspend handler for the corresponding affinity
229 * levels
230 ******************************************************************************/
Achin Gupta56bcdc22014-07-28 00:15:23 +0100231static int psci_call_suspend_handlers(aff_map_node_t *mpidr_nodes[],
Achin Gupta0959db52013-12-02 17:33:04 +0000232 int start_afflvl,
Soby Mathewf5121572014-09-30 11:19:51 +0100233 int end_afflvl)
Achin Gupta0959db52013-12-02 17:33:04 +0000234{
235 int rc = PSCI_E_INVALID_PARAMS, level;
Dan Handleye2712bc2014-04-10 15:37:22 +0100236 aff_map_node_t *node;
Achin Gupta0959db52013-12-02 17:33:04 +0000237
238 for (level = start_afflvl; level <= end_afflvl; level++) {
239 node = mpidr_nodes[level];
240 if (node == NULL)
241 continue;
242
243 /*
244 * TODO: In case of an error should there be a way
245 * of restoring what we might have torn down at
246 * lower affinity levels.
247 */
Soby Mathewf5121572014-09-30 11:19:51 +0100248 rc = psci_afflvl_suspend_handlers[level](node);
Achin Gupta0959db52013-12-02 17:33:04 +0000249 if (rc != PSCI_E_SUCCESS)
250 break;
251 }
252
253 return rc;
254}
255
256/*******************************************************************************
257 * Top level handler which is called when a cpu wants to suspend its execution.
258 * It is assumed that along with turning the cpu off, higher affinity levels
259 * until the target affinity level will be turned off as well. It traverses
260 * through all the affinity levels performing generic, architectural, platform
261 * setup and state management e.g. for a cluster that's to be suspended, it will
262 * call the platform specific code which will disable coherency at the
263 * interconnect level if the cpu is the last in the cluster. For a cpu it could
264 * mean programming the power controller etc.
265 *
266 * The state of all the relevant affinity levels is changed prior to calling the
267 * affinity level specific handlers as their actions would depend upon the state
268 * the affinity level is about to enter.
269 *
270 * The affinity level specific handlers are called in ascending order i.e. from
271 * the lowest to the highest affinity level implemented by the platform because
272 * to turn off affinity level X it is neccesary to turn off affinity level X - 1
273 * first.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100274 ******************************************************************************/
Soby Mathew8595b872015-01-06 15:36:38 +0000275int psci_afflvl_suspend(entry_point_info_t *ep,
Achin Gupta0959db52013-12-02 17:33:04 +0000276 int start_afflvl,
277 int end_afflvl)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100278{
Achin Gupta0959db52013-12-02 17:33:04 +0000279 int rc = PSCI_E_SUCCESS;
Dan Handleye2712bc2014-04-10 15:37:22 +0100280 mpidr_aff_map_nodes_t mpidr_nodes;
Achin Guptaf6b9e992014-07-31 11:19:11 +0100281 unsigned int max_phys_off_afflvl;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100282
Achin Gupta4f6ad662013-10-25 09:08:21 +0100283 /*
Achin Gupta0959db52013-12-02 17:33:04 +0000284 * Collect the pointers to the nodes in the topology tree for
285 * each affinity instance in the mpidr. If this function does
286 * not return successfully then either the mpidr or the affinity
287 * levels are incorrect.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100288 */
Andrew Thoelke2bc07852014-06-09 12:44:21 +0100289 rc = psci_get_aff_map_nodes(read_mpidr_el1() & MPIDR_AFFINITY_MASK,
Achin Gupta0959db52013-12-02 17:33:04 +0000290 start_afflvl,
291 end_afflvl,
292 mpidr_nodes);
293 if (rc != PSCI_E_SUCCESS)
294 return rc;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100295
296 /*
Achin Gupta0959db52013-12-02 17:33:04 +0000297 * This function acquires the lock corresponding to each affinity
298 * level so that by the time all locks are taken, the system topology
299 * is snapshot and state management can be done safely.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100300 */
Andrew Thoelke2bc07852014-06-09 12:44:21 +0100301 psci_acquire_afflvl_locks(start_afflvl,
Achin Gupta0959db52013-12-02 17:33:04 +0000302 end_afflvl,
303 mpidr_nodes);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100304
Achin Guptacab78e42014-07-28 00:09:01 +0100305 /*
306 * This function updates the state of each affinity instance
307 * corresponding to the mpidr in the range of affinity levels
308 * specified.
309 */
310 psci_do_afflvl_state_mgmt(start_afflvl,
311 end_afflvl,
312 mpidr_nodes,
313 PSCI_STATE_SUSPEND);
Achin Guptaf6b9e992014-07-31 11:19:11 +0100314
315 max_phys_off_afflvl = psci_find_max_phys_off_afflvl(start_afflvl,
316 end_afflvl,
317 mpidr_nodes);
318 assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
319
320 /* Stash the highest affinity level that will be turned off */
321 psci_set_max_phys_off_afflvl(max_phys_off_afflvl);
322
Soby Mathew8595b872015-01-06 15:36:38 +0000323 /*
324 * Store the re-entry information for the non-secure world.
325 */
326 cm_init_context(read_mpidr_el1(), ep);
327
Achin Gupta0959db52013-12-02 17:33:04 +0000328 /* Perform generic, architecture and platform specific handling */
329 rc = psci_call_suspend_handlers(mpidr_nodes,
330 start_afflvl,
Soby Mathewf5121572014-09-30 11:19:51 +0100331 end_afflvl);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100332
333 /*
Achin Guptaf6b9e992014-07-31 11:19:11 +0100334 * Invalidate the entry for the highest affinity level stashed earlier.
335 * This ensures that any reads of this variable outside the power
336 * up/down sequences return PSCI_INVALID_DATA.
337 */
338 psci_set_max_phys_off_afflvl(PSCI_INVALID_DATA);
339
340 /*
Achin Gupta0959db52013-12-02 17:33:04 +0000341 * Release the locks corresponding to each affinity level in the
342 * reverse order to which they were acquired.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100343 */
Andrew Thoelke2bc07852014-06-09 12:44:21 +0100344 psci_release_afflvl_locks(start_afflvl,
Achin Gupta0959db52013-12-02 17:33:04 +0000345 end_afflvl,
346 mpidr_nodes);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100347
Achin Gupta4f6ad662013-10-25 09:08:21 +0100348 return rc;
349}
350
351/*******************************************************************************
352 * The following functions finish an earlier affinity suspend request. They
353 * are called by the common finisher routine in psci_common.c.
354 ******************************************************************************/
Andrew Thoelke2bc07852014-06-09 12:44:21 +0100355static unsigned int psci_afflvl0_suspend_finish(aff_map_node_t *cpu_node)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100356{
Andrew Thoelke4e126072014-06-04 21:10:52 +0100357 unsigned int plat_state, state, rc;
Achin Gupta607084e2014-02-09 18:24:19 +0000358 int32_t suspend_level;
Soby Mathew2ed46e92014-07-04 16:02:26 +0100359 uint64_t counter_freq;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100360
361 assert(cpu_node->level == MPIDR_AFFLVL0);
362
Achin Gupta0959db52013-12-02 17:33:04 +0000363 /* Ensure we have been woken up from a suspended state */
Achin Gupta75f73672013-12-05 16:33:10 +0000364 state = psci_get_state(cpu_node);
Achin Gupta0959db52013-12-02 17:33:04 +0000365 assert(state == PSCI_STATE_SUSPEND);
366
Achin Gupta4f6ad662013-10-25 09:08:21 +0100367 /*
368 * Plat. management: Perform the platform specific actions
369 * before we change the state of the cpu e.g. enabling the
370 * gic or zeroing the mailbox register. If anything goes
371 * wrong then assert as there is no way to recover from this
372 * situation.
373 */
374 if (psci_plat_pm_ops->affinst_suspend_finish) {
Achin Gupta0959db52013-12-02 17:33:04 +0000375
376 /* Get the physical state of this cpu */
Achin Gupta75f73672013-12-05 16:33:10 +0000377 plat_state = get_phys_state(state);
Soby Mathewffb4ab12014-09-26 15:08:52 +0100378 rc = psci_plat_pm_ops->affinst_suspend_finish(cpu_node->level,
Achin Gupta4f6ad662013-10-25 09:08:21 +0100379 plat_state);
380 assert(rc == PSCI_E_SUCCESS);
381 }
382
383 /* Get the index for restoring the re-entry information */
Achin Gupta4f6ad662013-10-25 09:08:21 +0100384 /*
Achin Guptae1aa5162014-06-26 09:58:52 +0100385 * Arch. management: Enable the data cache, manage stack memory and
386 * restore the stashed EL3 architectural context from the 'cpu_context'
387 * structure for this cpu.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100388 */
Achin Guptae1aa5162014-06-26 09:58:52 +0100389 psci_do_pwrup_cache_maintenance();
Soby Mathew2ed46e92014-07-04 16:02:26 +0100390
391 /* Re-init the cntfrq_el0 register */
392 counter_freq = plat_get_syscnt_freq();
393 write_cntfrq_el0(counter_freq);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100394
395 /*
Achin Gupta607084e2014-02-09 18:24:19 +0000396 * Call the cpu suspend finish handler registered by the Secure Payload
397 * Dispatcher to let it do any bookeeping. If the handler encounters an
398 * error, it's expected to assert within
399 */
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000400 if (psci_spd_pm && psci_spd_pm->svc_suspend) {
Achin Guptaf3ccbab2014-07-25 14:52:47 +0100401 suspend_level = psci_get_suspend_afflvl();
Vikram Kanigirif100f412014-04-01 19:26:26 +0100402 assert (suspend_level != PSCI_INVALID_DATA);
Jeenu Viswambharan7f366602014-02-20 17:11:00 +0000403 psci_spd_pm->svc_suspend_finish(suspend_level);
Achin Gupta607084e2014-02-09 18:24:19 +0000404 }
405
Vikram Kanigirif100f412014-04-01 19:26:26 +0100406 /* Invalidate the suspend context for the node */
Achin Guptaf3ccbab2014-07-25 14:52:47 +0100407 psci_set_suspend_power_state(PSCI_INVALID_DATA);
Vikram Kanigirif100f412014-04-01 19:26:26 +0100408
Achin Gupta607084e2014-02-09 18:24:19 +0000409 /*
Achin Gupta4f6ad662013-10-25 09:08:21 +0100410 * Generic management: Now we just need to retrieve the
411 * information that we had stashed away during the suspend
Achin Gupta3140a9e2013-12-02 16:23:12 +0000412 * call to set this cpu on its way.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100413 */
Andrew Thoelke4e126072014-06-04 21:10:52 +0100414 cm_prepare_el3_exit(NON_SECURE);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100415
416 /* Clean caches before re-entering normal world */
417 dcsw_op_louis(DCCSW);
418
Andrew Thoelke4e126072014-06-04 21:10:52 +0100419 rc = PSCI_E_SUCCESS;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100420 return rc;
421}
422
Andrew Thoelke2bc07852014-06-09 12:44:21 +0100423static unsigned int psci_afflvl1_suspend_finish(aff_map_node_t *cluster_node)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100424{
Achin Gupta0959db52013-12-02 17:33:04 +0000425 unsigned int plat_state, rc = PSCI_E_SUCCESS;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100426
427 assert(cluster_node->level == MPIDR_AFFLVL1);
428
429 /*
430 * Plat. management: Perform the platform specific actions
431 * as per the old state of the cluster e.g. enabling
432 * coherency at the interconnect depends upon the state with
433 * which this cluster was powered up. If anything goes wrong
434 * then assert as there is no way to recover from this
435 * situation.
436 */
437 if (psci_plat_pm_ops->affinst_suspend_finish) {
Achin Gupta0959db52013-12-02 17:33:04 +0000438
439 /* Get the physical state of this cpu */
Achin Gupta75f73672013-12-05 16:33:10 +0000440 plat_state = psci_get_phys_state(cluster_node);
Soby Mathewffb4ab12014-09-26 15:08:52 +0100441 rc = psci_plat_pm_ops->affinst_suspend_finish(cluster_node->level,
Achin Gupta4f6ad662013-10-25 09:08:21 +0100442 plat_state);
443 assert(rc == PSCI_E_SUCCESS);
444 }
445
446 return rc;
447}
448
449
Andrew Thoelke2bc07852014-06-09 12:44:21 +0100450static unsigned int psci_afflvl2_suspend_finish(aff_map_node_t *system_node)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100451{
Achin Gupta0959db52013-12-02 17:33:04 +0000452 unsigned int plat_state, rc = PSCI_E_SUCCESS;;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100453
454 /* Cannot go beyond this affinity level */
455 assert(system_node->level == MPIDR_AFFLVL2);
456
457 /*
458 * Currently, there are no architectural actions to perform
459 * at the system level.
460 */
461
462 /*
463 * Plat. management: Perform the platform specific actions
464 * as per the old state of the cluster e.g. enabling
465 * coherency at the interconnect depends upon the state with
466 * which this cluster was powered up. If anything goes wrong
467 * then assert as there is no way to recover from this
468 * situation.
469 */
470 if (psci_plat_pm_ops->affinst_suspend_finish) {
Achin Gupta0959db52013-12-02 17:33:04 +0000471
472 /* Get the physical state of the system */
Achin Gupta75f73672013-12-05 16:33:10 +0000473 plat_state = psci_get_phys_state(system_node);
Soby Mathewffb4ab12014-09-26 15:08:52 +0100474 rc = psci_plat_pm_ops->affinst_suspend_finish(system_node->level,
Achin Gupta4f6ad662013-10-25 09:08:21 +0100475 plat_state);
476 assert(rc == PSCI_E_SUCCESS);
477 }
478
Achin Gupta4f6ad662013-10-25 09:08:21 +0100479 return rc;
480}
481
Dan Handleye2712bc2014-04-10 15:37:22 +0100482const afflvl_power_on_finisher_t psci_afflvl_suspend_finishers[] = {
Achin Gupta4f6ad662013-10-25 09:08:21 +0100483 psci_afflvl0_suspend_finish,
484 psci_afflvl1_suspend_finish,
485 psci_afflvl2_suspend_finish,
486};