blob: bc5435a80be10a2505f436a4fb6c7675335fe23a [file] [log] [blame]
Achin Gupta607084e2014-02-09 18:24:19 +00001/*
Douglas Raillardf2129652016-11-24 15:43:19 +00002 * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
Achin Gupta607084e2014-02-09 18:24:19 +00003 *
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 Gupta607084e2014-02-09 18:24:19 +000031#include <arch_helpers.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010032#include <assert.h>
33#include <bl_common.h>
Achin Gupta607084e2014-02-09 18:24:19 +000034#include <context_mgmt.h>
Achin Gupta607084e2014-02-09 18:24:19 +000035#include <debug.h>
Dan Handleyed6ff952014-05-14 17:44:19 +010036#include <platform.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010037#include <tsp.h>
Dan Handley714a0d22014-04-09 13:13:04 +010038#include "tspd_private.h"
Achin Gupta607084e2014-02-09 18:24:19 +000039
40/*******************************************************************************
41 * The target cpu is being turned on. Allow the TSPD/TSP to perform any actions
42 * needed. Nothing at the moment.
43 ******************************************************************************/
44static void tspd_cpu_on_handler(uint64_t target_cpu)
45{
46}
47
48/*******************************************************************************
49 * This cpu is being turned off. Allow the TSPD/TSP to perform any actions
50 * needed
51 ******************************************************************************/
Soby Mathewf5121572014-09-30 11:19:51 +010052static int32_t tspd_cpu_off_handler(uint64_t unused)
Achin Gupta607084e2014-02-09 18:24:19 +000053{
54 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +010055 uint32_t linear_id = plat_my_core_pos();
Dan Handleye2712bc2014-04-10 15:37:22 +010056 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Achin Gupta607084e2014-02-09 18:24:19 +000057
Andrew Thoelke891c4ca2014-05-20 21:43:27 +010058 assert(tsp_vectors);
Achin Gupta18d6eaf2014-05-04 18:23:26 +010059 assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
Achin Gupta607084e2014-02-09 18:24:19 +000060
Douglas Raillardf2129652016-11-24 15:43:19 +000061 /*
62 * Abort any preempted SMC request before overwriting the SECURE
63 * context.
64 */
65 tspd_abort_preempted_smc(tsp_ctx);
66
Achin Gupta607084e2014-02-09 18:24:19 +000067 /* Program the entry point and enter the TSP */
Andrew Thoelke891c4ca2014-05-20 21:43:27 +010068 cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_off_entry);
Achin Gupta607084e2014-02-09 18:24:19 +000069 rc = tspd_synchronous_sp_entry(tsp_ctx);
70
71 /*
72 * Read the response from the TSP. A non-zero return means that
73 * something went wrong while communicating with the TSP.
74 */
75 if (rc != 0)
76 panic();
77
78 /*
79 * Reset TSP's context for a fresh start when this cpu is turned on
80 * subsequently.
81 */
Achin Gupta18d6eaf2014-05-04 18:23:26 +010082 set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF);
Achin Gupta607084e2014-02-09 18:24:19 +000083
Douglas Raillardf2129652016-11-24 15:43:19 +000084 return 0;
Achin Gupta607084e2014-02-09 18:24:19 +000085}
86
87/*******************************************************************************
88 * This cpu is being suspended. S-EL1 state must have been saved in the
89 * resident cpu (mpidr format) if it is a UP/UP migratable TSP.
90 ******************************************************************************/
Achin Gupta9a0ff9b2015-09-07 20:43:27 +010091static void tspd_cpu_suspend_handler(uint64_t max_off_pwrlvl)
Achin Gupta607084e2014-02-09 18:24:19 +000092{
93 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +010094 uint32_t linear_id = plat_my_core_pos();
Dan Handleye2712bc2014-04-10 15:37:22 +010095 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Achin Gupta607084e2014-02-09 18:24:19 +000096
Andrew Thoelke891c4ca2014-05-20 21:43:27 +010097 assert(tsp_vectors);
Achin Gupta18d6eaf2014-05-04 18:23:26 +010098 assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
Achin Gupta607084e2014-02-09 18:24:19 +000099
Douglas Raillardf2129652016-11-24 15:43:19 +0000100 /*
101 * Abort any preempted SMC request before overwriting the SECURE
102 * context.
103 */
104 tspd_abort_preempted_smc(tsp_ctx);
105
Soby Mathewf5121572014-09-30 11:19:51 +0100106 /* Program the entry point and enter the TSP */
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100107 cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_suspend_entry);
Achin Gupta607084e2014-02-09 18:24:19 +0000108 rc = tspd_synchronous_sp_entry(tsp_ctx);
109
110 /*
111 * Read the response from the TSP. A non-zero return means that
112 * something went wrong while communicating with the TSP.
113 */
Douglas Raillardf2129652016-11-24 15:43:19 +0000114 if (rc)
Achin Gupta607084e2014-02-09 18:24:19 +0000115 panic();
116
117 /* Update its context to reflect the state the TSP is in */
Achin Gupta18d6eaf2014-05-04 18:23:26 +0100118 set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_SUSPEND);
Achin Gupta607084e2014-02-09 18:24:19 +0000119}
120
121/*******************************************************************************
122 * This cpu has been turned on. Enter the TSP to initialise S-EL1 and other bits
Douglas Raillardf2129652016-11-24 15:43:19 +0000123 * before passing control back to the Secure Monitor. Entry in S-EL1 is done
Achin Gupta607084e2014-02-09 18:24:19 +0000124 * after initialising minimal architectural state that guarantees safe
125 * execution.
126 ******************************************************************************/
Soby Mathewf5121572014-09-30 11:19:51 +0100127static void tspd_cpu_on_finish_handler(uint64_t unused)
Achin Gupta607084e2014-02-09 18:24:19 +0000128{
129 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +0100130 uint32_t linear_id = plat_my_core_pos();
Dan Handleye2712bc2014-04-10 15:37:22 +0100131 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100132 entry_point_info_t tsp_on_entrypoint;
Achin Gupta607084e2014-02-09 18:24:19 +0000133
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100134 assert(tsp_vectors);
Achin Gupta18d6eaf2014-05-04 18:23:26 +0100135 assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_OFF);
Achin Gupta607084e2014-02-09 18:24:19 +0000136
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100137 tspd_init_tsp_ep_state(&tsp_on_entrypoint,
Achin Gupta607084e2014-02-09 18:24:19 +0000138 TSP_AARCH64,
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100139 (uint64_t) &tsp_vectors->cpu_on_entry,
Achin Gupta607084e2014-02-09 18:24:19 +0000140 tsp_ctx);
141
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100142 /* Initialise this cpu's secure context */
Soby Mathewda43b662015-07-08 21:45:46 +0100143 cm_init_my_context(&tsp_on_entrypoint);
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100144
Soby Mathewbec98512015-09-03 18:29:38 +0100145#if TSP_NS_INTR_ASYNC_PREEMPT
Soby Mathew47903c02015-01-13 15:48:26 +0000146 /*
147 * Disable the NS interrupt locally since it will be enabled globally
Soby Mathewda43b662015-07-08 21:45:46 +0100148 * within cm_init_my_context.
Soby Mathew47903c02015-01-13 15:48:26 +0000149 */
150 disable_intr_rm_local(INTR_TYPE_NS, SECURE);
151#endif
152
Achin Gupta607084e2014-02-09 18:24:19 +0000153 /* Enter the TSP */
154 rc = tspd_synchronous_sp_entry(tsp_ctx);
155
156 /*
157 * Read the response from the TSP. A non-zero return means that
158 * something went wrong while communicating with the SP.
159 */
160 if (rc != 0)
161 panic();
162
163 /* Update its context to reflect the state the SP is in */
Achin Gupta18d6eaf2014-05-04 18:23:26 +0100164 set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON);
Achin Gupta607084e2014-02-09 18:24:19 +0000165}
166
167/*******************************************************************************
168 * This cpu has resumed from suspend. The SPD saved the TSP context when it
169 * completed the preceding suspend call. Use that context to program an entry
170 * into the TSP to allow it to do any remaining book keeping
171 ******************************************************************************/
Achin Gupta9a0ff9b2015-09-07 20:43:27 +0100172static void tspd_cpu_suspend_finish_handler(uint64_t max_off_pwrlvl)
Achin Gupta607084e2014-02-09 18:24:19 +0000173{
174 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +0100175 uint32_t linear_id = plat_my_core_pos();
Dan Handleye2712bc2014-04-10 15:37:22 +0100176 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Achin Gupta607084e2014-02-09 18:24:19 +0000177
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100178 assert(tsp_vectors);
Achin Gupta18d6eaf2014-05-04 18:23:26 +0100179 assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_SUSPEND);
Achin Gupta607084e2014-02-09 18:24:19 +0000180
Achin Gupta9a0ff9b2015-09-07 20:43:27 +0100181 /* Program the entry point, max_off_pwrlvl and enter the SP */
Achin Gupta607084e2014-02-09 18:24:19 +0000182 write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
183 CTX_GPREG_X0,
Achin Gupta9a0ff9b2015-09-07 20:43:27 +0100184 max_off_pwrlvl);
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100185 cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_resume_entry);
Achin Gupta607084e2014-02-09 18:24:19 +0000186 rc = tspd_synchronous_sp_entry(tsp_ctx);
187
188 /*
189 * Read the response from the TSP. A non-zero return means that
190 * something went wrong while communicating with the TSP.
191 */
192 if (rc != 0)
193 panic();
194
195 /* Update its context to reflect the state the SP is in */
Achin Gupta18d6eaf2014-05-04 18:23:26 +0100196 set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON);
Achin Gupta607084e2014-02-09 18:24:19 +0000197}
198
199/*******************************************************************************
200 * Return the type of TSP the TSPD is dealing with. Report the current resident
201 * cpu (mpidr format) if it is a UP/UP migratable TSP.
202 ******************************************************************************/
203static int32_t tspd_cpu_migrate_info(uint64_t *resident_cpu)
204{
205 return TSP_MIGRATE_INFO;
206}
207
208/*******************************************************************************
Juan Castillo4dc4a472014-08-12 11:17:06 +0100209 * System is about to be switched off. Allow the TSPD/TSP to perform
210 * any actions needed.
211 ******************************************************************************/
212static void tspd_system_off(void)
213{
Soby Mathewda43b662015-07-08 21:45:46 +0100214 uint32_t linear_id = plat_my_core_pos();
Juan Castillo4dc4a472014-08-12 11:17:06 +0100215 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
216
217 assert(tsp_vectors);
218 assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
219
Douglas Raillardf2129652016-11-24 15:43:19 +0000220 /*
221 * Abort any preempted SMC request before overwriting the SECURE
222 * context.
223 */
224 tspd_abort_preempted_smc(tsp_ctx);
225
Juan Castillo4dc4a472014-08-12 11:17:06 +0100226 /* Program the entry point */
227 cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_off_entry);
228
229 /* Enter the TSP. We do not care about the return value because we
230 * must continue the shutdown anyway */
231 tspd_synchronous_sp_entry(tsp_ctx);
232}
233
234/*******************************************************************************
235 * System is about to be reset. Allow the TSPD/TSP to perform
236 * any actions needed.
237 ******************************************************************************/
238static void tspd_system_reset(void)
239{
Soby Mathewda43b662015-07-08 21:45:46 +0100240 uint32_t linear_id = plat_my_core_pos();
Juan Castillo4dc4a472014-08-12 11:17:06 +0100241 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
242
243 assert(tsp_vectors);
244 assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
245
Douglas Raillardf2129652016-11-24 15:43:19 +0000246 /*
247 * Abort any preempted SMC request before overwriting the SECURE
248 * context.
249 */
250 tspd_abort_preempted_smc(tsp_ctx);
251
Juan Castillo4dc4a472014-08-12 11:17:06 +0100252 /* Program the entry point */
253 cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_reset_entry);
254
Douglas Raillardf2129652016-11-24 15:43:19 +0000255 /*
256 * Enter the TSP. We do not care about the return value because we
257 * must continue the reset anyway
258 */
Juan Castillo4dc4a472014-08-12 11:17:06 +0100259 tspd_synchronous_sp_entry(tsp_ctx);
260}
261
262/*******************************************************************************
Achin Gupta607084e2014-02-09 18:24:19 +0000263 * Structure populated by the TSP Dispatcher to be given a chance to perform any
264 * TSP bookkeeping before PSCI executes a power mgmt. operation.
265 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100266const spd_pm_ops_t tspd_pm = {
Juan Castillo4dc4a472014-08-12 11:17:06 +0100267 .svc_on = tspd_cpu_on_handler,
268 .svc_off = tspd_cpu_off_handler,
269 .svc_suspend = tspd_cpu_suspend_handler,
270 .svc_on_finish = tspd_cpu_on_finish_handler,
271 .svc_suspend_finish = tspd_cpu_suspend_finish_handler,
272 .svc_migrate = NULL,
273 .svc_migrate_info = tspd_cpu_migrate_info,
274 .svc_system_off = tspd_system_off,
275 .svc_system_reset = tspd_system_reset
Achin Gupta607084e2014-02-09 18:24:19 +0000276};