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