1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2017-2018, STMicroelectronics 4 */ 5 6 #include <arm.h> 7 #include <boot_api.h> 8 #include <drivers/stm32mp1_rcc.h> 9 #include <io.h> 10 #include <kernel/cache_helpers.h> 11 #include <kernel/delay.h> 12 #include <kernel/generic_boot.h> 13 #include <kernel/interrupt.h> 14 #include <kernel/misc.h> 15 #include <kernel/panic.h> 16 #include <kernel/spinlock.h> 17 #include <mm/core_memprot.h> 18 #include <platform_config.h> 19 #include <sm/psci.h> 20 #include <stm32_util.h> 21 #include <trace.h> 22 23 /* 24 * SMP boot support and access to the mailbox 25 */ 26 27 enum core_state_id { 28 CORE_OFF = 0, 29 CORE_RET, 30 CORE_AWAKE, 31 CORE_ON, 32 }; 33 34 static enum core_state_id core_state[CFG_TEE_CORE_NB_CORE]; 35 static unsigned int __maybe_unused state_lock = SPINLOCK_UNLOCK; 36 37 static uint32_t __maybe_unused lock_state_access(void) 38 { 39 return may_spin_lock(&state_lock); 40 } 41 42 static void __maybe_unused unlock_state_access(uint32_t exceptions) 43 { 44 may_spin_unlock(&state_lock, exceptions); 45 } 46 47 int psci_affinity_info(uint32_t affinity, uint32_t lowest_affinity_level) 48 { 49 unsigned int pos = get_core_pos_mpidr(affinity); 50 51 DMSG("core %zu, state %u", pos, core_state[pos]); 52 53 if ((pos >= CFG_TEE_CORE_NB_CORE) || 54 (lowest_affinity_level > PSCI_AFFINITY_LEVEL_ON)) { 55 return PSCI_RET_INVALID_PARAMETERS; 56 } 57 58 switch (core_state[pos]) { 59 case CORE_OFF: 60 case CORE_RET: 61 return PSCI_AFFINITY_LEVEL_OFF; 62 case CORE_AWAKE: 63 return PSCI_AFFINITY_LEVEL_ON_PENDING; 64 case CORE_ON: 65 return PSCI_AFFINITY_LEVEL_ON; 66 default: 67 panic(); 68 } 69 } 70 71 #if CFG_TEE_CORE_NB_CORE == 1 72 /* 73 * Function called when a CPU is booted through the OP-TEE. 74 * All cores shall register when online. 75 */ 76 void stm32mp_register_online_cpu(void) 77 { 78 assert(core_state[0] == CORE_OFF); 79 core_state[0] = CORE_ON; 80 } 81 #else 82 static void __noreturn stm32_pm_cpu_power_down_wfi(void) 83 { 84 dcache_op_level1(DCACHE_OP_CLEAN); 85 86 write32(RCC_MP_GRSTCSETR_MPUP1RST, stm32_rcc_base() + RCC_MP_GRSTCSETR); 87 88 dsb(); 89 isb(); 90 wfi(); 91 panic(); 92 } 93 94 void stm32mp_register_online_cpu(void) 95 { 96 size_t pos = get_core_pos(); 97 uint32_t excep = lock_state_access(); 98 99 if (pos == 0) { 100 assert(core_state[pos] == CORE_OFF); 101 } else { 102 if (core_state[pos] != CORE_AWAKE) { 103 core_state[pos] = CORE_OFF; 104 unlock_state_access(excep); 105 stm32_pm_cpu_power_down_wfi(); 106 panic(); 107 } 108 } 109 110 core_state[pos] = CORE_ON; 111 unlock_state_access(excep); 112 } 113 114 #define GICD_SGIR 0xF00 115 static void raise_sgi0_as_secure(void) 116 { 117 dsb_ishst(); 118 write32(GIC_NON_SEC_SGI_0 | SHIFT_U32(TARGET_CPU1_GIC_MASK, 16), 119 get_gicd_base() + GICD_SGIR); 120 } 121 122 static void release_secondary_early_hpen(size_t __unused pos) 123 { 124 /* Need to send SIG#0 over Group0 after individual core 1 reset */ 125 raise_sgi0_as_secure(); 126 udelay(20); 127 128 write32(TEE_LOAD_ADDR, 129 stm32mp_bkpreg(BCKR_CORE1_BRANCH_ADDRESS)); 130 write32(BOOT_API_A7_CORE1_MAGIC_NUMBER, 131 stm32mp_bkpreg(BCKR_CORE1_MAGIC_NUMBER)); 132 133 dsb_ishst(); 134 itr_raise_sgi(GIC_SEC_SGI_0, TARGET_CPU1_GIC_MASK); 135 } 136 137 /* Override default psci_cpu_on() with platform specific sequence */ 138 int psci_cpu_on(uint32_t core_id, uint32_t entry, uint32_t context_id) 139 { 140 size_t pos = get_core_pos_mpidr(core_id); 141 uint32_t excep; 142 int rc; 143 144 if (!pos || pos >= CFG_TEE_CORE_NB_CORE) 145 return PSCI_RET_INVALID_PARAMETERS; 146 147 DMSG("core %zu, ns_entry 0x%" PRIx32 ", state %u", 148 pos, entry, core_state[pos]); 149 150 excep = lock_state_access(); 151 152 switch (core_state[pos]) { 153 case CORE_ON: 154 rc = PSCI_RET_ALREADY_ON; 155 break; 156 case CORE_AWAKE: 157 rc = PSCI_RET_ON_PENDING; 158 break; 159 case CORE_RET: 160 rc = PSCI_RET_DENIED; 161 break; 162 case CORE_OFF: 163 core_state[pos] = CORE_AWAKE; 164 rc = PSCI_RET_SUCCESS; 165 break; 166 default: 167 panic(); 168 } 169 170 unlock_state_access(excep); 171 172 if (rc == PSCI_RET_SUCCESS) { 173 generic_boot_set_core_ns_entry(pos, entry, context_id); 174 release_secondary_early_hpen(pos); 175 } 176 177 return rc; 178 } 179 180 /* Override default psci_cpu_off() with platform specific sequence */ 181 int psci_cpu_off(void) 182 { 183 unsigned int pos = get_core_pos(); 184 uint32_t excep; 185 186 if (pos == 0) { 187 EMSG("PSCI_CPU_OFF not supported for core #0"); 188 return PSCI_RET_INTERNAL_FAILURE; 189 } 190 191 DMSG("core %u", pos); 192 193 excep = lock_state_access(); 194 195 assert(core_state[pos] == CORE_ON); 196 core_state[pos] = CORE_OFF; 197 198 unlock_state_access(excep); 199 200 thread_mask_exceptions(THREAD_EXCP_ALL); 201 stm32_pm_cpu_power_down_wfi(); 202 panic(); 203 } 204 #endif 205 206 /* Override default psci_cpu_on() with platform supported features */ 207 int psci_features(uint32_t psci_fid) 208 { 209 switch (psci_fid) { 210 case PSCI_PSCI_FEATURES: 211 case PSCI_VERSION: 212 #if CFG_TEE_CORE_NB_CORE > 1 213 case PSCI_CPU_ON: 214 #endif 215 return PSCI_RET_SUCCESS; 216 default: 217 return PSCI_RET_NOT_SUPPORTED; 218 } 219 } 220 221 /* Override default psci_version() to enable PSCI_VERSION_1_0 API */ 222 uint32_t psci_version(void) 223 { 224 return PSCI_VERSION_1_0; 225 } 226