xref: /optee_os/core/arch/arm/sm/psci.c (revision 1b181fb2138d6c8e14404737ad8a9cca7afd950a)
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 {
106 	return PSCI_RET_NOT_SUPPORTED;
107 }
108 
109 __weak int psci_stat_residency(uint32_t cpu_id __unused,
110 			       uint32_t power_state __unused)
111 {
112 	return PSCI_RET_NOT_SUPPORTED;
113 }
114 
115 __weak int psci_stat_count(uint32_t cpu_id __unused,
116 			   uint32_t power_state __unused)
117 {
118 	return PSCI_RET_NOT_SUPPORTED;
119 }
120 
121 void tee_psci_handler(struct thread_smc_args *args, struct sm_nsec_ctx *nsec)
122 {
123 	uint32_t smc_fid = args->a0;
124 	uint32_t a1 = args->a1;
125 	uint32_t a2 = args->a2;
126 	uint32_t a3 = args->a3;
127 
128 	switch (smc_fid) {
129 	case PSCI_VERSION:
130 		args->a0 = psci_version();
131 		break;
132 	case PSCI_CPU_SUSPEND:
133 		args->a0 = psci_cpu_suspend(a1, a2, a3, nsec);
134 		break;
135 	case PSCI_CPU_OFF:
136 		args->a0 = psci_cpu_off();
137 		break;
138 	case PSCI_CPU_ON:
139 		args->a0 = psci_cpu_on(a1, a2, a3);
140 		break;
141 	case PSCI_AFFINITY_INFO:
142 		args->a0 = psci_affinity_info(a1, a2);
143 		break;
144 	case PSCI_MIGRATE:
145 		args->a0 = psci_migrate(a1);
146 		break;
147 	case PSCI_MIGRATE_INFO_TYPE:
148 		args->a0 = psci_migrate_info_type();
149 		break;
150 	case PSCI_MIGRATE_INFO_UP_CPU:
151 		args->a0 = psci_migrate_info_up_cpu();
152 		break;
153 	case PSCI_SYSTEM_OFF:
154 		psci_system_off();
155 		while (1)
156 			;
157 		break;
158 	case PSCI_SYSTEM_RESET:
159 		psci_system_reset();
160 		while (1)
161 			;
162 		break;
163 	case PSCI_PSCI_FEATURES:
164 		args->a0 = psci_features(a1);
165 		break;
166 	case PSCI_NODE_HW_STATE:
167 		args->a0 = psci_node_hw_state(a1, a2);
168 		break;
169 	case PSCI_SYSTEM_SUSPEND:
170 		args->a0 = psci_system_suspend(a1, a2);
171 		break;
172 	default:
173 		args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
174 		break;
175 	}
176 }
177