xref: /rk3399_ARM-atf/services/spd/tspd/tspd_pm.c (revision 82cb2c1ad9897473743f08437d0a3995bed561b9)
1607084eeSAchin Gupta /*
23df6012aSDouglas Raillard  * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
3607084eeSAchin Gupta  *
4*82cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
5607084eeSAchin Gupta  */
6607084eeSAchin Gupta 
7607084eeSAchin Gupta #include <arch_helpers.h>
897043ac9SDan Handley #include <assert.h>
997043ac9SDan Handley #include <bl_common.h>
10607084eeSAchin Gupta #include <context_mgmt.h>
11607084eeSAchin Gupta #include <debug.h>
125f0cdb05SDan Handley #include <platform.h>
1397043ac9SDan Handley #include <tsp.h>
1435e98e55SDan Handley #include "tspd_private.h"
15607084eeSAchin Gupta 
16607084eeSAchin Gupta /*******************************************************************************
17607084eeSAchin Gupta  * The target cpu is being turned on. Allow the TSPD/TSP to perform any actions
18607084eeSAchin Gupta  * needed. Nothing at the moment.
19607084eeSAchin Gupta  ******************************************************************************/
20607084eeSAchin Gupta static void tspd_cpu_on_handler(uint64_t target_cpu)
21607084eeSAchin Gupta {
22607084eeSAchin Gupta }
23607084eeSAchin Gupta 
24607084eeSAchin Gupta /*******************************************************************************
25607084eeSAchin Gupta  * This cpu is being turned off. Allow the TSPD/TSP to perform any actions
26607084eeSAchin Gupta  * needed
27607084eeSAchin Gupta  ******************************************************************************/
2831244d74SSoby Mathew static int32_t tspd_cpu_off_handler(uint64_t unused)
29607084eeSAchin Gupta {
30607084eeSAchin Gupta 	int32_t rc = 0;
31fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
32fb037bfbSDan Handley 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
33607084eeSAchin Gupta 
34399fb08fSAndrew Thoelke 	assert(tsp_vectors);
353ee8a164SAchin Gupta 	assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
36607084eeSAchin Gupta 
373df6012aSDouglas Raillard 	/*
383df6012aSDouglas Raillard 	 * Abort any preempted SMC request before overwriting the SECURE
393df6012aSDouglas Raillard 	 * context.
403df6012aSDouglas Raillard 	 */
413df6012aSDouglas Raillard 	tspd_abort_preempted_smc(tsp_ctx);
423df6012aSDouglas Raillard 
43607084eeSAchin Gupta 	/* Program the entry point and enter the TSP */
44399fb08fSAndrew Thoelke 	cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_off_entry);
45607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
46607084eeSAchin Gupta 
47607084eeSAchin Gupta 	/*
48607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
49607084eeSAchin Gupta 	 * something went wrong while communicating with the TSP.
50607084eeSAchin Gupta 	 */
51607084eeSAchin Gupta 	if (rc != 0)
52607084eeSAchin Gupta 		panic();
53607084eeSAchin Gupta 
54607084eeSAchin Gupta 	/*
55607084eeSAchin Gupta 	 * Reset TSP's context for a fresh start when this cpu is turned on
56607084eeSAchin Gupta 	 * subsequently.
57607084eeSAchin Gupta 	 */
583ee8a164SAchin Gupta 	set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF);
59607084eeSAchin Gupta 
60607084eeSAchin Gupta 	return 0;
61607084eeSAchin Gupta }
62607084eeSAchin Gupta 
63607084eeSAchin Gupta /*******************************************************************************
64607084eeSAchin Gupta  * This cpu is being suspended. S-EL1 state must have been saved in the
65607084eeSAchin Gupta  * resident cpu (mpidr format) if it is a UP/UP migratable TSP.
66607084eeSAchin Gupta  ******************************************************************************/
67f1054c93SAchin Gupta static void tspd_cpu_suspend_handler(uint64_t max_off_pwrlvl)
68607084eeSAchin Gupta {
69607084eeSAchin Gupta 	int32_t rc = 0;
70fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
71fb037bfbSDan Handley 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
72607084eeSAchin Gupta 
73399fb08fSAndrew Thoelke 	assert(tsp_vectors);
743ee8a164SAchin Gupta 	assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
75607084eeSAchin Gupta 
763df6012aSDouglas Raillard 	/*
773df6012aSDouglas Raillard 	 * Abort any preempted SMC request before overwriting the SECURE
783df6012aSDouglas Raillard 	 * context.
793df6012aSDouglas Raillard 	 */
803df6012aSDouglas Raillard 	tspd_abort_preempted_smc(tsp_ctx);
813df6012aSDouglas Raillard 
8231244d74SSoby Mathew 	/* Program the entry point and enter the TSP */
83399fb08fSAndrew Thoelke 	cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_suspend_entry);
84607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
85607084eeSAchin Gupta 
86607084eeSAchin Gupta 	/*
87607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
88607084eeSAchin Gupta 	 * something went wrong while communicating with the TSP.
89607084eeSAchin Gupta 	 */
903df6012aSDouglas Raillard 	if (rc)
91607084eeSAchin Gupta 		panic();
92607084eeSAchin Gupta 
93607084eeSAchin Gupta 	/* Update its context to reflect the state the TSP is in */
943ee8a164SAchin Gupta 	set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_SUSPEND);
95607084eeSAchin Gupta }
96607084eeSAchin Gupta 
97607084eeSAchin Gupta /*******************************************************************************
98607084eeSAchin Gupta  * This cpu has been turned on. Enter the TSP to initialise S-EL1 and other bits
993df6012aSDouglas Raillard  * before passing control back to the Secure Monitor. Entry in S-EL1 is done
100607084eeSAchin Gupta  * after initialising minimal architectural state that guarantees safe
101607084eeSAchin Gupta  * execution.
102607084eeSAchin Gupta  ******************************************************************************/
10331244d74SSoby Mathew static void tspd_cpu_on_finish_handler(uint64_t unused)
104607084eeSAchin Gupta {
105607084eeSAchin Gupta 	int32_t rc = 0;
106fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
107fb037bfbSDan Handley 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
10850e27dadSVikram Kanigiri 	entry_point_info_t tsp_on_entrypoint;
109607084eeSAchin Gupta 
110399fb08fSAndrew Thoelke 	assert(tsp_vectors);
1113ee8a164SAchin Gupta 	assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_OFF);
112607084eeSAchin Gupta 
11350e27dadSVikram Kanigiri 	tspd_init_tsp_ep_state(&tsp_on_entrypoint,
114607084eeSAchin Gupta 				TSP_AARCH64,
11550e27dadSVikram Kanigiri 				(uint64_t) &tsp_vectors->cpu_on_entry,
116607084eeSAchin Gupta 				tsp_ctx);
117607084eeSAchin Gupta 
11850e27dadSVikram Kanigiri 	/* Initialise this cpu's secure context */
119fd650ff6SSoby Mathew 	cm_init_my_context(&tsp_on_entrypoint);
12050e27dadSVikram Kanigiri 
12102446137SSoby Mathew #if TSP_NS_INTR_ASYNC_PREEMPT
122f4f1ae77SSoby Mathew 	/*
123f4f1ae77SSoby Mathew 	 * Disable the NS interrupt locally since it will be enabled globally
124fd650ff6SSoby Mathew 	 * within cm_init_my_context.
125f4f1ae77SSoby Mathew 	 */
126f4f1ae77SSoby Mathew 	disable_intr_rm_local(INTR_TYPE_NS, SECURE);
127f4f1ae77SSoby Mathew #endif
128f4f1ae77SSoby Mathew 
129607084eeSAchin Gupta 	/* Enter the TSP */
130607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
131607084eeSAchin Gupta 
132607084eeSAchin Gupta 	/*
133607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
134607084eeSAchin Gupta 	 * something went wrong while communicating with the SP.
135607084eeSAchin Gupta 	 */
136607084eeSAchin Gupta 	if (rc != 0)
137607084eeSAchin Gupta 		panic();
138607084eeSAchin Gupta 
139607084eeSAchin Gupta 	/* Update its context to reflect the state the SP is in */
1403ee8a164SAchin Gupta 	set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON);
141607084eeSAchin Gupta }
142607084eeSAchin Gupta 
143607084eeSAchin Gupta /*******************************************************************************
144607084eeSAchin Gupta  * This cpu has resumed from suspend. The SPD saved the TSP context when it
145607084eeSAchin Gupta  * completed the preceding suspend call. Use that context to program an entry
146607084eeSAchin Gupta  * into the TSP to allow it to do any remaining book keeping
147607084eeSAchin Gupta  ******************************************************************************/
148f1054c93SAchin Gupta static void tspd_cpu_suspend_finish_handler(uint64_t max_off_pwrlvl)
149607084eeSAchin Gupta {
150607084eeSAchin Gupta 	int32_t rc = 0;
151fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
152fb037bfbSDan Handley 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
153607084eeSAchin Gupta 
154399fb08fSAndrew Thoelke 	assert(tsp_vectors);
1553ee8a164SAchin Gupta 	assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_SUSPEND);
156607084eeSAchin Gupta 
157f1054c93SAchin Gupta 	/* Program the entry point, max_off_pwrlvl and enter the SP */
158607084eeSAchin Gupta 	write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
159607084eeSAchin Gupta 		      CTX_GPREG_X0,
160f1054c93SAchin Gupta 		      max_off_pwrlvl);
161399fb08fSAndrew Thoelke 	cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_resume_entry);
162607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
163607084eeSAchin Gupta 
164607084eeSAchin Gupta 	/*
165607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
166607084eeSAchin Gupta 	 * something went wrong while communicating with the TSP.
167607084eeSAchin Gupta 	 */
168607084eeSAchin Gupta 	if (rc != 0)
169607084eeSAchin Gupta 		panic();
170607084eeSAchin Gupta 
171607084eeSAchin Gupta 	/* Update its context to reflect the state the SP is in */
1723ee8a164SAchin Gupta 	set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON);
173607084eeSAchin Gupta }
174607084eeSAchin Gupta 
175607084eeSAchin Gupta /*******************************************************************************
176607084eeSAchin Gupta  * Return the type of TSP the TSPD is dealing with. Report the current resident
177607084eeSAchin Gupta  * cpu (mpidr format) if it is a UP/UP migratable TSP.
178607084eeSAchin Gupta  ******************************************************************************/
179607084eeSAchin Gupta static int32_t tspd_cpu_migrate_info(uint64_t *resident_cpu)
180607084eeSAchin Gupta {
181607084eeSAchin Gupta 	return TSP_MIGRATE_INFO;
182607084eeSAchin Gupta }
183607084eeSAchin Gupta 
184607084eeSAchin Gupta /*******************************************************************************
185d5f13093SJuan Castillo  * System is about to be switched off. Allow the TSPD/TSP to perform
186d5f13093SJuan Castillo  * any actions needed.
187d5f13093SJuan Castillo  ******************************************************************************/
188d5f13093SJuan Castillo static void tspd_system_off(void)
189d5f13093SJuan Castillo {
190fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
191d5f13093SJuan Castillo 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
192d5f13093SJuan Castillo 
193d5f13093SJuan Castillo 	assert(tsp_vectors);
194d5f13093SJuan Castillo 	assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
195d5f13093SJuan Castillo 
1963df6012aSDouglas Raillard 	/*
1973df6012aSDouglas Raillard 	 * Abort any preempted SMC request before overwriting the SECURE
1983df6012aSDouglas Raillard 	 * context.
1993df6012aSDouglas Raillard 	 */
2003df6012aSDouglas Raillard 	tspd_abort_preempted_smc(tsp_ctx);
2013df6012aSDouglas Raillard 
202d5f13093SJuan Castillo 	/* Program the entry point */
203d5f13093SJuan Castillo 	cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_off_entry);
204d5f13093SJuan Castillo 
205d5f13093SJuan Castillo 	/* Enter the TSP. We do not care about the return value because we
206d5f13093SJuan Castillo 	 * must continue the shutdown anyway */
207d5f13093SJuan Castillo 	tspd_synchronous_sp_entry(tsp_ctx);
208d5f13093SJuan Castillo }
209d5f13093SJuan Castillo 
210d5f13093SJuan Castillo /*******************************************************************************
211d5f13093SJuan Castillo  * System is about to be reset. Allow the TSPD/TSP to perform
212d5f13093SJuan Castillo  * any actions needed.
213d5f13093SJuan Castillo  ******************************************************************************/
214d5f13093SJuan Castillo static void tspd_system_reset(void)
215d5f13093SJuan Castillo {
216fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
217d5f13093SJuan Castillo 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
218d5f13093SJuan Castillo 
219d5f13093SJuan Castillo 	assert(tsp_vectors);
220d5f13093SJuan Castillo 	assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
221d5f13093SJuan Castillo 
2223df6012aSDouglas Raillard 	/*
2233df6012aSDouglas Raillard 	 * Abort any preempted SMC request before overwriting the SECURE
2243df6012aSDouglas Raillard 	 * context.
2253df6012aSDouglas Raillard 	 */
2263df6012aSDouglas Raillard 	tspd_abort_preempted_smc(tsp_ctx);
2273df6012aSDouglas Raillard 
228d5f13093SJuan Castillo 	/* Program the entry point */
229d5f13093SJuan Castillo 	cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_reset_entry);
230d5f13093SJuan Castillo 
2313df6012aSDouglas Raillard 	/*
2323df6012aSDouglas Raillard 	 * Enter the TSP. We do not care about the return value because we
2333df6012aSDouglas Raillard 	 * must continue the reset anyway
2343df6012aSDouglas Raillard 	 */
235d5f13093SJuan Castillo 	tspd_synchronous_sp_entry(tsp_ctx);
236d5f13093SJuan Castillo }
237d5f13093SJuan Castillo 
238d5f13093SJuan Castillo /*******************************************************************************
239607084eeSAchin Gupta  * Structure populated by the TSP Dispatcher to be given a chance to perform any
240607084eeSAchin Gupta  * TSP bookkeeping before PSCI executes a power mgmt.  operation.
241607084eeSAchin Gupta  ******************************************************************************/
242fb037bfbSDan Handley const spd_pm_ops_t tspd_pm = {
243d5f13093SJuan Castillo 	.svc_on = tspd_cpu_on_handler,
244d5f13093SJuan Castillo 	.svc_off = tspd_cpu_off_handler,
245d5f13093SJuan Castillo 	.svc_suspend = tspd_cpu_suspend_handler,
246d5f13093SJuan Castillo 	.svc_on_finish = tspd_cpu_on_finish_handler,
247d5f13093SJuan Castillo 	.svc_suspend_finish = tspd_cpu_suspend_finish_handler,
248d5f13093SJuan Castillo 	.svc_migrate = NULL,
249d5f13093SJuan Castillo 	.svc_migrate_info = tspd_cpu_migrate_info,
250d5f13093SJuan Castillo 	.svc_system_off = tspd_system_off,
251d5f13093SJuan Castillo 	.svc_system_reset = tspd_system_reset
252607084eeSAchin Gupta };
253