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