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