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