xref: /rk3399_ARM-atf/services/spd/tspd/tspd_pm.c (revision fb037bfb7cbf7b404c069b4ebac5a10059d948b1)
1607084eeSAchin Gupta /*
2607084eeSAchin Gupta  * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
3607084eeSAchin Gupta  *
4607084eeSAchin Gupta  * Redistribution and use in source and binary forms, with or without
5607084eeSAchin Gupta  * modification, are permitted provided that the following conditions are met:
6607084eeSAchin Gupta  *
7607084eeSAchin Gupta  * Redistributions of source code must retain the above copyright notice, this
8607084eeSAchin Gupta  * list of conditions and the following disclaimer.
9607084eeSAchin Gupta  *
10607084eeSAchin Gupta  * Redistributions in binary form must reproduce the above copyright notice,
11607084eeSAchin Gupta  * this list of conditions and the following disclaimer in the documentation
12607084eeSAchin Gupta  * and/or other materials provided with the distribution.
13607084eeSAchin Gupta  *
14607084eeSAchin Gupta  * Neither the name of ARM nor the names of its contributors may be used
15607084eeSAchin Gupta  * to endorse or promote products derived from this software without specific
16607084eeSAchin Gupta  * prior written permission.
17607084eeSAchin Gupta  *
18607084eeSAchin Gupta  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19607084eeSAchin Gupta  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20607084eeSAchin Gupta  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21607084eeSAchin Gupta  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22607084eeSAchin Gupta  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23607084eeSAchin Gupta  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24607084eeSAchin Gupta  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25607084eeSAchin Gupta  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26607084eeSAchin Gupta  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27607084eeSAchin Gupta  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28607084eeSAchin Gupta  * POSSIBILITY OF SUCH DAMAGE.
29607084eeSAchin Gupta  */
30607084eeSAchin Gupta 
31607084eeSAchin Gupta #include <stdio.h>
32607084eeSAchin Gupta #include <string.h>
33607084eeSAchin Gupta #include <assert.h>
34607084eeSAchin Gupta #include <arch_helpers.h>
35607084eeSAchin Gupta #include <console.h>
36607084eeSAchin Gupta #include <platform.h>
37607084eeSAchin Gupta #include <context_mgmt.h>
38607084eeSAchin Gupta #include <runtime_svc.h>
39607084eeSAchin Gupta #include <bl31.h>
40607084eeSAchin Gupta #include <bl32.h>
41607084eeSAchin Gupta #include <psci.h>
42607084eeSAchin Gupta #include <debug.h>
4335e98e55SDan Handley #include "tspd_private.h"
44607084eeSAchin Gupta 
45607084eeSAchin Gupta /*******************************************************************************
46607084eeSAchin Gupta  * The target cpu is being turned on. Allow the TSPD/TSP to perform any actions
47607084eeSAchin Gupta  * needed. Nothing at the moment.
48607084eeSAchin Gupta  ******************************************************************************/
49607084eeSAchin Gupta static void tspd_cpu_on_handler(uint64_t target_cpu)
50607084eeSAchin Gupta {
51607084eeSAchin Gupta }
52607084eeSAchin Gupta 
53607084eeSAchin Gupta /*******************************************************************************
54607084eeSAchin Gupta  * This cpu is being turned off. Allow the TSPD/TSP to perform any actions
55607084eeSAchin Gupta  * needed
56607084eeSAchin Gupta  ******************************************************************************/
57607084eeSAchin Gupta static int32_t tspd_cpu_off_handler(uint64_t cookie)
58607084eeSAchin Gupta {
59607084eeSAchin Gupta 	int32_t rc = 0;
60607084eeSAchin Gupta 	uint64_t mpidr = read_mpidr();
61607084eeSAchin Gupta 	uint32_t linear_id = platform_get_core_pos(mpidr);
62*fb037bfbSDan Handley 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
63607084eeSAchin Gupta 
64607084eeSAchin Gupta 	assert(tsp_entry_info);
65607084eeSAchin Gupta 	assert(tsp_ctx->state == TSP_STATE_ON);
66607084eeSAchin Gupta 
67607084eeSAchin Gupta 	/* Program the entry point and enter the TSP */
68607084eeSAchin Gupta 	cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_off_entry);
69607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
70607084eeSAchin Gupta 
71607084eeSAchin Gupta 	/*
72607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
73607084eeSAchin Gupta 	 * something went wrong while communicating with the TSP.
74607084eeSAchin Gupta 	 */
75607084eeSAchin Gupta 	if (rc != 0)
76607084eeSAchin Gupta 		panic();
77607084eeSAchin Gupta 
78607084eeSAchin Gupta 	/*
79607084eeSAchin Gupta 	 * Reset TSP's context for a fresh start when this cpu is turned on
80607084eeSAchin Gupta 	 * subsequently.
81607084eeSAchin Gupta 	 */
82607084eeSAchin Gupta 	 tsp_ctx->state = TSP_STATE_OFF;
83607084eeSAchin Gupta 
84607084eeSAchin Gupta 	 return 0;
85607084eeSAchin Gupta }
86607084eeSAchin Gupta 
87607084eeSAchin Gupta /*******************************************************************************
88607084eeSAchin Gupta  * This cpu is being suspended. S-EL1 state must have been saved in the
89607084eeSAchin Gupta  * resident cpu (mpidr format) if it is a UP/UP migratable TSP.
90607084eeSAchin Gupta  ******************************************************************************/
91607084eeSAchin Gupta static void tspd_cpu_suspend_handler(uint64_t power_state)
92607084eeSAchin Gupta {
93607084eeSAchin Gupta 	int32_t rc = 0;
94607084eeSAchin Gupta 	uint64_t mpidr = read_mpidr();
95607084eeSAchin Gupta 	uint32_t linear_id = platform_get_core_pos(mpidr);
96*fb037bfbSDan Handley 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
97607084eeSAchin Gupta 
98607084eeSAchin Gupta 	assert(tsp_entry_info);
99607084eeSAchin Gupta 	assert(tsp_ctx->state == TSP_STATE_ON);
100607084eeSAchin Gupta 
101607084eeSAchin Gupta 	/* Program the entry point, power_state parameter and enter the TSP */
102607084eeSAchin Gupta 	write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
103607084eeSAchin Gupta 		      CTX_GPREG_X0,
104607084eeSAchin Gupta 		      power_state);
105607084eeSAchin Gupta 	cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_suspend_entry);
106607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
107607084eeSAchin Gupta 
108607084eeSAchin Gupta 	/*
109607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
110607084eeSAchin Gupta 	 * something went wrong while communicating with the TSP.
111607084eeSAchin Gupta 	 */
112607084eeSAchin Gupta 	if (rc != 0)
113607084eeSAchin Gupta 		panic();
114607084eeSAchin Gupta 
115607084eeSAchin Gupta 	/* Update its context to reflect the state the TSP is in */
116607084eeSAchin Gupta 	tsp_ctx->state = TSP_STATE_SUSPEND;
117607084eeSAchin Gupta }
118607084eeSAchin Gupta 
119607084eeSAchin Gupta /*******************************************************************************
120607084eeSAchin Gupta  * This cpu has been turned on. Enter the TSP to initialise S-EL1 and other bits
121607084eeSAchin Gupta  * before passing control back to the Secure Monitor. Entry in S-El1 is done
122607084eeSAchin Gupta  * after initialising minimal architectural state that guarantees safe
123607084eeSAchin Gupta  * execution.
124607084eeSAchin Gupta  ******************************************************************************/
125607084eeSAchin Gupta static void tspd_cpu_on_finish_handler(uint64_t cookie)
126607084eeSAchin Gupta {
127607084eeSAchin Gupta 	int32_t rc = 0;
128607084eeSAchin Gupta 	uint64_t mpidr = read_mpidr();
129607084eeSAchin Gupta 	uint32_t linear_id = platform_get_core_pos(mpidr);
130*fb037bfbSDan Handley 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
131607084eeSAchin Gupta 
132607084eeSAchin Gupta 	assert(tsp_entry_info);
133607084eeSAchin Gupta 	assert(tsp_ctx->state == TSP_STATE_OFF);
134607084eeSAchin Gupta 
135607084eeSAchin Gupta 	/* Initialise this cpu's secure context */
136607084eeSAchin Gupta 	tspd_init_secure_context((uint64_t) tsp_entry_info->cpu_on_entry,
137607084eeSAchin Gupta 				TSP_AARCH64,
138607084eeSAchin Gupta 				mpidr,
139607084eeSAchin Gupta 				tsp_ctx);
140607084eeSAchin Gupta 
141607084eeSAchin Gupta 	/* Enter the TSP */
142607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
143607084eeSAchin Gupta 
144607084eeSAchin Gupta 	/*
145607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
146607084eeSAchin Gupta 	 * something went wrong while communicating with the SP.
147607084eeSAchin Gupta 	 */
148607084eeSAchin Gupta 	if (rc != 0)
149607084eeSAchin Gupta 		panic();
150607084eeSAchin Gupta 
151607084eeSAchin Gupta 	/* Update its context to reflect the state the SP is in */
152607084eeSAchin Gupta 	tsp_ctx->state = TSP_STATE_ON;
153607084eeSAchin Gupta }
154607084eeSAchin Gupta 
155607084eeSAchin Gupta /*******************************************************************************
156607084eeSAchin Gupta  * This cpu has resumed from suspend. The SPD saved the TSP context when it
157607084eeSAchin Gupta  * completed the preceding suspend call. Use that context to program an entry
158607084eeSAchin Gupta  * into the TSP to allow it to do any remaining book keeping
159607084eeSAchin Gupta  ******************************************************************************/
160607084eeSAchin Gupta static void tspd_cpu_suspend_finish_handler(uint64_t suspend_level)
161607084eeSAchin Gupta {
162607084eeSAchin Gupta 	int32_t rc = 0;
163607084eeSAchin Gupta 	uint64_t mpidr = read_mpidr();
164607084eeSAchin Gupta 	uint32_t linear_id = platform_get_core_pos(mpidr);
165*fb037bfbSDan Handley 	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
166607084eeSAchin Gupta 
167607084eeSAchin Gupta 	assert(tsp_entry_info);
168607084eeSAchin Gupta 	assert(tsp_ctx->state == TSP_STATE_SUSPEND);
169607084eeSAchin Gupta 
170607084eeSAchin Gupta 	/* Program the entry point, suspend_level and enter the SP */
171607084eeSAchin Gupta 	write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
172607084eeSAchin Gupta 		      CTX_GPREG_X0,
173607084eeSAchin Gupta 		      suspend_level);
174607084eeSAchin Gupta 	cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_resume_entry);
175607084eeSAchin Gupta 	rc = tspd_synchronous_sp_entry(tsp_ctx);
176607084eeSAchin Gupta 
177607084eeSAchin Gupta 	/*
178607084eeSAchin Gupta 	 * Read the response from the TSP. A non-zero return means that
179607084eeSAchin Gupta 	 * something went wrong while communicating with the TSP.
180607084eeSAchin Gupta 	 */
181607084eeSAchin Gupta 	if (rc != 0)
182607084eeSAchin Gupta 		panic();
183607084eeSAchin Gupta 
184607084eeSAchin Gupta 	/* Update its context to reflect the state the SP is in */
185607084eeSAchin Gupta 	tsp_ctx->state = TSP_STATE_ON;
186607084eeSAchin Gupta }
187607084eeSAchin Gupta 
188607084eeSAchin Gupta /*******************************************************************************
189607084eeSAchin Gupta  * Return the type of TSP the TSPD is dealing with. Report the current resident
190607084eeSAchin Gupta  * cpu (mpidr format) if it is a UP/UP migratable TSP.
191607084eeSAchin Gupta  ******************************************************************************/
192607084eeSAchin Gupta static int32_t tspd_cpu_migrate_info(uint64_t *resident_cpu)
193607084eeSAchin Gupta {
194607084eeSAchin Gupta 	return TSP_MIGRATE_INFO;
195607084eeSAchin Gupta }
196607084eeSAchin Gupta 
197607084eeSAchin Gupta /*******************************************************************************
198607084eeSAchin Gupta  * Structure populated by the TSP Dispatcher to be given a chance to perform any
199607084eeSAchin Gupta  * TSP bookkeeping before PSCI executes a power mgmt.  operation.
200607084eeSAchin Gupta  ******************************************************************************/
201*fb037bfbSDan Handley const spd_pm_ops_t tspd_pm = {
202607084eeSAchin Gupta 	tspd_cpu_on_handler,
203607084eeSAchin Gupta 	tspd_cpu_off_handler,
204607084eeSAchin Gupta 	tspd_cpu_suspend_handler,
205607084eeSAchin Gupta 	tspd_cpu_on_finish_handler,
206607084eeSAchin Gupta 	tspd_cpu_suspend_finish_handler,
207607084eeSAchin Gupta 	NULL,
208607084eeSAchin Gupta 	tspd_cpu_migrate_info
209607084eeSAchin Gupta };
210607084eeSAchin Gupta 
211