arm_pm.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <platform_def.h>
  8. #include <arch_helpers.h>
  9. #include <lib/psci/psci.h>
  10. #include <plat/arm/common/plat_arm.h>
  11. #include <plat/common/platform.h>
  12. /* Allow ARM Standard platforms to override these functions */
  13. #pragma weak plat_arm_program_trusted_mailbox
  14. #if !ARM_RECOM_STATE_ID_ENC
  15. /*******************************************************************************
  16. * ARM standard platform handler called to check the validity of the power state
  17. * parameter.
  18. ******************************************************************************/
  19. int arm_validate_power_state(unsigned int power_state,
  20. psci_power_state_t *req_state)
  21. {
  22. unsigned int pstate = psci_get_pstate_type(power_state);
  23. unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
  24. unsigned int i;
  25. assert(req_state != NULL);
  26. if (pwr_lvl > PLAT_MAX_PWR_LVL)
  27. return PSCI_E_INVALID_PARAMS;
  28. /* Sanity check the requested state */
  29. if (pstate == PSTATE_TYPE_STANDBY) {
  30. /*
  31. * It's possible to enter standby only on power level 0
  32. * Ignore any other power level.
  33. */
  34. if (pwr_lvl != ARM_PWR_LVL0)
  35. return PSCI_E_INVALID_PARAMS;
  36. req_state->pwr_domain_state[ARM_PWR_LVL0] =
  37. ARM_LOCAL_STATE_RET;
  38. } else {
  39. for (i = ARM_PWR_LVL0; i <= pwr_lvl; i++)
  40. req_state->pwr_domain_state[i] =
  41. ARM_LOCAL_STATE_OFF;
  42. }
  43. /*
  44. * We expect the 'state id' to be zero.
  45. */
  46. if (psci_get_pstate_id(power_state) != 0U)
  47. return PSCI_E_INVALID_PARAMS;
  48. return PSCI_E_SUCCESS;
  49. }
  50. #else
  51. /*******************************************************************************
  52. * ARM standard platform handler called to check the validity of the power
  53. * state parameter. The power state parameter has to be a composite power
  54. * state.
  55. ******************************************************************************/
  56. int arm_validate_power_state(unsigned int power_state,
  57. psci_power_state_t *req_state)
  58. {
  59. unsigned int state_id;
  60. int i;
  61. assert(req_state != NULL);
  62. /*
  63. * Currently we are using a linear search for finding the matching
  64. * entry in the idle power state array. This can be made a binary
  65. * search if the number of entries justify the additional complexity.
  66. */
  67. for (i = 0; !!arm_pm_idle_states[i]; i++) {
  68. if ((power_state & ~ARM_LAST_AT_PLVL_MASK) ==
  69. arm_pm_idle_states[i])
  70. break;
  71. }
  72. /* Return error if entry not found in the idle state array */
  73. if (!arm_pm_idle_states[i])
  74. return PSCI_E_INVALID_PARAMS;
  75. i = 0;
  76. state_id = psci_get_pstate_id(power_state);
  77. /* Parse the State ID and populate the state info parameter */
  78. for (i = ARM_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) {
  79. req_state->pwr_domain_state[i] = state_id &
  80. ARM_LOCAL_PSTATE_MASK;
  81. state_id >>= ARM_LOCAL_PSTATE_WIDTH;
  82. }
  83. #if PSCI_OS_INIT_MODE
  84. req_state->last_at_pwrlvl = state_id & ARM_LOCAL_PSTATE_MASK;
  85. #endif /* __PSCI_OS_INIT_MODE__ */
  86. return PSCI_E_SUCCESS;
  87. }
  88. #endif /* __ARM_RECOM_STATE_ID_ENC__ */
  89. /*******************************************************************************
  90. * ARM standard platform handler called to check the validity of the non secure
  91. * entrypoint. Returns 0 if the entrypoint is valid, or -1 otherwise.
  92. ******************************************************************************/
  93. int arm_validate_ns_entrypoint(uintptr_t entrypoint)
  94. {
  95. /*
  96. * Check if the non secure entrypoint lies within the non
  97. * secure DRAM.
  98. */
  99. if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint <
  100. (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) {
  101. return 0;
  102. }
  103. #ifdef __aarch64__
  104. if ((entrypoint >= ARM_DRAM2_BASE) && (entrypoint <
  105. (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) {
  106. return 0;
  107. }
  108. #endif
  109. return -1;
  110. }
  111. int arm_validate_psci_entrypoint(uintptr_t entrypoint)
  112. {
  113. return (arm_validate_ns_entrypoint(entrypoint) == 0) ? PSCI_E_SUCCESS :
  114. PSCI_E_INVALID_ADDRESS;
  115. }
  116. /******************************************************************************
  117. * Helper function to save the platform state before a system suspend. Save the
  118. * state of the system components which are not in the Always ON power domain.
  119. *****************************************************************************/
  120. void arm_system_pwr_domain_save(void)
  121. {
  122. /* Assert system power domain is available on the platform */
  123. assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2);
  124. plat_arm_gic_save();
  125. /*
  126. * Unregister console now so that it is not registered for a second
  127. * time during resume.
  128. */
  129. arm_console_runtime_end();
  130. /*
  131. * All the other peripheral which are configured by ARM TF are
  132. * re-initialized on resume from system suspend. Hence we
  133. * don't save their state here.
  134. */
  135. }
  136. /******************************************************************************
  137. * Helper function to resume the platform from system suspend. Reinitialize
  138. * the system components which are not in the Always ON power domain.
  139. * TODO: Unify the platform setup when waking up from cold boot and system
  140. * resume in arm_bl31_platform_setup().
  141. *****************************************************************************/
  142. void arm_system_pwr_domain_resume(void)
  143. {
  144. /* Initialize the console */
  145. arm_console_runtime_init();
  146. /* Assert system power domain is available on the platform */
  147. assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2);
  148. plat_arm_gic_resume();
  149. plat_arm_security_setup();
  150. arm_configure_sys_timer();
  151. }
  152. /*******************************************************************************
  153. * ARM platform function to program the mailbox for a cpu before it is released
  154. * from reset. This function assumes that the Trusted mail box base is within
  155. * the ARM_SHARED_RAM region
  156. ******************************************************************************/
  157. void plat_arm_program_trusted_mailbox(uintptr_t address)
  158. {
  159. uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE;
  160. *mailbox = address;
  161. /*
  162. * Ensure that the PLAT_ARM_TRUSTED_MAILBOX_BASE is within
  163. * ARM_SHARED_RAM region.
  164. */
  165. assert((PLAT_ARM_TRUSTED_MAILBOX_BASE >= ARM_SHARED_RAM_BASE) &&
  166. ((PLAT_ARM_TRUSTED_MAILBOX_BASE + sizeof(*mailbox)) <=
  167. (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE)));
  168. }
  169. /*******************************************************************************
  170. * The ARM Standard platform definition of platform porting API
  171. * `plat_setup_psci_ops`.
  172. ******************************************************************************/
  173. int __init plat_setup_psci_ops(uintptr_t sec_entrypoint,
  174. const plat_psci_ops_t **psci_ops)
  175. {
  176. *psci_ops = plat_arm_psci_override_pm_ops(&plat_arm_psci_pm_ops);
  177. /* Setup mailbox with entry point. */
  178. plat_arm_program_trusted_mailbox(sec_entrypoint);
  179. return 0;
  180. }