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