fvp_pm.c 15 KB

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