xref: /rk3399_ARM-atf/services/spd/opteed/opteed_pm.c (revision 776ff52a8daa0eb35870638de536951e0d256a84)
1aa5da461SJens Wiklander /*
2d59a6accSEdison Ai  * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
3aa5da461SJens Wiklander  *
482cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
5aa5da461SJens Wiklander  */
6aa5da461SJens Wiklander 
7aa5da461SJens Wiklander #include <arch_helpers.h>
8aa5da461SJens Wiklander #include <assert.h>
9aa5da461SJens Wiklander #include <bl_common.h>
10aa5da461SJens Wiklander #include <context_mgmt.h>
11aa5da461SJens Wiklander #include <debug.h>
12aa5da461SJens Wiklander #include <platform.h>
13aa5da461SJens Wiklander #include "opteed_private.h"
14aa5da461SJens Wiklander 
15aa5da461SJens Wiklander /*******************************************************************************
16aa5da461SJens Wiklander  * The target cpu is being turned on. Allow the OPTEED/OPTEE to perform any
17aa5da461SJens Wiklander  * actions needed. Nothing at the moment.
18aa5da461SJens Wiklander  ******************************************************************************/
1957d1e5faSMasahiro Yamada static void opteed_cpu_on_handler(u_register_t target_cpu)
20aa5da461SJens Wiklander {
21aa5da461SJens Wiklander }
22aa5da461SJens Wiklander 
23aa5da461SJens Wiklander /*******************************************************************************
24aa5da461SJens Wiklander  * This cpu is being turned off. Allow the OPTEED/OPTEE to perform any actions
25aa5da461SJens Wiklander  * needed
26aa5da461SJens Wiklander  ******************************************************************************/
2757d1e5faSMasahiro Yamada static int32_t opteed_cpu_off_handler(u_register_t unused)
28aa5da461SJens Wiklander {
29aa5da461SJens Wiklander 	int32_t rc = 0;
30fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
31aa5da461SJens Wiklander 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
32aa5da461SJens Wiklander 
33*776ff52aSDaniel Boulby 	assert(optee_vector_table);
34aa5da461SJens Wiklander 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
35aa5da461SJens Wiklander 
36aa5da461SJens Wiklander 	/* Program the entry point and enter OPTEE */
37*776ff52aSDaniel Boulby 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_off_entry);
38aa5da461SJens Wiklander 	rc = opteed_synchronous_sp_entry(optee_ctx);
39aa5da461SJens Wiklander 
40aa5da461SJens Wiklander 	/*
41aa5da461SJens Wiklander 	 * Read the response from OPTEE. A non-zero return means that
42aa5da461SJens Wiklander 	 * something went wrong while communicating with OPTEE.
43aa5da461SJens Wiklander 	 */
44aa5da461SJens Wiklander 	if (rc != 0)
45aa5da461SJens Wiklander 		panic();
46aa5da461SJens Wiklander 
47aa5da461SJens Wiklander 	/*
48aa5da461SJens Wiklander 	 * Reset OPTEE's context for a fresh start when this cpu is turned on
49aa5da461SJens Wiklander 	 * subsequently.
50aa5da461SJens Wiklander 	 */
51aa5da461SJens Wiklander 	set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_OFF);
52aa5da461SJens Wiklander 
53aa5da461SJens Wiklander 	 return 0;
54aa5da461SJens Wiklander }
55aa5da461SJens Wiklander 
56aa5da461SJens Wiklander /*******************************************************************************
57aa5da461SJens Wiklander  * This cpu is being suspended. S-EL1 state must have been saved in the
58aa5da461SJens Wiklander  * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
59aa5da461SJens Wiklander  ******************************************************************************/
6057d1e5faSMasahiro Yamada static void opteed_cpu_suspend_handler(u_register_t max_off_pwrlvl)
61aa5da461SJens Wiklander {
62aa5da461SJens Wiklander 	int32_t rc = 0;
63fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
64aa5da461SJens Wiklander 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
65aa5da461SJens Wiklander 
66*776ff52aSDaniel Boulby 	assert(optee_vector_table);
67aa5da461SJens Wiklander 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
68aa5da461SJens Wiklander 
6931244d74SSoby Mathew 	/* Program the entry point and enter OPTEE */
70*776ff52aSDaniel Boulby 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_suspend_entry);
71aa5da461SJens Wiklander 	rc = opteed_synchronous_sp_entry(optee_ctx);
72aa5da461SJens Wiklander 
73aa5da461SJens Wiklander 	/*
74aa5da461SJens Wiklander 	 * Read the response from OPTEE. A non-zero return means that
75aa5da461SJens Wiklander 	 * something went wrong while communicating with OPTEE.
76aa5da461SJens Wiklander 	 */
77aa5da461SJens Wiklander 	if (rc != 0)
78aa5da461SJens Wiklander 		panic();
79aa5da461SJens Wiklander 
80aa5da461SJens Wiklander 	/* Update its context to reflect the state OPTEE is in */
81aa5da461SJens Wiklander 	set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_SUSPEND);
82aa5da461SJens Wiklander }
83aa5da461SJens Wiklander 
84aa5da461SJens Wiklander /*******************************************************************************
85aa5da461SJens Wiklander  * This cpu has been turned on. Enter OPTEE to initialise S-EL1 and other bits
86aa5da461SJens Wiklander  * before passing control back to the Secure Monitor. Entry in S-El1 is done
87aa5da461SJens Wiklander  * after initialising minimal architectural state that guarantees safe
88aa5da461SJens Wiklander  * execution.
89aa5da461SJens Wiklander  ******************************************************************************/
9057d1e5faSMasahiro Yamada static void opteed_cpu_on_finish_handler(u_register_t unused)
91aa5da461SJens Wiklander {
92aa5da461SJens Wiklander 	int32_t rc = 0;
93fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
94aa5da461SJens Wiklander 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
95aa5da461SJens Wiklander 	entry_point_info_t optee_on_entrypoint;
96aa5da461SJens Wiklander 
97*776ff52aSDaniel Boulby 	assert(optee_vector_table);
98aa5da461SJens Wiklander 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_OFF);
99aa5da461SJens Wiklander 
100aa5da461SJens Wiklander 	opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw,
101*776ff52aSDaniel Boulby 				(uint64_t)&optee_vector_table->cpu_on_entry,
10219911aa6SJens Wiklander 				0, 0, 0, optee_ctx);
103aa5da461SJens Wiklander 
104aa5da461SJens Wiklander 	/* Initialise this cpu's secure context */
105fd650ff6SSoby Mathew 	cm_init_my_context(&optee_on_entrypoint);
106aa5da461SJens Wiklander 
107aa5da461SJens Wiklander 	/* Enter OPTEE */
108aa5da461SJens Wiklander 	rc = opteed_synchronous_sp_entry(optee_ctx);
109aa5da461SJens Wiklander 
110aa5da461SJens Wiklander 	/*
111aa5da461SJens Wiklander 	 * Read the response from OPTEE. A non-zero return means that
112aa5da461SJens Wiklander 	 * something went wrong while communicating with OPTEE.
113aa5da461SJens Wiklander 	 */
114aa5da461SJens Wiklander 	if (rc != 0)
115aa5da461SJens Wiklander 		panic();
116aa5da461SJens Wiklander 
117aa5da461SJens Wiklander 	/* Update its context to reflect the state OPTEE is in */
118aa5da461SJens Wiklander 	set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
119aa5da461SJens Wiklander }
120aa5da461SJens Wiklander 
121aa5da461SJens Wiklander /*******************************************************************************
122aa5da461SJens Wiklander  * This cpu has resumed from suspend. The OPTEED saved the OPTEE context when it
123aa5da461SJens Wiklander  * completed the preceding suspend call. Use that context to program an entry
124aa5da461SJens Wiklander  * into OPTEE to allow it to do any remaining book keeping
125aa5da461SJens Wiklander  ******************************************************************************/
12657d1e5faSMasahiro Yamada static void opteed_cpu_suspend_finish_handler(u_register_t max_off_pwrlvl)
127aa5da461SJens Wiklander {
128aa5da461SJens Wiklander 	int32_t rc = 0;
129fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
130aa5da461SJens Wiklander 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
131aa5da461SJens Wiklander 
132*776ff52aSDaniel Boulby 	assert(optee_vector_table);
133aa5da461SJens Wiklander 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_SUSPEND);
134aa5da461SJens Wiklander 
135f1054c93SAchin Gupta 	/* Program the entry point, max_off_pwrlvl and enter the SP */
136aa5da461SJens Wiklander 	write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
137aa5da461SJens Wiklander 		      CTX_GPREG_X0,
138f1054c93SAchin Gupta 		      max_off_pwrlvl);
139*776ff52aSDaniel Boulby 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_resume_entry);
140aa5da461SJens Wiklander 	rc = opteed_synchronous_sp_entry(optee_ctx);
141aa5da461SJens Wiklander 
142aa5da461SJens Wiklander 	/*
143aa5da461SJens Wiklander 	 * Read the response from OPTEE. A non-zero return means that
144aa5da461SJens Wiklander 	 * something went wrong while communicating with OPTEE.
145aa5da461SJens Wiklander 	 */
146aa5da461SJens Wiklander 	if (rc != 0)
147aa5da461SJens Wiklander 		panic();
148aa5da461SJens Wiklander 
149aa5da461SJens Wiklander 	/* Update its context to reflect the state OPTEE is in */
150aa5da461SJens Wiklander 	set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
151aa5da461SJens Wiklander }
152aa5da461SJens Wiklander 
153aa5da461SJens Wiklander /*******************************************************************************
154aa5da461SJens Wiklander  * Return the type of OPTEE the OPTEED is dealing with. Report the current
155aa5da461SJens Wiklander  * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
156aa5da461SJens Wiklander  ******************************************************************************/
15757d1e5faSMasahiro Yamada static int32_t opteed_cpu_migrate_info(u_register_t *resident_cpu)
158aa5da461SJens Wiklander {
159aa5da461SJens Wiklander 	return OPTEE_MIGRATE_INFO;
160aa5da461SJens Wiklander }
161aa5da461SJens Wiklander 
162aa5da461SJens Wiklander /*******************************************************************************
163aa5da461SJens Wiklander  * System is about to be switched off. Allow the OPTEED/OPTEE to perform
164aa5da461SJens Wiklander  * any actions needed.
165aa5da461SJens Wiklander  ******************************************************************************/
166aa5da461SJens Wiklander static void opteed_system_off(void)
167aa5da461SJens Wiklander {
168fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
169aa5da461SJens Wiklander 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
170aa5da461SJens Wiklander 
171*776ff52aSDaniel Boulby 	assert(optee_vector_table);
172aa5da461SJens Wiklander 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
173aa5da461SJens Wiklander 
174aa5da461SJens Wiklander 	/* Program the entry point */
175*776ff52aSDaniel Boulby 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->system_off_entry);
176aa5da461SJens Wiklander 
177aa5da461SJens Wiklander 	/* Enter OPTEE. We do not care about the return value because we
178aa5da461SJens Wiklander 	 * must continue the shutdown anyway */
179aa5da461SJens Wiklander 	opteed_synchronous_sp_entry(optee_ctx);
180aa5da461SJens Wiklander }
181aa5da461SJens Wiklander 
182aa5da461SJens Wiklander /*******************************************************************************
183aa5da461SJens Wiklander  * System is about to be reset. Allow the OPTEED/OPTEE to perform
184aa5da461SJens Wiklander  * any actions needed.
185aa5da461SJens Wiklander  ******************************************************************************/
186aa5da461SJens Wiklander static void opteed_system_reset(void)
187aa5da461SJens Wiklander {
188fd650ff6SSoby Mathew 	uint32_t linear_id = plat_my_core_pos();
189aa5da461SJens Wiklander 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
190aa5da461SJens Wiklander 
191*776ff52aSDaniel Boulby 	assert(optee_vector_table);
192aa5da461SJens Wiklander 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
193aa5da461SJens Wiklander 
194aa5da461SJens Wiklander 	/* Program the entry point */
195*776ff52aSDaniel Boulby 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->system_reset_entry);
196aa5da461SJens Wiklander 
197aa5da461SJens Wiklander 	/* Enter OPTEE. We do not care about the return value because we
198aa5da461SJens Wiklander 	 * must continue the reset anyway */
199aa5da461SJens Wiklander 	opteed_synchronous_sp_entry(optee_ctx);
200aa5da461SJens Wiklander }
201aa5da461SJens Wiklander 
202aa5da461SJens Wiklander 
203aa5da461SJens Wiklander /*******************************************************************************
204aa5da461SJens Wiklander  * Structure populated by the OPTEE Dispatcher to be given a chance to
205aa5da461SJens Wiklander  * perform any OPTEE bookkeeping before PSCI executes a power mgmt.
206aa5da461SJens Wiklander  * operation.
207aa5da461SJens Wiklander  ******************************************************************************/
208aa5da461SJens Wiklander const spd_pm_ops_t opteed_pm = {
209aa5da461SJens Wiklander 	.svc_on = opteed_cpu_on_handler,
210aa5da461SJens Wiklander 	.svc_off = opteed_cpu_off_handler,
211aa5da461SJens Wiklander 	.svc_suspend = opteed_cpu_suspend_handler,
212aa5da461SJens Wiklander 	.svc_on_finish = opteed_cpu_on_finish_handler,
213aa5da461SJens Wiklander 	.svc_suspend_finish = opteed_cpu_suspend_finish_handler,
214aa5da461SJens Wiklander 	.svc_migrate = NULL,
215aa5da461SJens Wiklander 	.svc_migrate_info = opteed_cpu_migrate_info,
216aa5da461SJens Wiklander 	.svc_system_off = opteed_system_off,
217aa5da461SJens Wiklander 	.svc_system_reset = opteed_system_reset,
218aa5da461SJens Wiklander };
219