socfpga_psci.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved.
  3. * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
  4. * Copyright (c) 2024, Altera Corporation. All rights reserved.
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include <arch_helpers.h>
  9. #include <common/debug.h>
  10. #ifndef GICV3_SUPPORT_GIC600
  11. #include <drivers/arm/gicv2.h>
  12. #else
  13. #include <drivers/arm/gicv3.h>
  14. #endif
  15. #include <lib/mmio.h>
  16. #include <lib/psci/psci.h>
  17. #include <plat/common/platform.h>
  18. #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
  19. #include "agilex5_cache.h"
  20. #endif
  21. #include "ccu/ncore_ccu.h"
  22. #include "socfpga_mailbox.h"
  23. #include "socfpga_plat_def.h"
  24. #include "socfpga_private.h"
  25. #include "socfpga_reset_manager.h"
  26. #include "socfpga_sip_svc.h"
  27. #include "socfpga_system_manager.h"
  28. #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
  29. void socfpga_wakeup_secondary_cpu(unsigned int cpu_id);
  30. extern void plat_secondary_cold_boot_setup(void);
  31. #endif
  32. /*******************************************************************************
  33. * plat handler called when a CPU is about to enter standby.
  34. ******************************************************************************/
  35. void socfpga_cpu_standby(plat_local_state_t cpu_state)
  36. {
  37. /*
  38. * Enter standby state
  39. * dsb is good practice before using wfi to enter low power states
  40. */
  41. VERBOSE("%s: cpu_state: 0x%x\n", __func__, cpu_state);
  42. dsb();
  43. wfi();
  44. }
  45. /*******************************************************************************
  46. * plat handler called when a power domain is about to be turned on. The
  47. * mpidr determines the CPU to be turned on.
  48. ******************************************************************************/
  49. int socfpga_pwr_domain_on(u_register_t mpidr)
  50. {
  51. unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr);
  52. #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
  53. /* TODO: Add in CPU FUSE from SDM */
  54. #else
  55. uint32_t psci_boot = 0x00;
  56. VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
  57. #endif
  58. if (cpu_id == -1)
  59. return PSCI_E_INTERN_FAIL;
  60. #if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
  61. if (cpu_id == 0x00) {
  62. psci_boot = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_8));
  63. psci_boot |= 0x80000; /* bit 19 */
  64. mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_8), psci_boot);
  65. }
  66. mmio_write_64(PLAT_CPUID_RELEASE, cpu_id);
  67. #endif
  68. /* release core reset */
  69. #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
  70. bl31_plat_set_secondary_cpu_entrypoint(cpu_id);
  71. #else
  72. mmio_setbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id);
  73. mmio_write_64(PLAT_CPUID_RELEASE, cpu_id);
  74. #endif
  75. return PSCI_E_SUCCESS;
  76. }
  77. /*******************************************************************************
  78. * plat handler called when a power domain is about to be turned off. The
  79. * target_state encodes the power state that each level should transition to.
  80. ******************************************************************************/
  81. void socfpga_pwr_domain_off(const psci_power_state_t *target_state)
  82. {
  83. for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
  84. VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
  85. __func__, i, target_state->pwr_domain_state[i]);
  86. /* Prevent interrupts from spuriously waking up this cpu */
  87. #ifdef GICV3_SUPPORT_GIC600
  88. gicv3_cpuif_disable(plat_my_core_pos());
  89. #else
  90. gicv2_cpuif_disable();
  91. #endif
  92. }
  93. /*******************************************************************************
  94. * plat handler called when a power domain is about to be suspended. The
  95. * target_state encodes the power state that each level should transition to.
  96. ******************************************************************************/
  97. void socfpga_pwr_domain_suspend(const psci_power_state_t *target_state)
  98. {
  99. #if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
  100. unsigned int cpu_id = plat_my_core_pos();
  101. #endif
  102. for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
  103. VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
  104. __func__, i, target_state->pwr_domain_state[i]);
  105. #if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
  106. /* assert core reset */
  107. mmio_setbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id);
  108. #endif
  109. }
  110. /*******************************************************************************
  111. * plat handler called when a power domain has just been powered on after
  112. * being turned off earlier. The target_state encodes the low power state that
  113. * each level has woken up from.
  114. ******************************************************************************/
  115. void socfpga_pwr_domain_on_finish(const psci_power_state_t *target_state)
  116. {
  117. for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
  118. VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
  119. __func__, i, target_state->pwr_domain_state[i]);
  120. /* Enable the gic cpu interface */
  121. #ifdef GICV3_SUPPORT_GIC600
  122. gicv3_rdistif_init(plat_my_core_pos());
  123. gicv3_cpuif_enable(plat_my_core_pos());
  124. #else
  125. /* Program the gic per-cpu distributor or re-distributor interface */
  126. gicv2_pcpu_distif_init();
  127. gicv2_set_pe_target_mask(plat_my_core_pos());
  128. /* Enable the gic cpu interface */
  129. gicv2_cpuif_enable();
  130. #endif
  131. }
  132. /*******************************************************************************
  133. * plat handler called when a power domain has just been powered on after
  134. * having been suspended earlier. The target_state encodes the low power state
  135. * that each level has woken up from.
  136. * TODO: At the moment we reuse the on finisher and reinitialize the secure
  137. * context. Need to implement a separate suspend finisher.
  138. ******************************************************************************/
  139. void socfpga_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
  140. {
  141. #if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
  142. unsigned int cpu_id = plat_my_core_pos();
  143. #endif
  144. for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
  145. VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
  146. __func__, i, target_state->pwr_domain_state[i]);
  147. #if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
  148. /* release core reset */
  149. mmio_clrbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id);
  150. #endif
  151. }
  152. /*******************************************************************************
  153. * plat handlers to shutdown/reboot the system
  154. ******************************************************************************/
  155. static void __dead2 socfpga_system_off(void)
  156. {
  157. wfi();
  158. ERROR("System Off: operation not handled.\n");
  159. panic();
  160. }
  161. extern uint64_t intel_rsu_update_address;
  162. static void __dead2 socfpga_system_reset(void)
  163. {
  164. uint32_t addr_buf[2];
  165. memcpy_s(addr_buf, sizeof(intel_rsu_update_address),
  166. &intel_rsu_update_address, sizeof(intel_rsu_update_address));
  167. if (intel_rsu_update_address) {
  168. mailbox_rsu_update(addr_buf);
  169. } else {
  170. #if CACHE_FLUSH
  171. /* ATF Flush and Invalidate Cache */
  172. dcsw_op_all(DCCISW);
  173. invalidate_cache_low_el();
  174. #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
  175. flush_l3_dcache();
  176. #endif
  177. #endif
  178. mailbox_reset_cold();
  179. }
  180. while (1)
  181. wfi();
  182. }
  183. static int socfpga_system_reset2(int is_vendor, int reset_type,
  184. u_register_t cookie)
  185. {
  186. #if CACHE_FLUSH
  187. /*
  188. * ATF Flush and Invalidate Cache due to hardware limitation
  189. * of auto Flush and Invalidate Cache.
  190. */
  191. dcsw_op_all(DCCISW);
  192. invalidate_cache_low_el();
  193. #endif
  194. #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
  195. mailbox_reset_warm(reset_type);
  196. #else
  197. if (cold_reset_for_ecc_dbe()) {
  198. mailbox_reset_cold();
  199. }
  200. #endif
  201. /* disable cpuif */
  202. #ifdef GICV3_SUPPORT_GIC600
  203. gicv3_cpuif_disable(plat_my_core_pos());
  204. #else
  205. gicv2_cpuif_disable();
  206. #endif
  207. /* Store magic number */
  208. mmio_write_32(L2_RESET_DONE_REG, L2_RESET_DONE_STATUS);
  209. /* Increase timeout */
  210. mmio_write_32(SOCFPGA_RSTMGR(HDSKTIMEOUT), 0xffffff);
  211. /* Enable handshakes */
  212. mmio_setbits_32(SOCFPGA_RSTMGR(HDSKEN), RSTMGR_HDSKEN_SET);
  213. #if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
  214. /* Reset L2 module */
  215. mmio_setbits_32(SOCFPGA_RSTMGR(COLDMODRST), 0x100);
  216. #endif
  217. while (1)
  218. wfi();
  219. /* Should not reach here */
  220. return 0;
  221. }
  222. int socfpga_validate_power_state(unsigned int power_state,
  223. psci_power_state_t *req_state)
  224. {
  225. VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
  226. return PSCI_E_SUCCESS;
  227. }
  228. int socfpga_validate_ns_entrypoint(unsigned long ns_entrypoint)
  229. {
  230. VERBOSE("%s: ns_entrypoint: 0x%lx\n", __func__, ns_entrypoint);
  231. return PSCI_E_SUCCESS;
  232. }
  233. void socfpga_get_sys_suspend_power_state(psci_power_state_t *req_state)
  234. {
  235. req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE;
  236. req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE;
  237. }
  238. /*******************************************************************************
  239. * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
  240. * platform layer will take care of registering the handlers with PSCI.
  241. ******************************************************************************/
  242. const plat_psci_ops_t socfpga_psci_pm_ops = {
  243. .cpu_standby = socfpga_cpu_standby,
  244. .pwr_domain_on = socfpga_pwr_domain_on,
  245. .pwr_domain_off = socfpga_pwr_domain_off,
  246. .pwr_domain_suspend = socfpga_pwr_domain_suspend,
  247. .pwr_domain_on_finish = socfpga_pwr_domain_on_finish,
  248. .pwr_domain_suspend_finish = socfpga_pwr_domain_suspend_finish,
  249. .system_off = socfpga_system_off,
  250. .system_reset = socfpga_system_reset,
  251. .system_reset2 = socfpga_system_reset2,
  252. .validate_power_state = socfpga_validate_power_state,
  253. .validate_ns_entrypoint = socfpga_validate_ns_entrypoint,
  254. .get_sys_suspend_power_state = socfpga_get_sys_suspend_power_state
  255. };
  256. /*******************************************************************************
  257. * Export the platform specific power ops.
  258. ******************************************************************************/
  259. int plat_setup_psci_ops(uintptr_t sec_entrypoint,
  260. const struct plat_psci_ops **psci_ops)
  261. {
  262. /* Save warm boot entrypoint.*/
  263. mmio_write_64(PLAT_SEC_ENTRY, sec_entrypoint);
  264. *psci_ops = &socfpga_psci_pm_ops;
  265. return 0;
  266. }