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