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