blob: c402937ab34467bbe33313fd0482aaf3c55e2e7e [file] [log] [blame]
Soby Mathewb48349e2015-06-29 16:30:12 +01001/*
Soby Mathew4067dc32015-05-05 16:33:16 +01002 * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
Soby Mathewb48349e2015-06-29 16:30:12 +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 <assert.h>
32#include <bl_common.h>
33#include <arch.h>
34#include <arch_helpers.h>
35#include <context.h>
36#include <context_mgmt.h>
37#include <cpu_data.h>
38#include <debug.h>
39#include <platform.h>
40#include <runtime_svc.h>
41#include <stddef.h>
42#include "psci_private.h"
43
Soby Mathewb48349e2015-06-29 16:30:12 +010044/*******************************************************************************
45 * This function saves the power state parameter passed in the current PSCI
46 * cpu_suspend call in the per-cpu data array.
47 ******************************************************************************/
48void psci_set_suspend_power_state(unsigned int power_state)
49{
50 set_cpu_data(psci_svc_cpu_data.power_state, power_state);
51 flush_cpu_data(psci_svc_cpu_data.power_state);
52}
53
54/*******************************************************************************
Soby Mathew4067dc32015-05-05 16:33:16 +010055 * This function gets the power level till which the current cpu could be
Soby Mathewb48349e2015-06-29 16:30:12 +010056 * powered down during a cpu_suspend call. Returns PSCI_INVALID_DATA if the
57 * power state is invalid.
58 ******************************************************************************/
Soby Mathew4067dc32015-05-05 16:33:16 +010059int psci_get_suspend_pwrlvl(void)
Soby Mathewb48349e2015-06-29 16:30:12 +010060{
61 unsigned int power_state;
62
63 power_state = get_cpu_data(psci_svc_cpu_data.power_state);
64
65 return ((power_state == PSCI_INVALID_DATA) ?
Soby Mathew4067dc32015-05-05 16:33:16 +010066 power_state : psci_get_pstate_pwrlvl(power_state));
Soby Mathewb48349e2015-06-29 16:30:12 +010067}
68
69/*******************************************************************************
70 * This function gets the state id of the current cpu from the power state
71 * parameter saved in the per-cpu data array. Returns PSCI_INVALID_DATA if the
72 * power state saved is invalid.
73 ******************************************************************************/
74int psci_get_suspend_stateid(void)
75{
76 unsigned int power_state;
77
78 power_state = get_cpu_data(psci_svc_cpu_data.power_state);
79
80 return ((power_state == PSCI_INVALID_DATA) ?
81 power_state : psci_get_pstate_id(power_state));
82}
83
84/*******************************************************************************
Soby Mathew82dcc032015-04-08 17:42:06 +010085 * This function gets the state id of the cpu specified by the cpu index
Soby Mathewb48349e2015-06-29 16:30:12 +010086 * from the power state parameter saved in the per-cpu data array. Returns
87 * PSCI_INVALID_DATA if the power state saved is invalid.
88 ******************************************************************************/
Soby Mathew82dcc032015-04-08 17:42:06 +010089int psci_get_suspend_stateid_by_idx(unsigned long cpu_idx)
Soby Mathewb48349e2015-06-29 16:30:12 +010090{
91 unsigned int power_state;
92
Soby Mathew82dcc032015-04-08 17:42:06 +010093 power_state = get_cpu_data_by_index(cpu_idx,
Soby Mathewb48349e2015-06-29 16:30:12 +010094 psci_svc_cpu_data.power_state);
95
96 return ((power_state == PSCI_INVALID_DATA) ?
97 power_state : psci_get_pstate_id(power_state));
98}
99
100/*******************************************************************************
Soby Mathewb48349e2015-06-29 16:30:12 +0100101 * Top level handler which is called when a cpu wants to suspend its execution.
Soby Mathew4067dc32015-05-05 16:33:16 +0100102 * It is assumed that along with suspending the cpu power domain, power domains
103 * at higher levels until the target power level will be suspended as well.
104 * It finds the highest level where a domain has to be suspended by traversing
105 * the node information and then performs generic, architectural, platform
106 * setup and state management required to suspend that power domain and domains
107 * below it. * e.g. For a cpu that's to be suspended, it could mean programming
108 * the power controller whereas for a cluster that's to be suspended, it will
109 * call the platform specific code which will disable coherency at the
110 * interconnect level if the cpu is the last in the cluster and also the
111 * program the power controller.
Soby Mathewb48349e2015-06-29 16:30:12 +0100112 *
113 * All the required parameter checks are performed at the beginning and after
Soby Mathew6590ce22015-06-30 11:00:24 +0100114 * the state transition has been done, no further error is expected and it is
115 * not possible to undo any of the actions taken beyond that point.
Soby Mathewb48349e2015-06-29 16:30:12 +0100116 ******************************************************************************/
Soby Mathew82dcc032015-04-08 17:42:06 +0100117void psci_cpu_suspend_start(entry_point_info_t *ep, int end_pwrlvl)
Soby Mathewb48349e2015-06-29 16:30:12 +0100118{
119 int skip_wfi = 0;
Soby Mathew82dcc032015-04-08 17:42:06 +0100120 unsigned int max_phys_off_pwrlvl, idx = plat_my_core_pos();
Soby Mathew6590ce22015-06-30 11:00:24 +0100121 unsigned long psci_entrypoint;
Soby Mathewb48349e2015-06-29 16:30:12 +0100122
123 /*
124 * This function must only be called on platforms where the
125 * CPU_SUSPEND platform hooks have been implemented.
126 */
Soby Mathew4067dc32015-05-05 16:33:16 +0100127 assert(psci_plat_pm_ops->pwr_domain_suspend &&
128 psci_plat_pm_ops->pwr_domain_suspend_finish);
Soby Mathewb48349e2015-06-29 16:30:12 +0100129
130 /*
Soby Mathew4067dc32015-05-05 16:33:16 +0100131 * This function acquires the lock corresponding to each power
Soby Mathewb48349e2015-06-29 16:30:12 +0100132 * level so that by the time all locks are taken, the system topology
133 * is snapshot and state management can be done safely.
134 */
Soby Mathew82dcc032015-04-08 17:42:06 +0100135 psci_acquire_pwr_domain_locks(end_pwrlvl,
136 idx);
Soby Mathewb48349e2015-06-29 16:30:12 +0100137
138 /*
139 * We check if there are any pending interrupts after the delay
140 * introduced by lock contention to increase the chances of early
141 * detection that a wake-up interrupt has fired.
142 */
143 if (read_isr_el1()) {
144 skip_wfi = 1;
145 goto exit;
146 }
147
148 /*
149 * Call the cpu suspend handler registered by the Secure Payload
150 * Dispatcher to let it do any bookeeping. If the handler encounters an
151 * error, it's expected to assert within
152 */
153 if (psci_spd_pm && psci_spd_pm->svc_suspend)
154 psci_spd_pm->svc_suspend(0);
155
156 /*
Soby Mathew4067dc32015-05-05 16:33:16 +0100157 * This function updates the state of each power domain instance
Soby Mathew82dcc032015-04-08 17:42:06 +0100158 * corresponding to the cpu index in the range of power levels
Soby Mathewb48349e2015-06-29 16:30:12 +0100159 * specified.
160 */
Soby Mathew82dcc032015-04-08 17:42:06 +0100161 psci_do_state_coordination(end_pwrlvl,
162 idx,
163 PSCI_STATE_SUSPEND);
Soby Mathewb48349e2015-06-29 16:30:12 +0100164
Soby Mathew82dcc032015-04-08 17:42:06 +0100165 max_phys_off_pwrlvl = psci_find_max_phys_off_pwrlvl(end_pwrlvl,
166 idx);
Soby Mathew4067dc32015-05-05 16:33:16 +0100167 assert(max_phys_off_pwrlvl != PSCI_INVALID_DATA);
Soby Mathewb48349e2015-06-29 16:30:12 +0100168
Soby Mathewb48349e2015-06-29 16:30:12 +0100169 /*
170 * Store the re-entry information for the non-secure world.
171 */
Soby Mathew12d0d002015-04-09 13:40:55 +0100172 cm_init_my_context(ep);
Soby Mathewb48349e2015-06-29 16:30:12 +0100173
Soby Mathew6590ce22015-06-30 11:00:24 +0100174 /* Set the secure world (EL3) re-entry point after BL1 */
Soby Mathew4067dc32015-05-05 16:33:16 +0100175 psci_entrypoint = (unsigned long) psci_cpu_suspend_finish_entry;
Soby Mathewb48349e2015-06-29 16:30:12 +0100176
177 /*
Soby Mathew6590ce22015-06-30 11:00:24 +0100178 * Arch. management. Perform the necessary steps to flush all
179 * cpu caches.
Soby Mathewb48349e2015-06-29 16:30:12 +0100180 */
Soby Mathew4067dc32015-05-05 16:33:16 +0100181 psci_do_pwrdown_cache_maintenance(max_phys_off_pwrlvl);
Soby Mathew6590ce22015-06-30 11:00:24 +0100182
183 /*
184 * Plat. management: Allow the platform to perform the
185 * necessary actions to turn off this cpu e.g. set the
186 * platform defined mailbox with the psci entrypoint,
187 * program the power controller etc.
188 */
Soby Mathew4067dc32015-05-05 16:33:16 +0100189 psci_plat_pm_ops->pwr_domain_suspend(psci_entrypoint,
190 max_phys_off_pwrlvl);
Soby Mathewb48349e2015-06-29 16:30:12 +0100191
192exit:
193 /*
Soby Mathew4067dc32015-05-05 16:33:16 +0100194 * Release the locks corresponding to each power level in the
Soby Mathewb48349e2015-06-29 16:30:12 +0100195 * reverse order to which they were acquired.
196 */
Soby Mathew82dcc032015-04-08 17:42:06 +0100197 psci_release_pwr_domain_locks(end_pwrlvl,
198 idx);
Soby Mathewb48349e2015-06-29 16:30:12 +0100199 if (!skip_wfi)
200 psci_power_down_wfi();
201}
202
203/*******************************************************************************
Soby Mathew4067dc32015-05-05 16:33:16 +0100204 * The following functions finish an earlier suspend request. They
Soby Mathewb48349e2015-06-29 16:30:12 +0100205 * are called by the common finisher routine in psci_common.c.
206 ******************************************************************************/
Soby Mathew82dcc032015-04-08 17:42:06 +0100207void psci_cpu_suspend_finish(unsigned int cpu_idx, int max_off_pwrlvl)
Soby Mathewb48349e2015-06-29 16:30:12 +0100208{
Soby Mathewb48349e2015-06-29 16:30:12 +0100209 int32_t suspend_level;
210 uint64_t counter_freq;
211
Soby Mathewb48349e2015-06-29 16:30:12 +0100212 /* Ensure we have been woken up from a suspended state */
Soby Mathew82dcc032015-04-08 17:42:06 +0100213 assert(psci_get_state(cpu_idx, PSCI_CPU_PWR_LVL)
214 == PSCI_STATE_SUSPEND);
Soby Mathewb48349e2015-06-29 16:30:12 +0100215
216 /*
217 * Plat. management: Perform the platform specific actions
218 * before we change the state of the cpu e.g. enabling the
219 * gic or zeroing the mailbox register. If anything goes
220 * wrong then assert as there is no way to recover from this
221 * situation.
222 */
Soby Mathew82dcc032015-04-08 17:42:06 +0100223 psci_plat_pm_ops->pwr_domain_suspend_finish(max_off_pwrlvl);
Soby Mathewb48349e2015-06-29 16:30:12 +0100224
225 /*
226 * Arch. management: Enable the data cache, manage stack memory and
227 * restore the stashed EL3 architectural context from the 'cpu_context'
228 * structure for this cpu.
229 */
230 psci_do_pwrup_cache_maintenance();
231
232 /* Re-init the cntfrq_el0 register */
233 counter_freq = plat_get_syscnt_freq();
234 write_cntfrq_el0(counter_freq);
235
236 /*
237 * Call the cpu suspend finish handler registered by the Secure Payload
238 * Dispatcher to let it do any bookeeping. If the handler encounters an
239 * error, it's expected to assert within
240 */
241 if (psci_spd_pm && psci_spd_pm->svc_suspend) {
Soby Mathew4067dc32015-05-05 16:33:16 +0100242 suspend_level = psci_get_suspend_pwrlvl();
Soby Mathewb48349e2015-06-29 16:30:12 +0100243 assert (suspend_level != PSCI_INVALID_DATA);
244 psci_spd_pm->svc_suspend_finish(suspend_level);
245 }
246
247 /* Invalidate the suspend context for the node */
248 psci_set_suspend_power_state(PSCI_INVALID_DATA);
249
250 /*
251 * Generic management: Now we just need to retrieve the
252 * information that we had stashed away during the suspend
253 * call to set this cpu on its way.
254 */
255 cm_prepare_el3_exit(NON_SECURE);
256
257 /* Clean caches before re-entering normal world */
258 dcsw_op_louis(DCCSW);
259}