fvp_pm.c 15 KB

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