xref: /rk3399_ARM-atf/services/spd/tspd/tspd_pm.c (revision 607084ee4c2a7c20832beb8cd1d5cebf02b2cb26)
1*607084eeSAchin Gupta /*
2*607084eeSAchin Gupta  * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
3*607084eeSAchin Gupta  *
4*607084eeSAchin Gupta  * Redistribution and use in source and binary forms, with or without
5*607084eeSAchin Gupta  * modification, are permitted provided that the following conditions are met:
6*607084eeSAchin Gupta  *
7*607084eeSAchin Gupta  * Redistributions of source code must retain the above copyright notice, this
8*607084eeSAchin Gupta  * list of conditions and the following disclaimer.
9*607084eeSAchin Gupta  *
10*607084eeSAchin Gupta  * Redistributions in binary form must reproduce the above copyright notice,
11*607084eeSAchin Gupta  * this list of conditions and the following disclaimer in the documentation
12*607084eeSAchin Gupta  * and/or other materials provided with the distribution.
13*607084eeSAchin Gupta  *
14*607084eeSAchin Gupta  * Neither the name of ARM nor the names of its contributors may be used
15*607084eeSAchin Gupta  * to endorse or promote products derived from this software without specific
16*607084eeSAchin Gupta  * prior written permission.
17*607084eeSAchin Gupta  *
18*607084eeSAchin Gupta  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*607084eeSAchin Gupta  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*607084eeSAchin Gupta  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*607084eeSAchin Gupta  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22*607084eeSAchin Gupta  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*607084eeSAchin Gupta  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*607084eeSAchin Gupta  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*607084eeSAchin Gupta  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*607084eeSAchin Gupta  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*607084eeSAchin Gupta  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*607084eeSAchin Gupta  * POSSIBILITY OF SUCH DAMAGE.
29*607084eeSAchin Gupta  */
30*607084eeSAchin Gupta 
31*607084eeSAchin Gupta #include <stdio.h>
32*607084eeSAchin Gupta #include <string.h>
33*607084eeSAchin Gupta #include <assert.h>
34*607084eeSAchin Gupta #include <arch_helpers.h>
35*607084eeSAchin Gupta #include <console.h>
36*607084eeSAchin Gupta #include <platform.h>
37*607084eeSAchin Gupta #include <psci_private.h>
38*607084eeSAchin Gupta #include <context_mgmt.h>
39*607084eeSAchin Gupta #include <runtime_svc.h>
40*607084eeSAchin Gupta #include <bl31.h>
41*607084eeSAchin Gupta #include <bl32.h>
42*607084eeSAchin Gupta #include <psci.h>
43*607084eeSAchin Gupta #include <tspd_private.h>
44*607084eeSAchin Gupta #include <debug.h>
45*607084eeSAchin Gupta 
46*607084eeSAchin Gupta /*******************************************************************************
47*607084eeSAchin Gupta  * The target cpu is being turned on. Allow the TSPD/TSP to perform any actions
48*607084eeSAchin Gupta  * needed. Nothing at the moment.
49*607084eeSAchin Gupta  ******************************************************************************/
50*607084eeSAchin Gupta static void tspd_cpu_on_handler(uint64_t target_cpu)
51*607084eeSAchin Gupta {
52*607084eeSAchin Gupta }
53*607084eeSAchin Gupta 
54*607084eeSAchin Gupta /*******************************************************************************
55*607084eeSAchin Gupta  * This cpu is being turned off. Allow the TSPD/TSP to perform any actions
56*607084eeSAchin Gupta  * needed
57*607084eeSAchin Gupta  ******************************************************************************/
58*607084eeSAchin Gupta static int32_t tspd_cpu_off_handler(uint64_t cookie)
59*607084eeSAchin Gupta {
60*607084eeSAchin Gupta 	int32_t rc = 0;
61*607084eeSAchin Gupta 	uint64_t mpidr = read_mpidr();
62*607084eeSAchin Gupta 	uint32_t linear_id = platform_get_core_pos(mpidr);
63*607084eeSAchin Gupta 	tsp_context *tsp_ctx = &tspd_sp_context[linear_id];
64*607084eeSAchin Gupta 
65*607084eeSAchin Gupta 	assert(tsp_entry_info);
66*607084eeSAchin Gupta 	assert(tsp_ctx->state == TSP_STATE_ON);
67*607084eeSAchin Gupta 
68*607084eeSAchin Gupta 	/* Program the entry point and enter the TSP */
69*607084eeSAchin Gupta 	cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_off_entry);
70*607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
71*607084eeSAchin Gupta 
72*607084eeSAchin Gupta 	/*
73*607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
74*607084eeSAchin Gupta 	 * something went wrong while communicating with the TSP.
75*607084eeSAchin Gupta 	 */
76*607084eeSAchin Gupta 	if (rc != 0)
77*607084eeSAchin Gupta 		panic();
78*607084eeSAchin Gupta 
79*607084eeSAchin Gupta 	/*
80*607084eeSAchin Gupta 	 * Reset TSP's context for a fresh start when this cpu is turned on
81*607084eeSAchin Gupta 	 * subsequently.
82*607084eeSAchin Gupta 	 */
83*607084eeSAchin Gupta 	 tsp_ctx->state = TSP_STATE_OFF;
84*607084eeSAchin Gupta 
85*607084eeSAchin Gupta 	 return 0;
86*607084eeSAchin Gupta }
87*607084eeSAchin Gupta 
88*607084eeSAchin Gupta /*******************************************************************************
89*607084eeSAchin Gupta  * This cpu is being suspended. S-EL1 state must have been saved in the
90*607084eeSAchin Gupta  * resident cpu (mpidr format) if it is a UP/UP migratable TSP.
91*607084eeSAchin Gupta  ******************************************************************************/
92*607084eeSAchin Gupta static void tspd_cpu_suspend_handler(uint64_t power_state)
93*607084eeSAchin Gupta {
94*607084eeSAchin Gupta 	int32_t rc = 0;
95*607084eeSAchin Gupta 	uint64_t mpidr = read_mpidr();
96*607084eeSAchin Gupta 	uint32_t linear_id = platform_get_core_pos(mpidr);
97*607084eeSAchin Gupta 	tsp_context *tsp_ctx = &tspd_sp_context[linear_id];
98*607084eeSAchin Gupta 
99*607084eeSAchin Gupta 	assert(tsp_entry_info);
100*607084eeSAchin Gupta 	assert(tsp_ctx->state == TSP_STATE_ON);
101*607084eeSAchin Gupta 
102*607084eeSAchin Gupta 	/* Program the entry point, power_state parameter and enter the TSP */
103*607084eeSAchin Gupta 	write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
104*607084eeSAchin Gupta 		      CTX_GPREG_X0,
105*607084eeSAchin Gupta 		      power_state);
106*607084eeSAchin Gupta 	cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_suspend_entry);
107*607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
108*607084eeSAchin Gupta 
109*607084eeSAchin Gupta 	/*
110*607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
111*607084eeSAchin Gupta 	 * something went wrong while communicating with the TSP.
112*607084eeSAchin Gupta 	 */
113*607084eeSAchin Gupta 	if (rc != 0)
114*607084eeSAchin Gupta 		panic();
115*607084eeSAchin Gupta 
116*607084eeSAchin Gupta 	/* Update its context to reflect the state the TSP is in */
117*607084eeSAchin Gupta 	tsp_ctx->state = TSP_STATE_SUSPEND;
118*607084eeSAchin Gupta }
119*607084eeSAchin Gupta 
120*607084eeSAchin Gupta /*******************************************************************************
121*607084eeSAchin Gupta  * This cpu has been turned on. Enter the TSP to initialise S-EL1 and other bits
122*607084eeSAchin Gupta  * before passing control back to the Secure Monitor. Entry in S-El1 is done
123*607084eeSAchin Gupta  * after initialising minimal architectural state that guarantees safe
124*607084eeSAchin Gupta  * execution.
125*607084eeSAchin Gupta  ******************************************************************************/
126*607084eeSAchin Gupta static void tspd_cpu_on_finish_handler(uint64_t cookie)
127*607084eeSAchin Gupta {
128*607084eeSAchin Gupta 	int32_t rc = 0;
129*607084eeSAchin Gupta 	uint64_t mpidr = read_mpidr();
130*607084eeSAchin Gupta 	uint32_t linear_id = platform_get_core_pos(mpidr);
131*607084eeSAchin Gupta 	tsp_context *tsp_ctx = &tspd_sp_context[linear_id];
132*607084eeSAchin Gupta 
133*607084eeSAchin Gupta 	assert(tsp_entry_info);
134*607084eeSAchin Gupta 	assert(tsp_ctx->state == TSP_STATE_OFF);
135*607084eeSAchin Gupta 
136*607084eeSAchin Gupta 	/* Initialise this cpu's secure context */
137*607084eeSAchin Gupta 	tspd_init_secure_context((uint64_t) tsp_entry_info->cpu_on_entry,
138*607084eeSAchin Gupta 				TSP_AARCH64,
139*607084eeSAchin Gupta 				mpidr,
140*607084eeSAchin Gupta 				tsp_ctx);
141*607084eeSAchin Gupta 
142*607084eeSAchin Gupta 	/* Enter the TSP */
143*607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
144*607084eeSAchin Gupta 
145*607084eeSAchin Gupta 	/*
146*607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
147*607084eeSAchin Gupta 	 * something went wrong while communicating with the SP.
148*607084eeSAchin Gupta 	 */
149*607084eeSAchin Gupta 	if (rc != 0)
150*607084eeSAchin Gupta 		panic();
151*607084eeSAchin Gupta 
152*607084eeSAchin Gupta 	/* Update its context to reflect the state the SP is in */
153*607084eeSAchin Gupta 	tsp_ctx->state = TSP_STATE_ON;
154*607084eeSAchin Gupta }
155*607084eeSAchin Gupta 
156*607084eeSAchin Gupta /*******************************************************************************
157*607084eeSAchin Gupta  * This cpu has resumed from suspend. The SPD saved the TSP context when it
158*607084eeSAchin Gupta  * completed the preceding suspend call. Use that context to program an entry
159*607084eeSAchin Gupta  * into the TSP to allow it to do any remaining book keeping
160*607084eeSAchin Gupta  ******************************************************************************/
161*607084eeSAchin Gupta static void tspd_cpu_suspend_finish_handler(uint64_t suspend_level)
162*607084eeSAchin Gupta {
163*607084eeSAchin Gupta 	int32_t rc = 0;
164*607084eeSAchin Gupta 	uint64_t mpidr = read_mpidr();
165*607084eeSAchin Gupta 	uint32_t linear_id = platform_get_core_pos(mpidr);
166*607084eeSAchin Gupta 	tsp_context *tsp_ctx = &tspd_sp_context[linear_id];
167*607084eeSAchin Gupta 
168*607084eeSAchin Gupta 	assert(tsp_entry_info);
169*607084eeSAchin Gupta 	assert(tsp_ctx->state == TSP_STATE_SUSPEND);
170*607084eeSAchin Gupta 
171*607084eeSAchin Gupta 	/* Program the entry point, suspend_level and enter the SP */
172*607084eeSAchin Gupta 	write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
173*607084eeSAchin Gupta 		      CTX_GPREG_X0,
174*607084eeSAchin Gupta 		      suspend_level);
175*607084eeSAchin Gupta 	cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_resume_entry);
176*607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
177*607084eeSAchin Gupta 
178*607084eeSAchin Gupta 	/*
179*607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
180*607084eeSAchin Gupta 	 * something went wrong while communicating with the TSP.
181*607084eeSAchin Gupta 	 */
182*607084eeSAchin Gupta 	if (rc != 0)
183*607084eeSAchin Gupta 		panic();
184*607084eeSAchin Gupta 
185*607084eeSAchin Gupta 	/* Update its context to reflect the state the SP is in */
186*607084eeSAchin Gupta 	tsp_ctx->state = TSP_STATE_ON;
187*607084eeSAchin Gupta }
188*607084eeSAchin Gupta 
189*607084eeSAchin Gupta /*******************************************************************************
190*607084eeSAchin Gupta  * Return the type of TSP the TSPD is dealing with. Report the current resident
191*607084eeSAchin Gupta  * cpu (mpidr format) if it is a UP/UP migratable TSP.
192*607084eeSAchin Gupta  ******************************************************************************/
193*607084eeSAchin Gupta static int32_t tspd_cpu_migrate_info(uint64_t *resident_cpu)
194*607084eeSAchin Gupta {
195*607084eeSAchin Gupta 	return TSP_MIGRATE_INFO;
196*607084eeSAchin Gupta }
197*607084eeSAchin Gupta 
198*607084eeSAchin Gupta /*******************************************************************************
199*607084eeSAchin Gupta  * Structure populated by the TSP Dispatcher to be given a chance to perform any
200*607084eeSAchin Gupta  * TSP bookkeeping before PSCI executes a power mgmt.  operation.
201*607084eeSAchin Gupta  ******************************************************************************/
202*607084eeSAchin Gupta const spd_pm_ops spd_pm = {
203*607084eeSAchin Gupta 	tspd_cpu_on_handler,
204*607084eeSAchin Gupta 	tspd_cpu_off_handler,
205*607084eeSAchin Gupta 	tspd_cpu_suspend_handler,
206*607084eeSAchin Gupta 	tspd_cpu_on_finish_handler,
207*607084eeSAchin Gupta 	tspd_cpu_suspend_finish_handler,
208*607084eeSAchin Gupta 	NULL,
209*607084eeSAchin Gupta 	tspd_cpu_migrate_info
210*607084eeSAchin Gupta };
211*607084eeSAchin Gupta 
212