1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2016 Freescale Semiconductor, Inc.
4  * All rights reserved.
5  *
6  * Peng Fan <peng.fan@nxp.com>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  * this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
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 <console.h>
32 #include <kernel/boot.h>
33 #include <kernel/thread.h>
34 #include <stdint.h>
35 #include <sm/optee_smc.h>
36 #include <sm/psci.h>
37 #include <sm/sm.h>
38 #include <trace.h>
39 
psci_version(void)40 __weak uint32_t psci_version(void)
41 {
42 	return PSCI_VERSION_1_1;
43 }
44 
psci_cpu_suspend(uint32_t power_state __unused,uintptr_t entry __unused,uint32_t context_id __unused,struct sm_nsec_ctx * nsec __unused)45 __weak int psci_cpu_suspend(uint32_t power_state __unused,
46 			    uintptr_t entry __unused,
47 			    uint32_t context_id __unused,
48 			    struct sm_nsec_ctx *nsec __unused)
49 {
50 	return PSCI_RET_NOT_SUPPORTED;
51 }
52 
psci_cpu_off(void)53 __weak int psci_cpu_off(void)
54 {
55 	return PSCI_RET_NOT_SUPPORTED;
56 }
57 
psci_cpu_on(uint32_t cpu_id __unused,uint32_t entry __unused,uint32_t context_id __unused)58 __weak int psci_cpu_on(uint32_t cpu_id __unused, uint32_t entry __unused,
59 		       uint32_t context_id __unused)
60 {
61 	return PSCI_RET_NOT_SUPPORTED;
62 }
63 
psci_affinity_info(uint32_t affinity __unused,uint32_t lowest_affnity_level __unused)64 __weak int psci_affinity_info(uint32_t affinity __unused,
65 			      uint32_t lowest_affnity_level __unused)
66 {
67 	return PSCI_RET_NOT_SUPPORTED;
68 }
69 
psci_migrate(uint32_t cpu_id __unused)70 __weak int psci_migrate(uint32_t cpu_id __unused)
71 {
72 	return PSCI_RET_NOT_SUPPORTED;
73 }
74 
psci_migrate_info_type(void)75 __weak int psci_migrate_info_type(void)
76 {
77 	return PSCI_RET_NOT_SUPPORTED;
78 }
79 
psci_migrate_info_up_cpu(void)80 __weak int psci_migrate_info_up_cpu(void)
81 {
82 	return PSCI_RET_NOT_SUPPORTED;
83 }
84 
psci_system_off(void)85 __weak void psci_system_off(void)
86 {
87 }
88 
psci_system_reset(void)89 __weak void psci_system_reset(void)
90 {
91 }
92 
psci_features(uint32_t psci_fid __unused)93 __weak int psci_features(uint32_t psci_fid __unused)
94 {
95 	return PSCI_RET_NOT_SUPPORTED;
96 }
97 
psci_mem_protect(uint32_t enable __unused)98 __weak int psci_mem_protect(uint32_t enable __unused)
99 {
100 	return PSCI_RET_NOT_SUPPORTED;
101 }
102 
psci_mem_chk_range(paddr_t base __unused,size_t length __unused)103 __weak int psci_mem_chk_range(paddr_t base __unused,
104 			      size_t length __unused)
105 {
106 	return PSCI_RET_NOT_SUPPORTED;
107 }
108 
psci_system_reset2(uint32_t reset_type __unused,uint32_t cookie __unused)109 __weak int psci_system_reset2(uint32_t reset_type __unused,
110 			      uint32_t cookie __unused)
111 {
112 	return PSCI_RET_NOT_SUPPORTED;
113 }
114 
psci_node_hw_state(uint32_t cpu_id __unused,uint32_t power_level __unused)115 __weak int psci_node_hw_state(uint32_t cpu_id __unused,
116 			      uint32_t power_level __unused)
117 {
118 	return PSCI_RET_NOT_SUPPORTED;
119 }
120 
psci_system_suspend(uintptr_t entry __unused,uint32_t context_id __unused,struct sm_nsec_ctx * nsec __unused)121 __weak int psci_system_suspend(uintptr_t entry __unused,
122 			       uint32_t context_id __unused,
123 			       struct sm_nsec_ctx *nsec __unused)
124 {
125 	return PSCI_RET_NOT_SUPPORTED;
126 }
127 
psci_stat_residency(uint32_t cpu_id __unused,uint32_t power_state __unused)128 __weak int psci_stat_residency(uint32_t cpu_id __unused,
129 			       uint32_t power_state __unused)
130 {
131 	return PSCI_RET_NOT_SUPPORTED;
132 }
133 
psci_stat_count(uint32_t cpu_id __unused,uint32_t power_state __unused)134 __weak int psci_stat_count(uint32_t cpu_id __unused,
135 			   uint32_t power_state __unused)
136 {
137 	return PSCI_RET_NOT_SUPPORTED;
138 }
139 
tee_psci_handler(struct thread_smc_args * args,struct sm_nsec_ctx * nsec)140 void tee_psci_handler(struct thread_smc_args *args, struct sm_nsec_ctx *nsec)
141 {
142 	uint32_t smc_fid = args->a0;
143 	uint32_t a1 = args->a1;
144 	uint32_t a2 = args->a2;
145 	uint32_t a3 = args->a3;
146 
147 	switch (smc_fid) {
148 	case PSCI_VERSION:
149 		args->a0 = psci_version();
150 		break;
151 	case PSCI_CPU_SUSPEND:
152 		args->a0 = psci_cpu_suspend(a1, a2, a3, nsec);
153 		break;
154 	case PSCI_CPU_OFF:
155 		args->a0 = psci_cpu_off();
156 		break;
157 	case PSCI_CPU_ON:
158 		args->a0 = psci_cpu_on(a1, a2, a3);
159 		break;
160 	case PSCI_AFFINITY_INFO:
161 		args->a0 = psci_affinity_info(a1, a2);
162 		break;
163 	case PSCI_MIGRATE:
164 		args->a0 = psci_migrate(a1);
165 		break;
166 	case PSCI_MIGRATE_INFO_TYPE:
167 		args->a0 = psci_migrate_info_type();
168 		break;
169 	case PSCI_MIGRATE_INFO_UP_CPU:
170 		args->a0 = psci_migrate_info_up_cpu();
171 		break;
172 	case PSCI_SYSTEM_OFF:
173 		psci_system_off();
174 		while (1)
175 			;
176 		break;
177 	case PSCI_SYSTEM_RESET:
178 		psci_system_reset();
179 		while (1)
180 			;
181 		break;
182 	case PSCI_PSCI_FEATURES:
183 		args->a0 = psci_features(a1);
184 		break;
185 	case PSCI_SYSTEM_RESET2:
186 		args->a0 = psci_system_reset2(a1, a2);
187 		break;
188 	case PSCI_MEM_PROTECT:
189 		args->a0 = psci_mem_protect(a1);
190 		break;
191 	case PSCI_MEM_PROTECT_CHECK_RANGE:
192 		args->a0 = psci_mem_chk_range(a1, a2);
193 		break;
194 	case PSCI_NODE_HW_STATE:
195 		args->a0 = psci_node_hw_state(a1, a2);
196 		break;
197 	case PSCI_SYSTEM_SUSPEND:
198 		args->a0 = psci_system_suspend(a1, a2, nsec);
199 		break;
200 	default:
201 		args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
202 		break;
203 	}
204 }
205