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 40 __weak uint32_t psci_version(void) 41 { 42 return PSCI_VERSION_1_1; 43 } 44 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 53 __weak int psci_cpu_off(void) 54 { 55 return PSCI_RET_NOT_SUPPORTED; 56 } 57 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 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 70 __weak int psci_migrate(uint32_t cpu_id __unused) 71 { 72 return PSCI_RET_NOT_SUPPORTED; 73 } 74 75 __weak int psci_migrate_info_type(void) 76 { 77 return PSCI_RET_NOT_SUPPORTED; 78 } 79 80 __weak int psci_migrate_info_up_cpu(void) 81 { 82 return PSCI_RET_NOT_SUPPORTED; 83 } 84 85 __weak void psci_system_off(void) 86 { 87 } 88 89 __weak void psci_system_reset(void) 90 { 91 } 92 93 __weak int psci_features(uint32_t psci_fid __unused) 94 { 95 return PSCI_RET_NOT_SUPPORTED; 96 } 97 98 __weak int psci_mem_protect(uint32_t enable __unused) 99 { 100 return PSCI_RET_NOT_SUPPORTED; 101 } 102 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 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 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 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 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 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 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