1 /* 2 * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <arch_features.h> 10 #include <arch_helpers.h> 11 #include <common/debug.h> 12 #include <drivers/arm/gicv3.h> 13 #include <drivers/arm/fvp/fvp_pwrc.h> 14 #include <lib/extensions/spe.h> 15 #include <lib/mmio.h> 16 #include <lib/psci/psci.h> 17 #include <plat/arm/common/arm_config.h> 18 #include <plat/arm/common/plat_arm.h> 19 #include <platform_def.h> 20 21 #include "fvp_private.h" 22 #include "../drivers/arm/gic/v3/gicv3_private.h" 23 24 25 #if ARM_RECOM_STATE_ID_ENC 26 /* 27 * The table storing the valid idle power states. Ensure that the 28 * array entries are populated in ascending order of state-id to 29 * enable us to use binary search during power state validation. 30 * The table must be terminated by a NULL entry. 31 */ 32 const unsigned int arm_pm_idle_states[] = { 33 /* State-id - 0x01 */ 34 arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_RET, 35 ARM_PWR_LVL0, PSTATE_TYPE_STANDBY), 36 /* State-id - 0x02 */ 37 arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_OFF, 38 ARM_PWR_LVL0, PSTATE_TYPE_POWERDOWN), 39 /* State-id - 0x22 */ 40 arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF, 41 ARM_PWR_LVL1, PSTATE_TYPE_POWERDOWN), 42 /* State-id - 0x222 */ 43 arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF, 44 ARM_LOCAL_STATE_OFF, ARM_PWR_LVL2, PSTATE_TYPE_POWERDOWN), 45 0, 46 }; 47 #endif 48 49 /******************************************************************************* 50 * Function which implements the common FVP specific operations to power down a 51 * cluster in response to a CPU_OFF or CPU_SUSPEND request. 52 ******************************************************************************/ 53 static void fvp_cluster_pwrdwn_common(void) 54 { 55 uint64_t mpidr = read_mpidr_el1(); 56 57 /* 58 * On power down we need to disable statistical profiling extensions 59 * before exiting coherency. 60 */ 61 if (is_feat_spe_supported()) { 62 spe_disable(); 63 } 64 65 /* Disable coherency if this cluster is to be turned off */ 66 fvp_interconnect_disable(); 67 68 #if HW_ASSISTED_COHERENCY 69 uint32_t reg; 70 71 /* 72 * If we have determined this core to be the last man standing and we 73 * intend to power down the cluster proactively, we provide a hint to 74 * the power controller that cluster power is not required when all 75 * cores are powered down. 76 * Note that this is only an advisory to power controller and is supported 77 * by SoCs with DynamIQ Shared Units only. 78 */ 79 reg = read_clusterpwrdn(); 80 81 /* Clear and set bit 0 : Cluster power not required */ 82 reg &= ~DSU_CLUSTER_PWR_MASK; 83 reg |= DSU_CLUSTER_PWR_OFF; 84 write_clusterpwrdn(reg); 85 #endif 86 87 /* Program the power controller to turn the cluster off */ 88 fvp_pwrc_write_pcoffr(mpidr); 89 } 90 91 /* 92 * Empty implementation of these hooks avoid setting the GICR_WAKER.Sleep bit 93 * on ARM GICv3 implementations on FVP. This is required, because FVP does not 94 * support SYSTEM_SUSPEND and it is `faked` in firmware. Hence, for wake up 95 * from `fake` system suspend the GIC must not be powered off. 96 */ 97 void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num) 98 {} 99 100 void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num) 101 {} 102 103 static void fvp_power_domain_on_finish_common(const psci_power_state_t *target_state) 104 { 105 unsigned long mpidr; 106 107 assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == 108 ARM_LOCAL_STATE_OFF); 109 110 /* Get the mpidr for this cpu */ 111 mpidr = read_mpidr_el1(); 112 113 /* Perform the common cluster specific operations */ 114 if (target_state->pwr_domain_state[ARM_PWR_LVL1] == 115 ARM_LOCAL_STATE_OFF) { 116 /* 117 * This CPU might have woken up whilst the cluster was 118 * attempting to power down. In this case the FVP power 119 * controller will have a pending cluster power off request 120 * which needs to be cleared by writing to the PPONR register. 121 * This prevents the power controller from interpreting a 122 * subsequent entry of this cpu into a simple wfi as a power 123 * down request. 124 */ 125 fvp_pwrc_write_pponr(mpidr); 126 127 /* Enable coherency if this cluster was off */ 128 fvp_interconnect_enable(); 129 } 130 /* Perform the common system specific operations */ 131 if (target_state->pwr_domain_state[ARM_PWR_LVL2] == 132 ARM_LOCAL_STATE_OFF) 133 arm_system_pwr_domain_resume(); 134 135 /* 136 * Clear PWKUPR.WEN bit to ensure interrupts do not interfere 137 * with a cpu power down unless the bit is set again 138 */ 139 fvp_pwrc_clr_wen(mpidr); 140 } 141 142 /******************************************************************************* 143 * FVP handler called when a CPU is about to enter standby. 144 ******************************************************************************/ 145 static void fvp_cpu_standby(plat_local_state_t cpu_state) 146 { 147 u_register_t scr = read_scr_el3(); 148 149 assert(cpu_state == ARM_LOCAL_STATE_RET); 150 151 /* 152 * Enable the Non-secure interrupt to wake the CPU. 153 * In GICv3 affinity routing mode, the Non-secure Group 1 interrupts 154 * use Physical FIQ at EL3 whereas in GICv2, Physical IRQ is used. 155 * Enabling both the bits works for both GICv2 mode and GICv3 affinity 156 * routing mode. 157 */ 158 write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); 159 isb(); 160 161 /* 162 * Enter standby state. 163 * dsb is good practice before using wfi to enter low power states. 164 */ 165 dsb(); 166 wfi(); 167 168 /* 169 * Restore SCR_EL3 to the original value, synchronisation of SCR_EL3 170 * is done by eret in el3_exit() to save some execution cycles. 171 */ 172 write_scr_el3(scr); 173 } 174 175 /******************************************************************************* 176 * FVP handler called when a power domain is about to be turned on. The 177 * mpidr determines the CPU to be turned on. 178 ******************************************************************************/ 179 static int fvp_pwr_domain_on(u_register_t mpidr) 180 { 181 int rc = PSCI_E_SUCCESS; 182 unsigned int psysr; 183 184 /* 185 * Ensure that we do not cancel an inflight power off request for the 186 * target cpu. That would leave it in a zombie wfi. Wait for it to power 187 * off and then program the power controller to turn that CPU on. 188 */ 189 do { 190 psysr = fvp_pwrc_read_psysr(mpidr); 191 } while ((psysr & PSYSR_AFF_L0) != 0U); 192 193 fvp_pwrc_write_pponr(mpidr); 194 return rc; 195 } 196 197 /******************************************************************************* 198 * FVP handler called when a power domain is about to be turned off. The 199 * target_state encodes the power state that each level should transition to. 200 ******************************************************************************/ 201 static void fvp_pwr_domain_off(const psci_power_state_t *target_state) 202 { 203 assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == 204 ARM_LOCAL_STATE_OFF); 205 206 /* 207 * If execution reaches this stage then this power domain will be 208 * suspended. Perform at least the cpu specific actions followed 209 * by the cluster specific operations if applicable. 210 */ 211 212 /* Prevent interrupts from spuriously waking up this cpu */ 213 plat_arm_gic_cpuif_disable(); 214 215 /* Turn redistributor off */ 216 plat_arm_gic_redistif_off(); 217 218 /* Program the power controller to power off this cpu. */ 219 fvp_pwrc_write_ppoffr(read_mpidr_el1()); 220 221 if (target_state->pwr_domain_state[ARM_PWR_LVL1] == 222 ARM_LOCAL_STATE_OFF) 223 fvp_cluster_pwrdwn_common(); 224 225 } 226 227 /******************************************************************************* 228 * FVP handler called when a power domain is about to be suspended. The 229 * target_state encodes the power state that each level should transition to. 230 ******************************************************************************/ 231 #if PSCI_OS_INIT_MODE 232 static int fvp_pwr_domain_suspend(const psci_power_state_t *target_state) 233 #else 234 static void fvp_pwr_domain_suspend(const psci_power_state_t *target_state) 235 #endif 236 { 237 unsigned long mpidr; 238 239 /* 240 * FVP has retention only at cpu level. Just return 241 * as nothing is to be done for retention. 242 */ 243 if (target_state->pwr_domain_state[ARM_PWR_LVL0] == 244 ARM_LOCAL_STATE_RET) 245 #if PSCI_OS_INIT_MODE 246 return PSCI_E_SUCCESS; 247 #else 248 return; 249 #endif 250 251 assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == 252 ARM_LOCAL_STATE_OFF); 253 254 /* Get the mpidr for this cpu */ 255 mpidr = read_mpidr_el1(); 256 257 /* Program the power controller to enable wakeup interrupts. */ 258 fvp_pwrc_set_wen(mpidr); 259 260 /* Prevent interrupts from spuriously waking up this cpu */ 261 plat_arm_gic_cpuif_disable(); 262 263 /* 264 * The Redistributor is not powered off as it can potentially prevent 265 * wake up events reaching the CPUIF and/or might lead to losing 266 * register context. 267 */ 268 269 /* Perform the common cluster specific operations */ 270 if (target_state->pwr_domain_state[ARM_PWR_LVL1] == 271 ARM_LOCAL_STATE_OFF) 272 fvp_cluster_pwrdwn_common(); 273 274 /* Perform the common system specific operations */ 275 if (target_state->pwr_domain_state[ARM_PWR_LVL2] == 276 ARM_LOCAL_STATE_OFF) 277 arm_system_pwr_domain_save(); 278 279 /* Program the power controller to power off this cpu. */ 280 fvp_pwrc_write_ppoffr(read_mpidr_el1()); 281 282 #if PSCI_OS_INIT_MODE 283 return PSCI_E_SUCCESS; 284 #else 285 return; 286 #endif 287 } 288 289 /******************************************************************************* 290 * FVP handler called when a power domain has just been powered on after 291 * being turned off earlier. The target_state encodes the low power state that 292 * each level has woken up from. 293 ******************************************************************************/ 294 static void fvp_pwr_domain_on_finish(const psci_power_state_t *target_state) 295 { 296 fvp_power_domain_on_finish_common(target_state); 297 298 } 299 300 /******************************************************************************* 301 * FVP handler called when a power domain has just been powered on and the cpu 302 * and its cluster are fully participating in coherent transaction on the 303 * interconnect. Data cache must be enabled for CPU at this point. 304 ******************************************************************************/ 305 static void fvp_pwr_domain_on_finish_late(const psci_power_state_t *target_state) 306 { 307 /* Program GIC per-cpu distributor or re-distributor interface */ 308 plat_arm_gic_pcpu_init(); 309 310 /* Enable GIC CPU interface */ 311 plat_arm_gic_cpuif_enable(); 312 } 313 314 /******************************************************************************* 315 * FVP handler called when a power domain has just been powered on after 316 * having been suspended earlier. The target_state encodes the low power state 317 * that each level has woken up from. 318 * TODO: At the moment we reuse the on finisher and reinitialize the secure 319 * context. Need to implement a separate suspend finisher. 320 ******************************************************************************/ 321 static void fvp_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 322 { 323 /* 324 * Nothing to be done on waking up from retention from CPU level. 325 */ 326 if (target_state->pwr_domain_state[ARM_PWR_LVL0] == 327 ARM_LOCAL_STATE_RET) 328 return; 329 330 fvp_power_domain_on_finish_common(target_state); 331 332 /* Enable GIC CPU interface */ 333 plat_arm_gic_cpuif_enable(); 334 } 335 336 /******************************************************************************* 337 * FVP handlers to shutdown/reboot the system 338 ******************************************************************************/ 339 static void __dead2 fvp_system_off(void) 340 { 341 /* Write the System Configuration Control Register */ 342 mmio_write_32(V2M_SYSREGS_BASE + V2M_SYS_CFGCTRL, 343 V2M_CFGCTRL_START | 344 V2M_CFGCTRL_RW | 345 V2M_CFGCTRL_FUNC(V2M_FUNC_SHUTDOWN)); 346 wfi(); 347 ERROR("FVP System Off: operation not handled.\n"); 348 panic(); 349 } 350 351 static void __dead2 fvp_system_reset(void) 352 { 353 /* Write the System Configuration Control Register */ 354 mmio_write_32(V2M_SYSREGS_BASE + V2M_SYS_CFGCTRL, 355 V2M_CFGCTRL_START | 356 V2M_CFGCTRL_RW | 357 V2M_CFGCTRL_FUNC(V2M_FUNC_REBOOT)); 358 wfi(); 359 ERROR("FVP System Reset: operation not handled.\n"); 360 panic(); 361 } 362 363 static int fvp_node_hw_state(u_register_t target_cpu, 364 unsigned int power_level) 365 { 366 unsigned int psysr; 367 int ret; 368 369 /* 370 * The format of 'power_level' is implementation-defined, but 0 must 371 * mean a CPU. We also allow 1 to denote the cluster 372 */ 373 if ((power_level != ARM_PWR_LVL0) && (power_level != ARM_PWR_LVL1)) 374 return PSCI_E_INVALID_PARAMS; 375 376 /* 377 * Read the status of the given MPDIR from FVP power controller. The 378 * power controller only gives us on/off status, so map that to expected 379 * return values of the PSCI call 380 */ 381 psysr = fvp_pwrc_read_psysr(target_cpu); 382 if (psysr == PSYSR_INVALID) 383 return PSCI_E_INVALID_PARAMS; 384 385 if (power_level == ARM_PWR_LVL0) { 386 ret = ((psysr & PSYSR_AFF_L0) != 0U) ? HW_ON : HW_OFF; 387 } else { 388 /* power_level == ARM_PWR_LVL1 */ 389 ret = ((psysr & PSYSR_AFF_L1) != 0U) ? HW_ON : HW_OFF; 390 } 391 392 return ret; 393 } 394 395 /* 396 * The FVP doesn't truly support power management at SYSTEM power domain. The 397 * SYSTEM_SUSPEND will be down-graded to the cluster level within the platform 398 * layer. The `fake` SYSTEM_SUSPEND allows us to validate some of the driver 399 * save and restore sequences on FVP. 400 */ 401 #if !ARM_BL31_IN_DRAM 402 static void fvp_get_sys_suspend_power_state(psci_power_state_t *req_state) 403 { 404 unsigned int i; 405 406 for (i = ARM_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) 407 req_state->pwr_domain_state[i] = ARM_LOCAL_STATE_OFF; 408 } 409 #endif 410 411 /******************************************************************************* 412 * Handler to filter PSCI requests. 413 ******************************************************************************/ 414 /* 415 * The system power domain suspend is only supported only via 416 * PSCI SYSTEM_SUSPEND API. PSCI CPU_SUSPEND request to system power domain 417 * will be downgraded to the lower level. 418 */ 419 static int fvp_validate_power_state(unsigned int power_state, 420 psci_power_state_t *req_state) 421 { 422 int rc; 423 rc = arm_validate_power_state(power_state, req_state); 424 425 /* 426 * Ensure that the system power domain level is never suspended 427 * via PSCI CPU SUSPEND API. Currently system suspend is only 428 * supported via PSCI SYSTEM SUSPEND API. 429 */ 430 req_state->pwr_domain_state[ARM_PWR_LVL2] = ARM_LOCAL_STATE_RUN; 431 return rc; 432 } 433 434 /* 435 * Custom `translate_power_state_by_mpidr` handler for FVP. Unlike in the 436 * `fvp_validate_power_state`, we do not downgrade the system power 437 * domain level request in `power_state` as it will be used to query the 438 * PSCI_STAT_COUNT/RESIDENCY at the system power domain level. 439 */ 440 static int fvp_translate_power_state_by_mpidr(u_register_t mpidr, 441 unsigned int power_state, 442 psci_power_state_t *output_state) 443 { 444 return arm_validate_power_state(power_state, output_state); 445 } 446 447 /******************************************************************************* 448 * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard 449 * platform layer will take care of registering the handlers with PSCI. 450 ******************************************************************************/ 451 plat_psci_ops_t plat_arm_psci_pm_ops = { 452 .cpu_standby = fvp_cpu_standby, 453 .pwr_domain_on = fvp_pwr_domain_on, 454 .pwr_domain_off = fvp_pwr_domain_off, 455 .pwr_domain_suspend = fvp_pwr_domain_suspend, 456 .pwr_domain_on_finish = fvp_pwr_domain_on_finish, 457 .pwr_domain_on_finish_late = fvp_pwr_domain_on_finish_late, 458 .pwr_domain_suspend_finish = fvp_pwr_domain_suspend_finish, 459 .system_off = fvp_system_off, 460 .system_reset = fvp_system_reset, 461 .validate_power_state = fvp_validate_power_state, 462 .validate_ns_entrypoint = arm_validate_psci_entrypoint, 463 .translate_power_state_by_mpidr = fvp_translate_power_state_by_mpidr, 464 .get_node_hw_state = fvp_node_hw_state, 465 #if !ARM_BL31_IN_DRAM 466 /* 467 * The TrustZone Controller is set up during the warmboot sequence after 468 * resuming the CPU from a SYSTEM_SUSPEND. If BL31 is located in SRAM 469 * this is not a problem but, if it is in TZC-secured DRAM, it tries to 470 * reconfigure the same memory it is running on, causing an exception. 471 */ 472 .get_sys_suspend_power_state = fvp_get_sys_suspend_power_state, 473 #endif 474 .mem_protect_chk = arm_psci_mem_protect_chk, 475 .read_mem_protect = arm_psci_read_mem_protect, 476 .write_mem_protect = arm_nor_psci_write_mem_protect, 477 }; 478 479 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) 480 { 481 return ops; 482 } 483