xref: /optee_os/core/arch/arm/sm/psci.c (revision 789e38a6f8af88dd77ac34147bb6ed1ef33a650e)
1 /*
2  * Copyright (C) 2016 Freescale Semiconductor, Inc.
3  * All rights reserved.
4  *
5  * Peng Fan <peng.fan@nxp.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <console.h>
31 #include <kernel/generic_boot.h>
32 #include <kernel/thread.h>
33 #include <stdint.h>
34 #include <sm/optee_smc.h>
35 #include <sm/psci.h>
36 #include <sm/sm.h>
37 #include <trace.h>
38 
39 __weak uint32_t psci_version(void)
40 {
41 	return PSCI_VERSION_0_2;
42 }
43 
44 __weak int psci_cpu_suspend(uint32_t power_state __unused,
45 			    uintptr_t entry __unused,
46 			    uint32_t context_id __unused,
47 			    struct sm_nsec_ctx *nsec __unused)
48 {
49 	return PSCI_RET_NOT_SUPPORTED;
50 }
51 
52 __weak int psci_cpu_off(void)
53 {
54 	return PSCI_RET_NOT_SUPPORTED;
55 }
56 
57 __weak int psci_cpu_on(uint32_t cpu_id __unused, uint32_t entry __unused,
58 		       uint32_t context_id __unused)
59 {
60 	return PSCI_RET_NOT_SUPPORTED;
61 }
62 
63 __weak int psci_affinity_info(uint32_t affinity __unused,
64 			      uint32_t lowest_affnity_level __unused)
65 {
66 	return PSCI_RET_NOT_SUPPORTED;
67 }
68 
69 __weak int psci_migrate(uint32_t cpu_id __unused)
70 {
71 	return PSCI_RET_NOT_SUPPORTED;
72 }
73 
74 __weak int psci_migrate_info_type(void)
75 {
76 	return PSCI_RET_NOT_SUPPORTED;
77 }
78 
79 __weak int psci_migrate_info_up_cpu(void)
80 {
81 	return PSCI_RET_NOT_SUPPORTED;
82 }
83 
84 __weak void psci_system_off(void)
85 {
86 }
87 
88 __weak void psci_system_reset(void)
89 {
90 }
91 
92 __weak int psci_features(uint32_t psci_fid __unused)
93 {
94 	return PSCI_RET_NOT_SUPPORTED;
95 }
96 
97 __weak int psci_node_hw_state(uint32_t cpu_id __unused,
98 			      uint32_t power_level __unused)
99 {
100 	return PSCI_RET_NOT_SUPPORTED;
101 }
102 
103 __weak int psci_system_suspend(uintptr_t entry __unused,
104 			       uint32_t context_id __unused,
105 			       struct sm_nsec_ctx *nsec __unused)
106 {
107 	return PSCI_RET_NOT_SUPPORTED;
108 }
109 
110 __weak int psci_stat_residency(uint32_t cpu_id __unused,
111 			       uint32_t power_state __unused)
112 {
113 	return PSCI_RET_NOT_SUPPORTED;
114 }
115 
116 __weak int psci_stat_count(uint32_t cpu_id __unused,
117 			   uint32_t power_state __unused)
118 {
119 	return PSCI_RET_NOT_SUPPORTED;
120 }
121 
122 void tee_psci_handler(struct thread_smc_args *args, struct sm_nsec_ctx *nsec)
123 {
124 	uint32_t smc_fid = args->a0;
125 	uint32_t a1 = args->a1;
126 	uint32_t a2 = args->a2;
127 	uint32_t a3 = args->a3;
128 
129 	switch (smc_fid) {
130 	case PSCI_VERSION:
131 		args->a0 = psci_version();
132 		break;
133 	case PSCI_CPU_SUSPEND:
134 		args->a0 = psci_cpu_suspend(a1, a2, a3, nsec);
135 		break;
136 	case PSCI_CPU_OFF:
137 		args->a0 = psci_cpu_off();
138 		break;
139 	case PSCI_CPU_ON:
140 		args->a0 = psci_cpu_on(a1, a2, a3);
141 		break;
142 	case PSCI_AFFINITY_INFO:
143 		args->a0 = psci_affinity_info(a1, a2);
144 		break;
145 	case PSCI_MIGRATE:
146 		args->a0 = psci_migrate(a1);
147 		break;
148 	case PSCI_MIGRATE_INFO_TYPE:
149 		args->a0 = psci_migrate_info_type();
150 		break;
151 	case PSCI_MIGRATE_INFO_UP_CPU:
152 		args->a0 = psci_migrate_info_up_cpu();
153 		break;
154 	case PSCI_SYSTEM_OFF:
155 		psci_system_off();
156 		while (1)
157 			;
158 		break;
159 	case PSCI_SYSTEM_RESET:
160 		psci_system_reset();
161 		while (1)
162 			;
163 		break;
164 	case PSCI_PSCI_FEATURES:
165 		args->a0 = psci_features(a1);
166 		break;
167 	case PSCI_NODE_HW_STATE:
168 		args->a0 = psci_node_hw_state(a1, a2);
169 		break;
170 	case PSCI_SYSTEM_SUSPEND:
171 		args->a0 = psci_system_suspend(a1, a2, nsec);
172 		break;
173 	default:
174 		args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
175 		break;
176 	}
177 }
178