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