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