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