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