xref: /rk3399_ARM-atf/services/spd/tspd/tspd_pm.c (revision 3df6012a3eff73d75d747187d7cfac1fd6d7819f)
1607084eeSAchin Gupta /*
2*3df6012aSDouglas Raillard  * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
3607084eeSAchin Gupta  *
4607084eeSAchin Gupta  * Redistribution and use in source and binary forms, with or without
5607084eeSAchin Gupta  * modification, are permitted provided that the following conditions are met:
6607084eeSAchin Gupta  *
7607084eeSAchin Gupta  * Redistributions of source code must retain the above copyright notice, this
8607084eeSAchin Gupta  * list of conditions and the following disclaimer.
9607084eeSAchin Gupta  *
10607084eeSAchin Gupta  * Redistributions in binary form must reproduce the above copyright notice,
11607084eeSAchin Gupta  * this list of conditions and the following disclaimer in the documentation
12607084eeSAchin Gupta  * and/or other materials provided with the distribution.
13607084eeSAchin Gupta  *
14607084eeSAchin Gupta  * Neither the name of ARM nor the names of its contributors may be used
15607084eeSAchin Gupta  * to endorse or promote products derived from this software without specific
16607084eeSAchin Gupta  * prior written permission.
17607084eeSAchin Gupta  *
18607084eeSAchin Gupta  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19607084eeSAchin Gupta  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20607084eeSAchin Gupta  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21607084eeSAchin Gupta  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22607084eeSAchin Gupta  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23607084eeSAchin Gupta  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24607084eeSAchin Gupta  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25607084eeSAchin Gupta  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26607084eeSAchin Gupta  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27607084eeSAchin Gupta  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28607084eeSAchin Gupta  * POSSIBILITY OF SUCH DAMAGE.
29607084eeSAchin Gupta  */
30607084eeSAchin Gupta 
31607084eeSAchin Gupta #include <arch_helpers.h>
3297043ac9SDan Handley #include <assert.h>
3397043ac9SDan Handley #include <bl_common.h>
34607084eeSAchin Gupta #include <context_mgmt.h>
35607084eeSAchin Gupta #include <debug.h>
365f0cdb05SDan Handley #include <platform.h>
3797043ac9SDan Handley #include <tsp.h>
3835e98e55SDan Handley #include "tspd_private.h"
39607084eeSAchin Gupta 
40607084eeSAchin Gupta /*******************************************************************************
41607084eeSAchin Gupta  * The target cpu is being turned on. Allow the TSPD/TSP to perform any actions
42607084eeSAchin Gupta  * needed. Nothing at the moment.
43607084eeSAchin Gupta  ******************************************************************************/
44607084eeSAchin Gupta static void tspd_cpu_on_handler(uint64_t target_cpu)
45607084eeSAchin Gupta {
46607084eeSAchin Gupta }
47607084eeSAchin Gupta 
48607084eeSAchin Gupta /*******************************************************************************
49607084eeSAchin Gupta  * This cpu is being turned off. Allow the TSPD/TSP to perform any actions
50607084eeSAchin Gupta  * needed
51607084eeSAchin Gupta  ******************************************************************************/
5231244d74SSoby Mathew static int32_t tspd_cpu_off_handler(uint64_t unused)
53607084eeSAchin Gupta {
54607084eeSAchin Gupta 	int32_t rc = 0;
55fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
56fb037bfbSDan Handley 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
57607084eeSAchin Gupta 
58399fb08fSAndrew Thoelke 	assert(tsp_vectors);
593ee8a164SAchin Gupta 	assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
60607084eeSAchin Gupta 
61*3df6012aSDouglas Raillard 	/*
62*3df6012aSDouglas Raillard 	 * Abort any preempted SMC request before overwriting the SECURE
63*3df6012aSDouglas Raillard 	 * context.
64*3df6012aSDouglas Raillard 	 */
65*3df6012aSDouglas Raillard 	tspd_abort_preempted_smc(tsp_ctx);
66*3df6012aSDouglas Raillard 
67607084eeSAchin Gupta 	/* Program the entry point and enter the TSP */
68399fb08fSAndrew Thoelke 	cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_off_entry);
69607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
70607084eeSAchin Gupta 
71607084eeSAchin Gupta 	/*
72607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
73607084eeSAchin Gupta 	 * something went wrong while communicating with the TSP.
74607084eeSAchin Gupta 	 */
75607084eeSAchin Gupta 	if (rc != 0)
76607084eeSAchin Gupta 		panic();
77607084eeSAchin Gupta 
78607084eeSAchin Gupta 	/*
79607084eeSAchin Gupta 	 * Reset TSP's context for a fresh start when this cpu is turned on
80607084eeSAchin Gupta 	 * subsequently.
81607084eeSAchin Gupta 	 */
823ee8a164SAchin Gupta 	set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF);
83607084eeSAchin Gupta 
84607084eeSAchin Gupta 	return 0;
85607084eeSAchin Gupta }
86607084eeSAchin Gupta 
87607084eeSAchin Gupta /*******************************************************************************
88607084eeSAchin Gupta  * This cpu is being suspended. S-EL1 state must have been saved in the
89607084eeSAchin Gupta  * resident cpu (mpidr format) if it is a UP/UP migratable TSP.
90607084eeSAchin Gupta  ******************************************************************************/
91f1054c93SAchin Gupta static void tspd_cpu_suspend_handler(uint64_t max_off_pwrlvl)
92607084eeSAchin Gupta {
93607084eeSAchin Gupta 	int32_t rc = 0;
94fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
95fb037bfbSDan Handley 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
96607084eeSAchin Gupta 
97399fb08fSAndrew Thoelke 	assert(tsp_vectors);
983ee8a164SAchin Gupta 	assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
99607084eeSAchin Gupta 
100*3df6012aSDouglas Raillard 	/*
101*3df6012aSDouglas Raillard 	 * Abort any preempted SMC request before overwriting the SECURE
102*3df6012aSDouglas Raillard 	 * context.
103*3df6012aSDouglas Raillard 	 */
104*3df6012aSDouglas Raillard 	tspd_abort_preempted_smc(tsp_ctx);
105*3df6012aSDouglas Raillard 
10631244d74SSoby Mathew 	/* Program the entry point and enter the TSP */
107399fb08fSAndrew Thoelke 	cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_suspend_entry);
108607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
109607084eeSAchin Gupta 
110607084eeSAchin Gupta 	/*
111607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
112607084eeSAchin Gupta 	 * something went wrong while communicating with the TSP.
113607084eeSAchin Gupta 	 */
114*3df6012aSDouglas Raillard 	if (rc)
115607084eeSAchin Gupta 		panic();
116607084eeSAchin Gupta 
117607084eeSAchin Gupta 	/* Update its context to reflect the state the TSP is in */
1183ee8a164SAchin Gupta 	set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_SUSPEND);
119607084eeSAchin Gupta }
120607084eeSAchin Gupta 
121607084eeSAchin Gupta /*******************************************************************************
122607084eeSAchin Gupta  * This cpu has been turned on. Enter the TSP to initialise S-EL1 and other bits
123*3df6012aSDouglas Raillard  * before passing control back to the Secure Monitor. Entry in S-EL1 is done
124607084eeSAchin Gupta  * after initialising minimal architectural state that guarantees safe
125607084eeSAchin Gupta  * execution.
126607084eeSAchin Gupta  ******************************************************************************/
12731244d74SSoby Mathew static void tspd_cpu_on_finish_handler(uint64_t unused)
128607084eeSAchin Gupta {
129607084eeSAchin Gupta 	int32_t rc = 0;
130fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
131fb037bfbSDan Handley 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
13250e27dadSVikram Kanigiri 	entry_point_info_t tsp_on_entrypoint;
133607084eeSAchin Gupta 
134399fb08fSAndrew Thoelke 	assert(tsp_vectors);
1353ee8a164SAchin Gupta 	assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_OFF);
136607084eeSAchin Gupta 
13750e27dadSVikram Kanigiri 	tspd_init_tsp_ep_state(&tsp_on_entrypoint,
138607084eeSAchin Gupta 				TSP_AARCH64,
13950e27dadSVikram Kanigiri 				(uint64_t) &tsp_vectors->cpu_on_entry,
140607084eeSAchin Gupta 				tsp_ctx);
141607084eeSAchin Gupta 
14250e27dadSVikram Kanigiri 	/* Initialise this cpu's secure context */
143fd650ff6SSoby Mathew 	cm_init_my_context(&tsp_on_entrypoint);
14450e27dadSVikram Kanigiri 
14502446137SSoby Mathew #if TSP_NS_INTR_ASYNC_PREEMPT
146f4f1ae77SSoby Mathew 	/*
147f4f1ae77SSoby Mathew 	 * Disable the NS interrupt locally since it will be enabled globally
148fd650ff6SSoby Mathew 	 * within cm_init_my_context.
149f4f1ae77SSoby Mathew 	 */
150f4f1ae77SSoby Mathew 	disable_intr_rm_local(INTR_TYPE_NS, SECURE);
151f4f1ae77SSoby Mathew #endif
152f4f1ae77SSoby Mathew 
153607084eeSAchin Gupta 	/* Enter the TSP */
154607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
155607084eeSAchin Gupta 
156607084eeSAchin Gupta 	/*
157607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
158607084eeSAchin Gupta 	 * something went wrong while communicating with the SP.
159607084eeSAchin Gupta 	 */
160607084eeSAchin Gupta 	if (rc != 0)
161607084eeSAchin Gupta 		panic();
162607084eeSAchin Gupta 
163607084eeSAchin Gupta 	/* Update its context to reflect the state the SP is in */
1643ee8a164SAchin Gupta 	set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON);
165607084eeSAchin Gupta }
166607084eeSAchin Gupta 
167607084eeSAchin Gupta /*******************************************************************************
168607084eeSAchin Gupta  * This cpu has resumed from suspend. The SPD saved the TSP context when it
169607084eeSAchin Gupta  * completed the preceding suspend call. Use that context to program an entry
170607084eeSAchin Gupta  * into the TSP to allow it to do any remaining book keeping
171607084eeSAchin Gupta  ******************************************************************************/
172f1054c93SAchin Gupta static void tspd_cpu_suspend_finish_handler(uint64_t max_off_pwrlvl)
173607084eeSAchin Gupta {
174607084eeSAchin Gupta 	int32_t rc = 0;
175fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
176fb037bfbSDan Handley 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
177607084eeSAchin Gupta 
178399fb08fSAndrew Thoelke 	assert(tsp_vectors);
1793ee8a164SAchin Gupta 	assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_SUSPEND);
180607084eeSAchin Gupta 
181f1054c93SAchin Gupta 	/* Program the entry point, max_off_pwrlvl and enter the SP */
182607084eeSAchin Gupta 	write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
183607084eeSAchin Gupta 		      CTX_GPREG_X0,
184f1054c93SAchin Gupta 		      max_off_pwrlvl);
185399fb08fSAndrew Thoelke 	cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_resume_entry);
186607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
187607084eeSAchin Gupta 
188607084eeSAchin Gupta 	/*
189607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
190607084eeSAchin Gupta 	 * something went wrong while communicating with the TSP.
191607084eeSAchin Gupta 	 */
192607084eeSAchin Gupta 	if (rc != 0)
193607084eeSAchin Gupta 		panic();
194607084eeSAchin Gupta 
195607084eeSAchin Gupta 	/* Update its context to reflect the state the SP is in */
1963ee8a164SAchin Gupta 	set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON);
197607084eeSAchin Gupta }
198607084eeSAchin Gupta 
199607084eeSAchin Gupta /*******************************************************************************
200607084eeSAchin Gupta  * Return the type of TSP the TSPD is dealing with. Report the current resident
201607084eeSAchin Gupta  * cpu (mpidr format) if it is a UP/UP migratable TSP.
202607084eeSAchin Gupta  ******************************************************************************/
203607084eeSAchin Gupta static int32_t tspd_cpu_migrate_info(uint64_t *resident_cpu)
204607084eeSAchin Gupta {
205607084eeSAchin Gupta 	return TSP_MIGRATE_INFO;
206607084eeSAchin Gupta }
207607084eeSAchin Gupta 
208607084eeSAchin Gupta /*******************************************************************************
209d5f13093SJuan Castillo  * System is about to be switched off. Allow the TSPD/TSP to perform
210d5f13093SJuan Castillo  * any actions needed.
211d5f13093SJuan Castillo  ******************************************************************************/
212d5f13093SJuan Castillo static void tspd_system_off(void)
213d5f13093SJuan Castillo {
214fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
215d5f13093SJuan Castillo 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
216d5f13093SJuan Castillo 
217d5f13093SJuan Castillo 	assert(tsp_vectors);
218d5f13093SJuan Castillo 	assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
219d5f13093SJuan Castillo 
220*3df6012aSDouglas Raillard 	/*
221*3df6012aSDouglas Raillard 	 * Abort any preempted SMC request before overwriting the SECURE
222*3df6012aSDouglas Raillard 	 * context.
223*3df6012aSDouglas Raillard 	 */
224*3df6012aSDouglas Raillard 	tspd_abort_preempted_smc(tsp_ctx);
225*3df6012aSDouglas Raillard 
226d5f13093SJuan Castillo 	/* Program the entry point */
227d5f13093SJuan Castillo 	cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_off_entry);
228d5f13093SJuan Castillo 
229d5f13093SJuan Castillo 	/* Enter the TSP. We do not care about the return value because we
230d5f13093SJuan Castillo 	 * must continue the shutdown anyway */
231d5f13093SJuan Castillo 	tspd_synchronous_sp_entry(tsp_ctx);
232d5f13093SJuan Castillo }
233d5f13093SJuan Castillo 
234d5f13093SJuan Castillo /*******************************************************************************
235d5f13093SJuan Castillo  * System is about to be reset. Allow the TSPD/TSP to perform
236d5f13093SJuan Castillo  * any actions needed.
237d5f13093SJuan Castillo  ******************************************************************************/
238d5f13093SJuan Castillo static void tspd_system_reset(void)
239d5f13093SJuan Castillo {
240fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
241d5f13093SJuan Castillo 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
242d5f13093SJuan Castillo 
243d5f13093SJuan Castillo 	assert(tsp_vectors);
244d5f13093SJuan Castillo 	assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
245d5f13093SJuan Castillo 
246*3df6012aSDouglas Raillard 	/*
247*3df6012aSDouglas Raillard 	 * Abort any preempted SMC request before overwriting the SECURE
248*3df6012aSDouglas Raillard 	 * context.
249*3df6012aSDouglas Raillard 	 */
250*3df6012aSDouglas Raillard 	tspd_abort_preempted_smc(tsp_ctx);
251*3df6012aSDouglas Raillard 
252d5f13093SJuan Castillo 	/* Program the entry point */
253d5f13093SJuan Castillo 	cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_reset_entry);
254d5f13093SJuan Castillo 
255*3df6012aSDouglas Raillard 	/*
256*3df6012aSDouglas Raillard 	 * Enter the TSP. We do not care about the return value because we
257*3df6012aSDouglas Raillard 	 * must continue the reset anyway
258*3df6012aSDouglas Raillard 	 */
259d5f13093SJuan Castillo 	tspd_synchronous_sp_entry(tsp_ctx);
260d5f13093SJuan Castillo }
261d5f13093SJuan Castillo 
262d5f13093SJuan Castillo /*******************************************************************************
263607084eeSAchin Gupta  * Structure populated by the TSP Dispatcher to be given a chance to perform any
264607084eeSAchin Gupta  * TSP bookkeeping before PSCI executes a power mgmt.  operation.
265607084eeSAchin Gupta  ******************************************************************************/
266fb037bfbSDan Handley const spd_pm_ops_t tspd_pm = {
267d5f13093SJuan Castillo 	.svc_on = tspd_cpu_on_handler,
268d5f13093SJuan Castillo 	.svc_off = tspd_cpu_off_handler,
269d5f13093SJuan Castillo 	.svc_suspend = tspd_cpu_suspend_handler,
270d5f13093SJuan Castillo 	.svc_on_finish = tspd_cpu_on_finish_handler,
271d5f13093SJuan Castillo 	.svc_suspend_finish = tspd_cpu_suspend_finish_handler,
272d5f13093SJuan Castillo 	.svc_migrate = NULL,
273d5f13093SJuan Castillo 	.svc_migrate_info = tspd_cpu_migrate_info,
274d5f13093SJuan Castillo 	.svc_system_off = tspd_system_off,
275d5f13093SJuan Castillo 	.svc_system_reset = tspd_system_reset
276607084eeSAchin Gupta };
277