xref: /rk3399_ARM-atf/services/spd/opteed/opteed_pm.c (revision 31244d74b350d49cfba6ad46d90dad2d5f2f364c)
1aa5da461SJens Wiklander /*
2aa5da461SJens Wiklander  * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
3aa5da461SJens Wiklander  *
4aa5da461SJens Wiklander  * Redistribution and use in source and binary forms, with or without
5aa5da461SJens Wiklander  * modification, are permitted provided that the following conditions are met:
6aa5da461SJens Wiklander  *
7aa5da461SJens Wiklander  * Redistributions of source code must retain the above copyright notice, this
8aa5da461SJens Wiklander  * list of conditions and the following disclaimer.
9aa5da461SJens Wiklander  *
10aa5da461SJens Wiklander  * Redistributions in binary form must reproduce the above copyright notice,
11aa5da461SJens Wiklander  * this list of conditions and the following disclaimer in the documentation
12aa5da461SJens Wiklander  * and/or other materials provided with the distribution.
13aa5da461SJens Wiklander  *
14aa5da461SJens Wiklander  * Neither the name of ARM nor the names of its contributors may be used
15aa5da461SJens Wiklander  * to endorse or promote products derived from this software without specific
16aa5da461SJens Wiklander  * prior written permission.
17aa5da461SJens Wiklander  *
18aa5da461SJens Wiklander  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19aa5da461SJens Wiklander  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20aa5da461SJens Wiklander  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21aa5da461SJens Wiklander  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22aa5da461SJens Wiklander  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23aa5da461SJens Wiklander  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24aa5da461SJens Wiklander  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25aa5da461SJens Wiklander  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26aa5da461SJens Wiklander  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27aa5da461SJens Wiklander  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28aa5da461SJens Wiklander  * POSSIBILITY OF SUCH DAMAGE.
29aa5da461SJens Wiklander  */
30aa5da461SJens Wiklander 
31aa5da461SJens Wiklander #include <arch_helpers.h>
32aa5da461SJens Wiklander #include <assert.h>
33aa5da461SJens Wiklander #include <bl_common.h>
34aa5da461SJens Wiklander #include <context_mgmt.h>
35aa5da461SJens Wiklander #include <debug.h>
36aa5da461SJens Wiklander #include <platform.h>
37aa5da461SJens Wiklander #include "opteed_private.h"
38aa5da461SJens Wiklander 
39aa5da461SJens Wiklander /*******************************************************************************
40aa5da461SJens Wiklander  * The target cpu is being turned on. Allow the OPTEED/OPTEE to perform any
41aa5da461SJens Wiklander  * actions needed. Nothing at the moment.
42aa5da461SJens Wiklander  ******************************************************************************/
43aa5da461SJens Wiklander static void opteed_cpu_on_handler(uint64_t target_cpu)
44aa5da461SJens Wiklander {
45aa5da461SJens Wiklander }
46aa5da461SJens Wiklander 
47aa5da461SJens Wiklander /*******************************************************************************
48aa5da461SJens Wiklander  * This cpu is being turned off. Allow the OPTEED/OPTEE to perform any actions
49aa5da461SJens Wiklander  * needed
50aa5da461SJens Wiklander  ******************************************************************************/
51*31244d74SSoby Mathew static int32_t opteed_cpu_off_handler(uint64_t unused)
52aa5da461SJens Wiklander {
53aa5da461SJens Wiklander 	int32_t rc = 0;
54aa5da461SJens Wiklander 	uint64_t mpidr = read_mpidr();
55aa5da461SJens Wiklander 	uint32_t linear_id = platform_get_core_pos(mpidr);
56aa5da461SJens Wiklander 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
57aa5da461SJens Wiklander 
58aa5da461SJens Wiklander 	assert(optee_vectors);
59aa5da461SJens Wiklander 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
60aa5da461SJens Wiklander 
61aa5da461SJens Wiklander 	/* Program the entry point and enter OPTEE */
62aa5da461SJens Wiklander 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_off_entry);
63aa5da461SJens Wiklander 	rc = opteed_synchronous_sp_entry(optee_ctx);
64aa5da461SJens Wiklander 
65aa5da461SJens Wiklander 	/*
66aa5da461SJens Wiklander 	 * Read the response from OPTEE. A non-zero return means that
67aa5da461SJens Wiklander 	 * something went wrong while communicating with OPTEE.
68aa5da461SJens Wiklander 	 */
69aa5da461SJens Wiklander 	if (rc != 0)
70aa5da461SJens Wiklander 		panic();
71aa5da461SJens Wiklander 
72aa5da461SJens Wiklander 	/*
73aa5da461SJens Wiklander 	 * Reset OPTEE's context for a fresh start when this cpu is turned on
74aa5da461SJens Wiklander 	 * subsequently.
75aa5da461SJens Wiklander 	 */
76aa5da461SJens Wiklander 	set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_OFF);
77aa5da461SJens Wiklander 
78aa5da461SJens Wiklander 	 return 0;
79aa5da461SJens Wiklander }
80aa5da461SJens Wiklander 
81aa5da461SJens Wiklander /*******************************************************************************
82aa5da461SJens Wiklander  * This cpu is being suspended. S-EL1 state must have been saved in the
83aa5da461SJens Wiklander  * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
84aa5da461SJens Wiklander  ******************************************************************************/
85*31244d74SSoby Mathew static void opteed_cpu_suspend_handler(uint64_t unused)
86aa5da461SJens Wiklander {
87aa5da461SJens Wiklander 	int32_t rc = 0;
88aa5da461SJens Wiklander 	uint64_t mpidr = read_mpidr();
89aa5da461SJens Wiklander 	uint32_t linear_id = platform_get_core_pos(mpidr);
90aa5da461SJens Wiklander 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
91aa5da461SJens Wiklander 
92aa5da461SJens Wiklander 	assert(optee_vectors);
93aa5da461SJens Wiklander 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
94aa5da461SJens Wiklander 
95*31244d74SSoby Mathew 	/* Program the entry point and enter OPTEE */
96aa5da461SJens Wiklander 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_suspend_entry);
97aa5da461SJens Wiklander 	rc = opteed_synchronous_sp_entry(optee_ctx);
98aa5da461SJens Wiklander 
99aa5da461SJens Wiklander 	/*
100aa5da461SJens Wiklander 	 * Read the response from OPTEE. A non-zero return means that
101aa5da461SJens Wiklander 	 * something went wrong while communicating with OPTEE.
102aa5da461SJens Wiklander 	 */
103aa5da461SJens Wiklander 	if (rc != 0)
104aa5da461SJens Wiklander 		panic();
105aa5da461SJens Wiklander 
106aa5da461SJens Wiklander 	/* Update its context to reflect the state OPTEE is in */
107aa5da461SJens Wiklander 	set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_SUSPEND);
108aa5da461SJens Wiklander }
109aa5da461SJens Wiklander 
110aa5da461SJens Wiklander /*******************************************************************************
111aa5da461SJens Wiklander  * This cpu has been turned on. Enter OPTEE to initialise S-EL1 and other bits
112aa5da461SJens Wiklander  * before passing control back to the Secure Monitor. Entry in S-El1 is done
113aa5da461SJens Wiklander  * after initialising minimal architectural state that guarantees safe
114aa5da461SJens Wiklander  * execution.
115aa5da461SJens Wiklander  ******************************************************************************/
116*31244d74SSoby Mathew static void opteed_cpu_on_finish_handler(uint64_t unused)
117aa5da461SJens Wiklander {
118aa5da461SJens Wiklander 	int32_t rc = 0;
119aa5da461SJens Wiklander 	uint64_t mpidr = read_mpidr();
120aa5da461SJens Wiklander 	uint32_t linear_id = platform_get_core_pos(mpidr);
121aa5da461SJens Wiklander 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
122aa5da461SJens Wiklander 	entry_point_info_t optee_on_entrypoint;
123aa5da461SJens Wiklander 
124aa5da461SJens Wiklander 	assert(optee_vectors);
125aa5da461SJens Wiklander 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_OFF);
126aa5da461SJens Wiklander 
127aa5da461SJens Wiklander 	opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw,
128aa5da461SJens Wiklander 				(uint64_t)&optee_vectors->cpu_on_entry,
129aa5da461SJens Wiklander 				optee_ctx);
130aa5da461SJens Wiklander 
131aa5da461SJens Wiklander 	/* Initialise this cpu's secure context */
132aa5da461SJens Wiklander 	cm_init_context(mpidr, &optee_on_entrypoint);
133aa5da461SJens Wiklander 
134aa5da461SJens Wiklander 	/* Enter OPTEE */
135aa5da461SJens Wiklander 	rc = opteed_synchronous_sp_entry(optee_ctx);
136aa5da461SJens Wiklander 
137aa5da461SJens Wiklander 	/*
138aa5da461SJens Wiklander 	 * Read the response from OPTEE. A non-zero return means that
139aa5da461SJens Wiklander 	 * something went wrong while communicating with OPTEE.
140aa5da461SJens Wiklander 	 */
141aa5da461SJens Wiklander 	if (rc != 0)
142aa5da461SJens Wiklander 		panic();
143aa5da461SJens Wiklander 
144aa5da461SJens Wiklander 	/* Update its context to reflect the state OPTEE is in */
145aa5da461SJens Wiklander 	set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
146aa5da461SJens Wiklander }
147aa5da461SJens Wiklander 
148aa5da461SJens Wiklander /*******************************************************************************
149aa5da461SJens Wiklander  * This cpu has resumed from suspend. The OPTEED saved the OPTEE context when it
150aa5da461SJens Wiklander  * completed the preceding suspend call. Use that context to program an entry
151aa5da461SJens Wiklander  * into OPTEE to allow it to do any remaining book keeping
152aa5da461SJens Wiklander  ******************************************************************************/
153aa5da461SJens Wiklander static void opteed_cpu_suspend_finish_handler(uint64_t suspend_level)
154aa5da461SJens Wiklander {
155aa5da461SJens Wiklander 	int32_t rc = 0;
156aa5da461SJens Wiklander 	uint64_t mpidr = read_mpidr();
157aa5da461SJens Wiklander 	uint32_t linear_id = platform_get_core_pos(mpidr);
158aa5da461SJens Wiklander 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
159aa5da461SJens Wiklander 
160aa5da461SJens Wiklander 	assert(optee_vectors);
161aa5da461SJens Wiklander 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_SUSPEND);
162aa5da461SJens Wiklander 
163aa5da461SJens Wiklander 	/* Program the entry point, suspend_level and enter the SP */
164aa5da461SJens Wiklander 	write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
165aa5da461SJens Wiklander 		      CTX_GPREG_X0,
166aa5da461SJens Wiklander 		      suspend_level);
167aa5da461SJens Wiklander 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_resume_entry);
168aa5da461SJens Wiklander 	rc = opteed_synchronous_sp_entry(optee_ctx);
169aa5da461SJens Wiklander 
170aa5da461SJens Wiklander 	/*
171aa5da461SJens Wiklander 	 * Read the response from OPTEE. A non-zero return means that
172aa5da461SJens Wiklander 	 * something went wrong while communicating with OPTEE.
173aa5da461SJens Wiklander 	 */
174aa5da461SJens Wiklander 	if (rc != 0)
175aa5da461SJens Wiklander 		panic();
176aa5da461SJens Wiklander 
177aa5da461SJens Wiklander 	/* Update its context to reflect the state OPTEE is in */
178aa5da461SJens Wiklander 	set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
179aa5da461SJens Wiklander }
180aa5da461SJens Wiklander 
181aa5da461SJens Wiklander /*******************************************************************************
182aa5da461SJens Wiklander  * Return the type of OPTEE the OPTEED is dealing with. Report the current
183aa5da461SJens Wiklander  * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
184aa5da461SJens Wiklander  ******************************************************************************/
185aa5da461SJens Wiklander static int32_t opteed_cpu_migrate_info(uint64_t *resident_cpu)
186aa5da461SJens Wiklander {
187aa5da461SJens Wiklander 	return OPTEE_MIGRATE_INFO;
188aa5da461SJens Wiklander }
189aa5da461SJens Wiklander 
190aa5da461SJens Wiklander /*******************************************************************************
191aa5da461SJens Wiklander  * System is about to be switched off. Allow the OPTEED/OPTEE to perform
192aa5da461SJens Wiklander  * any actions needed.
193aa5da461SJens Wiklander  ******************************************************************************/
194aa5da461SJens Wiklander static void opteed_system_off(void)
195aa5da461SJens Wiklander {
196aa5da461SJens Wiklander 	uint64_t mpidr = read_mpidr();
197aa5da461SJens Wiklander 	uint32_t linear_id = platform_get_core_pos(mpidr);
198aa5da461SJens Wiklander 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
199aa5da461SJens Wiklander 
200aa5da461SJens Wiklander 	assert(optee_vectors);
201aa5da461SJens Wiklander 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
202aa5da461SJens Wiklander 
203aa5da461SJens Wiklander 	/* Program the entry point */
204aa5da461SJens Wiklander 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->system_off_entry);
205aa5da461SJens Wiklander 
206aa5da461SJens Wiklander 	/* Enter OPTEE. We do not care about the return value because we
207aa5da461SJens Wiklander 	 * must continue the shutdown anyway */
208aa5da461SJens Wiklander 	opteed_synchronous_sp_entry(optee_ctx);
209aa5da461SJens Wiklander }
210aa5da461SJens Wiklander 
211aa5da461SJens Wiklander /*******************************************************************************
212aa5da461SJens Wiklander  * System is about to be reset. Allow the OPTEED/OPTEE to perform
213aa5da461SJens Wiklander  * any actions needed.
214aa5da461SJens Wiklander  ******************************************************************************/
215aa5da461SJens Wiklander static void opteed_system_reset(void)
216aa5da461SJens Wiklander {
217aa5da461SJens Wiklander 	uint64_t mpidr = read_mpidr();
218aa5da461SJens Wiklander 	uint32_t linear_id = platform_get_core_pos(mpidr);
219aa5da461SJens Wiklander 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
220aa5da461SJens Wiklander 
221aa5da461SJens Wiklander 	assert(optee_vectors);
222aa5da461SJens Wiklander 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
223aa5da461SJens Wiklander 
224aa5da461SJens Wiklander 	/* Program the entry point */
225aa5da461SJens Wiklander 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->system_reset_entry);
226aa5da461SJens Wiklander 
227aa5da461SJens Wiklander 	/* Enter OPTEE. We do not care about the return value because we
228aa5da461SJens Wiklander 	 * must continue the reset anyway */
229aa5da461SJens Wiklander 	opteed_synchronous_sp_entry(optee_ctx);
230aa5da461SJens Wiklander }
231aa5da461SJens Wiklander 
232aa5da461SJens Wiklander 
233aa5da461SJens Wiklander /*******************************************************************************
234aa5da461SJens Wiklander  * Structure populated by the OPTEE Dispatcher to be given a chance to
235aa5da461SJens Wiklander  * perform any OPTEE bookkeeping before PSCI executes a power mgmt.
236aa5da461SJens Wiklander  * operation.
237aa5da461SJens Wiklander  ******************************************************************************/
238aa5da461SJens Wiklander const spd_pm_ops_t opteed_pm = {
239aa5da461SJens Wiklander 	.svc_on = opteed_cpu_on_handler,
240aa5da461SJens Wiklander 	.svc_off = opteed_cpu_off_handler,
241aa5da461SJens Wiklander 	.svc_suspend = opteed_cpu_suspend_handler,
242aa5da461SJens Wiklander 	.svc_on_finish = opteed_cpu_on_finish_handler,
243aa5da461SJens Wiklander 	.svc_suspend_finish = opteed_cpu_suspend_finish_handler,
244aa5da461SJens Wiklander 	.svc_migrate = NULL,
245aa5da461SJens Wiklander 	.svc_migrate_info = opteed_cpu_migrate_info,
246aa5da461SJens Wiklander 	.svc_system_off = opteed_system_off,
247aa5da461SJens Wiklander 	.svc_system_reset = opteed_system_reset,
248aa5da461SJens Wiklander };
249aa5da461SJens Wiklander 
250