socfpga_psci.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <arch_helpers.h>
  7. #include <common/debug.h>
  8. #include <drivers/arm/gicv2.h>
  9. #include <lib/mmio.h>
  10. #include <lib/psci/psci.h>
  11. #include <plat/common/platform.h>
  12. #include "socfpga_mailbox.h"
  13. #include "socfpga_plat_def.h"
  14. #include "socfpga_reset_manager.h"
  15. #include "socfpga_sip_svc.h"
  16. /*******************************************************************************
  17. * plat handler called when a CPU is about to enter standby.
  18. ******************************************************************************/
  19. void socfpga_cpu_standby(plat_local_state_t cpu_state)
  20. {
  21. /*
  22. * Enter standby state
  23. * dsb is good practice before using wfi to enter low power states
  24. */
  25. VERBOSE("%s: cpu_state: 0x%x\n", __func__, cpu_state);
  26. dsb();
  27. wfi();
  28. }
  29. /*******************************************************************************
  30. * plat handler called when a power domain is about to be turned on. The
  31. * mpidr determines the CPU to be turned on.
  32. ******************************************************************************/
  33. int socfpga_pwr_domain_on(u_register_t mpidr)
  34. {
  35. unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr);
  36. VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
  37. if (cpu_id == -1)
  38. return PSCI_E_INTERN_FAIL;
  39. mmio_write_64(PLAT_CPUID_RELEASE, cpu_id);
  40. /* release core reset */
  41. mmio_setbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id);
  42. return PSCI_E_SUCCESS;
  43. }
  44. /*******************************************************************************
  45. * plat handler called when a power domain is about to be turned off. The
  46. * target_state encodes the power state that each level should transition to.
  47. ******************************************************************************/
  48. void socfpga_pwr_domain_off(const psci_power_state_t *target_state)
  49. {
  50. for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
  51. VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
  52. __func__, i, target_state->pwr_domain_state[i]);
  53. /* Prevent interrupts from spuriously waking up this cpu */
  54. gicv2_cpuif_disable();
  55. }
  56. /*******************************************************************************
  57. * plat handler called when a power domain is about to be suspended. The
  58. * target_state encodes the power state that each level should transition to.
  59. ******************************************************************************/
  60. void socfpga_pwr_domain_suspend(const psci_power_state_t *target_state)
  61. {
  62. unsigned int cpu_id = plat_my_core_pos();
  63. for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
  64. VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
  65. __func__, i, target_state->pwr_domain_state[i]);
  66. /* assert core reset */
  67. mmio_setbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id);
  68. }
  69. /*******************************************************************************
  70. * plat handler called when a power domain has just been powered on after
  71. * being turned off earlier. The target_state encodes the low power state that
  72. * each level has woken up from.
  73. ******************************************************************************/
  74. void socfpga_pwr_domain_on_finish(const psci_power_state_t *target_state)
  75. {
  76. for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
  77. VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
  78. __func__, i, target_state->pwr_domain_state[i]);
  79. /* Program the gic per-cpu distributor or re-distributor interface */
  80. gicv2_pcpu_distif_init();
  81. gicv2_set_pe_target_mask(plat_my_core_pos());
  82. /* Enable the gic cpu interface */
  83. gicv2_cpuif_enable();
  84. }
  85. /*******************************************************************************
  86. * plat handler called when a power domain has just been powered on after
  87. * having been suspended earlier. The target_state encodes the low power state
  88. * that each level has woken up from.
  89. * TODO: At the moment we reuse the on finisher and reinitialize the secure
  90. * context. Need to implement a separate suspend finisher.
  91. ******************************************************************************/
  92. void socfpga_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
  93. {
  94. unsigned int cpu_id = plat_my_core_pos();
  95. for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
  96. VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
  97. __func__, i, target_state->pwr_domain_state[i]);
  98. /* release core reset */
  99. mmio_clrbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id);
  100. }
  101. /*******************************************************************************
  102. * plat handlers to shutdown/reboot the system
  103. ******************************************************************************/
  104. static void __dead2 socfpga_system_off(void)
  105. {
  106. wfi();
  107. ERROR("System Off: operation not handled.\n");
  108. panic();
  109. }
  110. extern uint64_t intel_rsu_update_address;
  111. static void __dead2 socfpga_system_reset(void)
  112. {
  113. uint32_t addr_buf[2];
  114. memcpy(addr_buf, &intel_rsu_update_address,
  115. sizeof(intel_rsu_update_address));
  116. if (intel_rsu_update_address)
  117. mailbox_rsu_update(addr_buf);
  118. else
  119. mailbox_reset_cold();
  120. while (1)
  121. wfi();
  122. }
  123. static int socfpga_system_reset2(int is_vendor, int reset_type,
  124. u_register_t cookie)
  125. {
  126. if (cold_reset_for_ecc_dbe()) {
  127. mailbox_reset_cold();
  128. }
  129. /* disable cpuif */
  130. gicv2_cpuif_disable();
  131. /* Store magic number */
  132. mmio_write_32(L2_RESET_DONE_REG, L2_RESET_DONE_STATUS);
  133. /* Increase timeout */
  134. mmio_write_32(SOCFPGA_RSTMGR(HDSKTIMEOUT), 0xffffff);
  135. /* Enable handshakes */
  136. mmio_setbits_32(SOCFPGA_RSTMGR(HDSKEN), RSTMGR_HDSKEN_SET);
  137. /* Reset L2 module */
  138. mmio_setbits_32(SOCFPGA_RSTMGR(COLDMODRST), 0x100);
  139. while (1)
  140. wfi();
  141. /* Should not reach here */
  142. return 0;
  143. }
  144. int socfpga_validate_power_state(unsigned int power_state,
  145. psci_power_state_t *req_state)
  146. {
  147. VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
  148. return PSCI_E_SUCCESS;
  149. }
  150. int socfpga_validate_ns_entrypoint(unsigned long ns_entrypoint)
  151. {
  152. VERBOSE("%s: ns_entrypoint: 0x%lx\n", __func__, ns_entrypoint);
  153. return PSCI_E_SUCCESS;
  154. }
  155. void socfpga_get_sys_suspend_power_state(psci_power_state_t *req_state)
  156. {
  157. req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE;
  158. req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE;
  159. }
  160. /*******************************************************************************
  161. * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
  162. * platform layer will take care of registering the handlers with PSCI.
  163. ******************************************************************************/
  164. const plat_psci_ops_t socfpga_psci_pm_ops = {
  165. .cpu_standby = socfpga_cpu_standby,
  166. .pwr_domain_on = socfpga_pwr_domain_on,
  167. .pwr_domain_off = socfpga_pwr_domain_off,
  168. .pwr_domain_suspend = socfpga_pwr_domain_suspend,
  169. .pwr_domain_on_finish = socfpga_pwr_domain_on_finish,
  170. .pwr_domain_suspend_finish = socfpga_pwr_domain_suspend_finish,
  171. .system_off = socfpga_system_off,
  172. .system_reset = socfpga_system_reset,
  173. .system_reset2 = socfpga_system_reset2,
  174. .validate_power_state = socfpga_validate_power_state,
  175. .validate_ns_entrypoint = socfpga_validate_ns_entrypoint,
  176. .get_sys_suspend_power_state = socfpga_get_sys_suspend_power_state
  177. };
  178. /*******************************************************************************
  179. * Export the platform specific power ops.
  180. ******************************************************************************/
  181. int plat_setup_psci_ops(uintptr_t sec_entrypoint,
  182. const struct plat_psci_ops **psci_ops)
  183. {
  184. /* Save warm boot entrypoint.*/
  185. mmio_write_64(PLAT_SEC_ENTRY, sec_entrypoint);
  186. *psci_ops = &socfpga_psci_pm_ops;
  187. return 0;
  188. }