xref: /rk3399_ARM-atf/services/spd/tspd/tspd_pm.c (revision cd529320988a559c3408292f09e443233d2157c3)
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 <stdio.h>
32 #include <string.h>
33 #include <assert.h>
34 #include <arch_helpers.h>
35 #include <console.h>
36 #include <platform.h>
37 #include <psci_private.h>
38 #include <context_mgmt.h>
39 #include <runtime_svc.h>
40 #include <bl31.h>
41 #include <bl32.h>
42 #include <psci.h>
43 #include <tspd_private.h>
44 #include <debug.h>
45 
46 /*******************************************************************************
47  * The target cpu is being turned on. Allow the TSPD/TSP to perform any actions
48  * needed. Nothing at the moment.
49  ******************************************************************************/
50 static void tspd_cpu_on_handler(uint64_t target_cpu)
51 {
52 }
53 
54 /*******************************************************************************
55  * This cpu is being turned off. Allow the TSPD/TSP to perform any actions
56  * needed
57  ******************************************************************************/
58 static int32_t tspd_cpu_off_handler(uint64_t cookie)
59 {
60 	int32_t rc = 0;
61 	uint64_t mpidr = read_mpidr();
62 	uint32_t linear_id = platform_get_core_pos(mpidr);
63 	tsp_context *tsp_ctx = &tspd_sp_context[linear_id];
64 
65 	assert(tsp_entry_info);
66 	assert(tsp_ctx->state == TSP_STATE_ON);
67 
68 	/* Program the entry point and enter the TSP */
69 	cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_off_entry);
70 	rc = tspd_synchronous_sp_entry(tsp_ctx);
71 
72 	/*
73 	 * Read the response from the TSP. A non-zero return means that
74 	 * something went wrong while communicating with the TSP.
75 	 */
76 	if (rc != 0)
77 		panic();
78 
79 	/*
80 	 * Reset TSP's context for a fresh start when this cpu is turned on
81 	 * subsequently.
82 	 */
83 	 tsp_ctx->state = TSP_STATE_OFF;
84 
85 	 return 0;
86 }
87 
88 /*******************************************************************************
89  * This cpu is being suspended. S-EL1 state must have been saved in the
90  * resident cpu (mpidr format) if it is a UP/UP migratable TSP.
91  ******************************************************************************/
92 static void tspd_cpu_suspend_handler(uint64_t power_state)
93 {
94 	int32_t rc = 0;
95 	uint64_t mpidr = read_mpidr();
96 	uint32_t linear_id = platform_get_core_pos(mpidr);
97 	tsp_context *tsp_ctx = &tspd_sp_context[linear_id];
98 
99 	assert(tsp_entry_info);
100 	assert(tsp_ctx->state == TSP_STATE_ON);
101 
102 	/* Program the entry point, power_state parameter and enter the TSP */
103 	write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
104 		      CTX_GPREG_X0,
105 		      power_state);
106 	cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_suspend_entry);
107 	rc = tspd_synchronous_sp_entry(tsp_ctx);
108 
109 	/*
110 	 * Read the response from the TSP. A non-zero return means that
111 	 * something went wrong while communicating with the TSP.
112 	 */
113 	if (rc != 0)
114 		panic();
115 
116 	/* Update its context to reflect the state the TSP is in */
117 	tsp_ctx->state = TSP_STATE_SUSPEND;
118 }
119 
120 /*******************************************************************************
121  * This cpu has been turned on. Enter the TSP to initialise S-EL1 and other bits
122  * before passing control back to the Secure Monitor. Entry in S-El1 is done
123  * after initialising minimal architectural state that guarantees safe
124  * execution.
125  ******************************************************************************/
126 static void tspd_cpu_on_finish_handler(uint64_t cookie)
127 {
128 	int32_t rc = 0;
129 	uint64_t mpidr = read_mpidr();
130 	uint32_t linear_id = platform_get_core_pos(mpidr);
131 	tsp_context *tsp_ctx = &tspd_sp_context[linear_id];
132 
133 	assert(tsp_entry_info);
134 	assert(tsp_ctx->state == TSP_STATE_OFF);
135 
136 	/* Initialise this cpu's secure context */
137 	tspd_init_secure_context((uint64_t) tsp_entry_info->cpu_on_entry,
138 				TSP_AARCH64,
139 				mpidr,
140 				tsp_ctx);
141 
142 	/* Enter the TSP */
143 	rc = tspd_synchronous_sp_entry(tsp_ctx);
144 
145 	/*
146 	 * Read the response from the TSP. A non-zero return means that
147 	 * something went wrong while communicating with the SP.
148 	 */
149 	if (rc != 0)
150 		panic();
151 
152 	/* Update its context to reflect the state the SP is in */
153 	tsp_ctx->state = TSP_STATE_ON;
154 }
155 
156 /*******************************************************************************
157  * This cpu has resumed from suspend. The SPD saved the TSP context when it
158  * completed the preceding suspend call. Use that context to program an entry
159  * into the TSP to allow it to do any remaining book keeping
160  ******************************************************************************/
161 static void tspd_cpu_suspend_finish_handler(uint64_t suspend_level)
162 {
163 	int32_t rc = 0;
164 	uint64_t mpidr = read_mpidr();
165 	uint32_t linear_id = platform_get_core_pos(mpidr);
166 	tsp_context *tsp_ctx = &tspd_sp_context[linear_id];
167 
168 	assert(tsp_entry_info);
169 	assert(tsp_ctx->state == TSP_STATE_SUSPEND);
170 
171 	/* Program the entry point, suspend_level and enter the SP */
172 	write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
173 		      CTX_GPREG_X0,
174 		      suspend_level);
175 	cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_resume_entry);
176 	rc = tspd_synchronous_sp_entry(tsp_ctx);
177 
178 	/*
179 	 * Read the response from the TSP. A non-zero return means that
180 	 * something went wrong while communicating with the TSP.
181 	 */
182 	if (rc != 0)
183 		panic();
184 
185 	/* Update its context to reflect the state the SP is in */
186 	tsp_ctx->state = TSP_STATE_ON;
187 }
188 
189 /*******************************************************************************
190  * Return the type of TSP the TSPD is dealing with. Report the current resident
191  * cpu (mpidr format) if it is a UP/UP migratable TSP.
192  ******************************************************************************/
193 static int32_t tspd_cpu_migrate_info(uint64_t *resident_cpu)
194 {
195 	return TSP_MIGRATE_INFO;
196 }
197 
198 /*******************************************************************************
199  * Structure populated by the TSP Dispatcher to be given a chance to perform any
200  * TSP bookkeeping before PSCI executes a power mgmt.  operation.
201  ******************************************************************************/
202 const spd_pm_ops spd_pm = {
203 	tspd_cpu_on_handler,
204 	tspd_cpu_off_handler,
205 	tspd_cpu_suspend_handler,
206 	tspd_cpu_on_finish_handler,
207 	tspd_cpu_suspend_finish_handler,
208 	NULL,
209 	tspd_cpu_migrate_info
210 };
211 
212