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