blob: 2447d9e837c44010bca69e58775742d4a31d994f [file] [log] [blame]
Achin Gupta607084e2014-02-09 18:24:19 +00001/*
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
Achin Gupta607084e2014-02-09 18:24:19 +000031#include <arch_helpers.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010032#include <assert.h>
33#include <bl_common.h>
Achin Gupta607084e2014-02-09 18:24:19 +000034#include <context_mgmt.h>
Achin Gupta607084e2014-02-09 18:24:19 +000035#include <debug.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010036#include <tsp.h>
Dan Handley714a0d22014-04-09 13:13:04 +010037#include "tspd_private.h"
Achin Gupta607084e2014-02-09 18:24:19 +000038
39/*******************************************************************************
40 * The target cpu is being turned on. Allow the TSPD/TSP to perform any actions
41 * needed. Nothing at the moment.
42 ******************************************************************************/
43static void tspd_cpu_on_handler(uint64_t target_cpu)
44{
45}
46
47/*******************************************************************************
48 * This cpu is being turned off. Allow the TSPD/TSP to perform any actions
49 * needed
50 ******************************************************************************/
51static int32_t tspd_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);
Dan Handleye2712bc2014-04-10 15:37:22 +010056 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Achin Gupta607084e2014-02-09 18:24:19 +000057
58 assert(tsp_entry_info);
59 assert(tsp_ctx->state == TSP_STATE_ON);
60
61 /* Program the entry point and enter the TSP */
62 cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_off_entry);
63 rc = tspd_synchronous_sp_entry(tsp_ctx);
64
65 /*
66 * Read the response from the TSP. A non-zero return means that
67 * something went wrong while communicating with the TSP.
68 */
69 if (rc != 0)
70 panic();
71
72 /*
73 * Reset TSP's context for a fresh start when this cpu is turned on
74 * subsequently.
75 */
76 tsp_ctx->state = TSP_STATE_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 TSP.
84 ******************************************************************************/
85static void tspd_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);
Dan Handleye2712bc2014-04-10 15:37:22 +010090 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Achin Gupta607084e2014-02-09 18:24:19 +000091
92 assert(tsp_entry_info);
93 assert(tsp_ctx->state == TSP_STATE_ON);
94
95 /* Program the entry point, power_state parameter and enter the TSP */
96 write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
97 CTX_GPREG_X0,
98 power_state);
99 cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_suspend_entry);
100 rc = tspd_synchronous_sp_entry(tsp_ctx);
101
102 /*
103 * Read the response from the TSP. A non-zero return means that
104 * something went wrong while communicating with the TSP.
105 */
106 if (rc != 0)
107 panic();
108
109 /* Update its context to reflect the state the TSP is in */
110 tsp_ctx->state = TSP_STATE_SUSPEND;
111}
112
113/*******************************************************************************
114 * This cpu has been turned on. Enter the TSP 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 ******************************************************************************/
119static void tspd_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);
Dan Handleye2712bc2014-04-10 15:37:22 +0100124 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Achin Gupta607084e2014-02-09 18:24:19 +0000125
126 assert(tsp_entry_info);
127 assert(tsp_ctx->state == TSP_STATE_OFF);
128
129 /* Initialise this cpu's secure context */
130 tspd_init_secure_context((uint64_t) tsp_entry_info->cpu_on_entry,
131 TSP_AARCH64,
132 mpidr,
133 tsp_ctx);
134
135 /* Enter the TSP */
136 rc = tspd_synchronous_sp_entry(tsp_ctx);
137
138 /*
139 * Read the response from the TSP. A non-zero return means that
140 * something went wrong while communicating with the SP.
141 */
142 if (rc != 0)
143 panic();
144
145 /* Update its context to reflect the state the SP is in */
146 tsp_ctx->state = TSP_STATE_ON;
147}
148
149/*******************************************************************************
150 * This cpu has resumed from suspend. The SPD saved the TSP context when it
151 * completed the preceding suspend call. Use that context to program an entry
152 * into the TSP to allow it to do any remaining book keeping
153 ******************************************************************************/
154static void tspd_cpu_suspend_finish_handler(uint64_t suspend_level)
155{
156 int32_t rc = 0;
157 uint64_t mpidr = read_mpidr();
158 uint32_t linear_id = platform_get_core_pos(mpidr);
Dan Handleye2712bc2014-04-10 15:37:22 +0100159 tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
Achin Gupta607084e2014-02-09 18:24:19 +0000160
161 assert(tsp_entry_info);
162 assert(tsp_ctx->state == TSP_STATE_SUSPEND);
163
164 /* Program the entry point, suspend_level and enter the SP */
165 write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
166 CTX_GPREG_X0,
167 suspend_level);
168 cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_resume_entry);
169 rc = tspd_synchronous_sp_entry(tsp_ctx);
170
171 /*
172 * Read the response from the TSP. A non-zero return means that
173 * something went wrong while communicating with the TSP.
174 */
175 if (rc != 0)
176 panic();
177
178 /* Update its context to reflect the state the SP is in */
179 tsp_ctx->state = TSP_STATE_ON;
180}
181
182/*******************************************************************************
183 * Return the type of TSP the TSPD is dealing with. Report the current resident
184 * cpu (mpidr format) if it is a UP/UP migratable TSP.
185 ******************************************************************************/
186static int32_t tspd_cpu_migrate_info(uint64_t *resident_cpu)
187{
188 return TSP_MIGRATE_INFO;
189}
190
191/*******************************************************************************
192 * Structure populated by the TSP Dispatcher to be given a chance to perform any
193 * TSP bookkeeping before PSCI executes a power mgmt. operation.
194 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100195const spd_pm_ops_t tspd_pm = {
Achin Gupta607084e2014-02-09 18:24:19 +0000196 tspd_cpu_on_handler,
197 tspd_cpu_off_handler,
198 tspd_cpu_suspend_handler,
199 tspd_cpu_on_finish_handler,
200 tspd_cpu_suspend_finish_handler,
201 NULL,
202 tspd_cpu_migrate_info
203};
204