blob: 9414c154e5b78edd3e4f9b0812a283dc023150b8 [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 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Achin Gupta607084e2014-02-09 18:24:19 +00005 */
6
Achin Gupta607084e2014-02-09 18:24:19 +00007#include <arch_helpers.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +01008#include <assert.h>
9#include <bl_common.h>
Achin Gupta607084e2014-02-09 18:24:19 +000010#include <context_mgmt.h>
Achin Gupta607084e2014-02-09 18:24:19 +000011#include <debug.h>
Dan Handleyed6ff952014-05-14 17:44:19 +010012#include <platform.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010013#include <tsp.h>
Dan Handley714a0d22014-04-09 13:13:04 +010014#include "tspd_private.h"
Achin Gupta607084e2014-02-09 18:24:19 +000015
16/*******************************************************************************
17 * The target cpu is being turned on. Allow the TSPD/TSP to perform any actions
18 * needed. Nothing at the moment.
19 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +090020static void tspd_cpu_on_handler(u_register_t target_cpu)
Achin Gupta607084e2014-02-09 18:24:19 +000021{
22}
23
24/*******************************************************************************
25 * This cpu is being turned off. Allow the TSPD/TSP to perform any actions
26 * needed
27 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +090028static int32_t tspd_cpu_off_handler(u_register_t unused)
Achin Gupta607084e2014-02-09 18:24:19 +000029{
30 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +010031 uint32_t linear_id = plat_my_core_pos();
Dan Handleye2712bc2014-04-10 15:37:22 +010032 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Achin Gupta607084e2014-02-09 18:24:19 +000033
Andrew Thoelke891c4ca2014-05-20 21:43:27 +010034 assert(tsp_vectors);
Achin Gupta18d6eaf2014-05-04 18:23:26 +010035 assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
Achin Gupta607084e2014-02-09 18:24:19 +000036
Douglas Raillardf2129652016-11-24 15:43:19 +000037 /*
38 * Abort any preempted SMC request before overwriting the SECURE
39 * context.
40 */
41 tspd_abort_preempted_smc(tsp_ctx);
42
Achin Gupta607084e2014-02-09 18:24:19 +000043 /* Program the entry point and enter the TSP */
Andrew Thoelke891c4ca2014-05-20 21:43:27 +010044 cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_off_entry);
Achin Gupta607084e2014-02-09 18:24:19 +000045 rc = tspd_synchronous_sp_entry(tsp_ctx);
46
47 /*
48 * Read the response from the TSP. A non-zero return means that
49 * something went wrong while communicating with the TSP.
50 */
51 if (rc != 0)
52 panic();
53
54 /*
55 * Reset TSP's context for a fresh start when this cpu is turned on
56 * subsequently.
57 */
Achin Gupta18d6eaf2014-05-04 18:23:26 +010058 set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF);
Achin Gupta607084e2014-02-09 18:24:19 +000059
Douglas Raillardf2129652016-11-24 15:43:19 +000060 return 0;
Achin Gupta607084e2014-02-09 18:24:19 +000061}
62
63/*******************************************************************************
64 * This cpu is being suspended. S-EL1 state must have been saved in the
65 * resident cpu (mpidr format) if it is a UP/UP migratable TSP.
66 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +090067static void tspd_cpu_suspend_handler(u_register_t max_off_pwrlvl)
Achin Gupta607084e2014-02-09 18:24:19 +000068{
69 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +010070 uint32_t linear_id = plat_my_core_pos();
Dan Handleye2712bc2014-04-10 15:37:22 +010071 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Achin Gupta607084e2014-02-09 18:24:19 +000072
Andrew Thoelke891c4ca2014-05-20 21:43:27 +010073 assert(tsp_vectors);
Achin Gupta18d6eaf2014-05-04 18:23:26 +010074 assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
Achin Gupta607084e2014-02-09 18:24:19 +000075
Douglas Raillardf2129652016-11-24 15:43:19 +000076 /*
77 * Abort any preempted SMC request before overwriting the SECURE
78 * context.
79 */
80 tspd_abort_preempted_smc(tsp_ctx);
81
Soby Mathewf5121572014-09-30 11:19:51 +010082 /* Program the entry point and enter the TSP */
Andrew Thoelke891c4ca2014-05-20 21:43:27 +010083 cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_suspend_entry);
Achin Gupta607084e2014-02-09 18:24:19 +000084 rc = tspd_synchronous_sp_entry(tsp_ctx);
85
86 /*
87 * Read the response from the TSP. A non-zero return means that
88 * something went wrong while communicating with the TSP.
89 */
Douglas Raillardf2129652016-11-24 15:43:19 +000090 if (rc)
Achin Gupta607084e2014-02-09 18:24:19 +000091 panic();
92
93 /* Update its context to reflect the state the TSP is in */
Achin Gupta18d6eaf2014-05-04 18:23:26 +010094 set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_SUSPEND);
Achin Gupta607084e2014-02-09 18:24:19 +000095}
96
97/*******************************************************************************
98 * This cpu has been turned on. Enter the TSP to initialise S-EL1 and other bits
Douglas Raillardf2129652016-11-24 15:43:19 +000099 * before passing control back to the Secure Monitor. Entry in S-EL1 is done
Achin Gupta607084e2014-02-09 18:24:19 +0000100 * after initialising minimal architectural state that guarantees safe
101 * execution.
102 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +0900103static void tspd_cpu_on_finish_handler(u_register_t unused)
Achin Gupta607084e2014-02-09 18:24:19 +0000104{
105 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +0100106 uint32_t linear_id = plat_my_core_pos();
Dan Handleye2712bc2014-04-10 15:37:22 +0100107 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100108 entry_point_info_t tsp_on_entrypoint;
Achin Gupta607084e2014-02-09 18:24:19 +0000109
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100110 assert(tsp_vectors);
Achin Gupta18d6eaf2014-05-04 18:23:26 +0100111 assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_OFF);
Achin Gupta607084e2014-02-09 18:24:19 +0000112
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100113 tspd_init_tsp_ep_state(&tsp_on_entrypoint,
Achin Gupta607084e2014-02-09 18:24:19 +0000114 TSP_AARCH64,
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100115 (uint64_t) &tsp_vectors->cpu_on_entry,
Achin Gupta607084e2014-02-09 18:24:19 +0000116 tsp_ctx);
117
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100118 /* Initialise this cpu's secure context */
Soby Mathewda43b662015-07-08 21:45:46 +0100119 cm_init_my_context(&tsp_on_entrypoint);
Vikram Kanigiri9d70f0f2014-07-15 16:46:43 +0100120
Soby Mathewbec98512015-09-03 18:29:38 +0100121#if TSP_NS_INTR_ASYNC_PREEMPT
Soby Mathew47903c02015-01-13 15:48:26 +0000122 /*
123 * Disable the NS interrupt locally since it will be enabled globally
Soby Mathewda43b662015-07-08 21:45:46 +0100124 * within cm_init_my_context.
Soby Mathew47903c02015-01-13 15:48:26 +0000125 */
126 disable_intr_rm_local(INTR_TYPE_NS, SECURE);
127#endif
128
Achin Gupta607084e2014-02-09 18:24:19 +0000129 /* Enter the TSP */
130 rc = tspd_synchronous_sp_entry(tsp_ctx);
131
132 /*
133 * Read the response from the TSP. A non-zero return means that
134 * something went wrong while communicating with the SP.
135 */
136 if (rc != 0)
137 panic();
138
139 /* Update its context to reflect the state the SP is in */
Achin Gupta18d6eaf2014-05-04 18:23:26 +0100140 set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON);
Achin Gupta607084e2014-02-09 18:24:19 +0000141}
142
143/*******************************************************************************
144 * This cpu has resumed from suspend. The SPD saved the TSP context when it
145 * completed the preceding suspend call. Use that context to program an entry
146 * into the TSP to allow it to do any remaining book keeping
147 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +0900148static void tspd_cpu_suspend_finish_handler(u_register_t max_off_pwrlvl)
Achin Gupta607084e2014-02-09 18:24:19 +0000149{
150 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +0100151 uint32_t linear_id = plat_my_core_pos();
Dan Handleye2712bc2014-04-10 15:37:22 +0100152 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Achin Gupta607084e2014-02-09 18:24:19 +0000153
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100154 assert(tsp_vectors);
Achin Gupta18d6eaf2014-05-04 18:23:26 +0100155 assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_SUSPEND);
Achin Gupta607084e2014-02-09 18:24:19 +0000156
Achin Gupta9a0ff9b2015-09-07 20:43:27 +0100157 /* Program the entry point, max_off_pwrlvl and enter the SP */
Achin Gupta607084e2014-02-09 18:24:19 +0000158 write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
159 CTX_GPREG_X0,
Achin Gupta9a0ff9b2015-09-07 20:43:27 +0100160 max_off_pwrlvl);
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100161 cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_resume_entry);
Achin Gupta607084e2014-02-09 18:24:19 +0000162 rc = tspd_synchronous_sp_entry(tsp_ctx);
163
164 /*
165 * Read the response from the TSP. A non-zero return means that
166 * something went wrong while communicating with the TSP.
167 */
168 if (rc != 0)
169 panic();
170
171 /* Update its context to reflect the state the SP is in */
Achin Gupta18d6eaf2014-05-04 18:23:26 +0100172 set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON);
Achin Gupta607084e2014-02-09 18:24:19 +0000173}
174
175/*******************************************************************************
176 * Return the type of TSP the TSPD is dealing with. Report the current resident
177 * cpu (mpidr format) if it is a UP/UP migratable TSP.
178 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +0900179static int32_t tspd_cpu_migrate_info(u_register_t *resident_cpu)
Achin Gupta607084e2014-02-09 18:24:19 +0000180{
181 return TSP_MIGRATE_INFO;
182}
183
184/*******************************************************************************
Juan Castillo4dc4a472014-08-12 11:17:06 +0100185 * System is about to be switched off. Allow the TSPD/TSP to perform
186 * any actions needed.
187 ******************************************************************************/
188static void tspd_system_off(void)
189{
Soby Mathewda43b662015-07-08 21:45:46 +0100190 uint32_t linear_id = plat_my_core_pos();
Juan Castillo4dc4a472014-08-12 11:17:06 +0100191 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
192
193 assert(tsp_vectors);
194 assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
195
Douglas Raillardf2129652016-11-24 15:43:19 +0000196 /*
197 * Abort any preempted SMC request before overwriting the SECURE
198 * context.
199 */
200 tspd_abort_preempted_smc(tsp_ctx);
201
Juan Castillo4dc4a472014-08-12 11:17:06 +0100202 /* Program the entry point */
203 cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_off_entry);
204
205 /* Enter the TSP. We do not care about the return value because we
206 * must continue the shutdown anyway */
207 tspd_synchronous_sp_entry(tsp_ctx);
208}
209
210/*******************************************************************************
211 * System is about to be reset. Allow the TSPD/TSP to perform
212 * any actions needed.
213 ******************************************************************************/
214static void tspd_system_reset(void)
215{
Soby Mathewda43b662015-07-08 21:45:46 +0100216 uint32_t linear_id = plat_my_core_pos();
Juan Castillo4dc4a472014-08-12 11:17:06 +0100217 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
218
219 assert(tsp_vectors);
220 assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
221
Douglas Raillardf2129652016-11-24 15:43:19 +0000222 /*
223 * Abort any preempted SMC request before overwriting the SECURE
224 * context.
225 */
226 tspd_abort_preempted_smc(tsp_ctx);
227
Juan Castillo4dc4a472014-08-12 11:17:06 +0100228 /* Program the entry point */
229 cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_reset_entry);
230
Douglas Raillardf2129652016-11-24 15:43:19 +0000231 /*
232 * Enter the TSP. We do not care about the return value because we
233 * must continue the reset anyway
234 */
Juan Castillo4dc4a472014-08-12 11:17:06 +0100235 tspd_synchronous_sp_entry(tsp_ctx);
236}
237
238/*******************************************************************************
Achin Gupta607084e2014-02-09 18:24:19 +0000239 * Structure populated by the TSP Dispatcher to be given a chance to perform any
240 * TSP bookkeeping before PSCI executes a power mgmt. operation.
241 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100242const spd_pm_ops_t tspd_pm = {
Juan Castillo4dc4a472014-08-12 11:17:06 +0100243 .svc_on = tspd_cpu_on_handler,
244 .svc_off = tspd_cpu_off_handler,
245 .svc_suspend = tspd_cpu_suspend_handler,
246 .svc_on_finish = tspd_cpu_on_finish_handler,
247 .svc_suspend_finish = tspd_cpu_suspend_finish_handler,
248 .svc_migrate = NULL,
249 .svc_migrate_info = tspd_cpu_migrate_info,
250 .svc_system_off = tspd_system_off,
251 .svc_system_reset = tspd_system_reset
Achin Gupta607084e2014-02-09 18:24:19 +0000252};