imx8m_psci_common.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * Copyright (c) 2018-2023, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <stdbool.h>
  7. #include <arch.h>
  8. #include <arch_helpers.h>
  9. #include <common/debug.h>
  10. #include <drivers/delay_timer.h>
  11. #include <lib/mmio.h>
  12. #include <lib/psci/psci.h>
  13. #include <dram.h>
  14. #include <gpc.h>
  15. #include <imx8m_psci.h>
  16. #include <plat_imx8.h>
  17. /*
  18. * below callback functions need to be override by i.mx8mq,
  19. * for other i.mx8m soc, if no special requirement,
  20. * reuse below ones.
  21. */
  22. #pragma weak imx_validate_power_state
  23. #pragma weak imx_pwr_domain_off
  24. #pragma weak imx_domain_suspend
  25. #pragma weak imx_domain_suspend_finish
  26. #pragma weak imx_get_sys_suspend_power_state
  27. int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
  28. {
  29. /* The non-secure entrypoint should be in RAM space */
  30. if (ns_entrypoint < PLAT_NS_IMAGE_OFFSET)
  31. return PSCI_E_INVALID_PARAMS;
  32. return PSCI_E_SUCCESS;
  33. }
  34. int imx_pwr_domain_on(u_register_t mpidr)
  35. {
  36. unsigned int core_id;
  37. uint64_t base_addr = BL31_START;
  38. core_id = MPIDR_AFFLVL0_VAL(mpidr);
  39. imx_set_cpu_secure_entry(core_id, base_addr);
  40. imx_set_cpu_pwr_on(core_id);
  41. return PSCI_E_SUCCESS;
  42. }
  43. void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
  44. {
  45. plat_gic_pcpu_init();
  46. plat_gic_cpuif_enable();
  47. }
  48. void imx_pwr_domain_off(const psci_power_state_t *target_state)
  49. {
  50. uint64_t mpidr = read_mpidr_el1();
  51. unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
  52. plat_gic_cpuif_disable();
  53. imx_set_cpu_pwr_off(core_id);
  54. }
  55. int imx_validate_power_state(unsigned int power_state,
  56. psci_power_state_t *req_state)
  57. {
  58. int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
  59. int pwr_type = psci_get_pstate_type(power_state);
  60. int state_id = psci_get_pstate_id(power_state);
  61. if (pwr_lvl > PLAT_MAX_PWR_LVL)
  62. return PSCI_E_INVALID_PARAMS;
  63. if (pwr_type == PSTATE_TYPE_STANDBY) {
  64. CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
  65. CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
  66. }
  67. if (pwr_type == PSTATE_TYPE_POWERDOWN && state_id == 0x33) {
  68. CORE_PWR_STATE(req_state) = PLAT_MAX_OFF_STATE;
  69. CLUSTER_PWR_STATE(req_state) = PLAT_WAIT_RET_STATE;
  70. }
  71. return PSCI_E_SUCCESS;
  72. }
  73. void imx_cpu_standby(plat_local_state_t cpu_state)
  74. {
  75. dsb();
  76. write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
  77. isb();
  78. wfi();
  79. write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
  80. isb();
  81. }
  82. void imx_domain_suspend(const psci_power_state_t *target_state)
  83. {
  84. uint64_t base_addr = BL31_START;
  85. uint64_t mpidr = read_mpidr_el1();
  86. unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
  87. if (is_local_state_off(CORE_PWR_STATE(target_state))) {
  88. plat_gic_cpuif_disable();
  89. imx_set_cpu_secure_entry(core_id, base_addr);
  90. imx_set_cpu_lpm(core_id, true);
  91. } else {
  92. dsb();
  93. write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
  94. isb();
  95. }
  96. if (!is_local_state_run(CLUSTER_PWR_STATE(target_state)))
  97. imx_set_cluster_powerdown(core_id, CLUSTER_PWR_STATE(target_state));
  98. if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
  99. imx_set_sys_lpm(core_id, true);
  100. dram_enter_retention();
  101. imx_anamix_override(true);
  102. }
  103. }
  104. void imx_domain_suspend_finish(const psci_power_state_t *target_state)
  105. {
  106. uint64_t mpidr = read_mpidr_el1();
  107. unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
  108. if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
  109. imx_anamix_override(false);
  110. dram_exit_retention();
  111. imx_set_sys_lpm(core_id, false);
  112. }
  113. if (!is_local_state_run(CLUSTER_PWR_STATE(target_state))) {
  114. imx_clear_rbc_count();
  115. imx_set_cluster_powerdown(core_id, PSCI_LOCAL_STATE_RUN);
  116. }
  117. if (is_local_state_off(CORE_PWR_STATE(target_state))) {
  118. imx_set_cpu_lpm(core_id, false);
  119. plat_gic_cpuif_enable();
  120. } else {
  121. write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
  122. isb();
  123. }
  124. }
  125. void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
  126. {
  127. unsigned int i;
  128. for (i = IMX_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++)
  129. req_state->pwr_domain_state[i] = PLAT_STOP_OFF_STATE;
  130. }
  131. static void __dead2 imx_wdog_restart(bool external_reset)
  132. {
  133. uintptr_t wdog_base = IMX_WDOG_BASE;
  134. unsigned int val;
  135. val = mmio_read_16(wdog_base);
  136. /*
  137. * Common watchdog init flags, for additional details check
  138. * 6.6.4.1 Watchdog Control Register (WDOGx_WCR)
  139. *
  140. * Initial bit selection:
  141. * WDOG_WCR_WDE - Enable the watchdog.
  142. *
  143. * 0x000E mask is used to keep previous values (that could be set
  144. * in SPL) of WDBG and WDE/WDT (both are write-one once-only bits).
  145. */
  146. val = (val & 0x000E) | WDOG_WCR_WDE;
  147. if (external_reset) {
  148. /*
  149. * To assert WDOG_B (external reset) we have
  150. * to set WDA bit 0 (already set in previous step).
  151. * SRS bits are required to be set to 1 (no effect on the
  152. * system).
  153. */
  154. val |= WDOG_WCR_SRS;
  155. } else {
  156. /*
  157. * To assert Software Reset Signal (internal reset) we have
  158. * to set SRS bit to 0 (already set in previous step).
  159. * SRE bit is required to be set to 1 when used in
  160. * conjunction with the Software Reset Signal before
  161. * SRS asserton, otherwise SRS bit will just automatically
  162. * reset to 1.
  163. *
  164. * Also we set WDA to 1 (no effect on system).
  165. */
  166. val |= WDOG_WCR_SRE | WDOG_WCR_WDA;
  167. }
  168. mmio_write_16(wdog_base, val);
  169. mmio_write_16(wdog_base + WDOG_WSR, 0x5555);
  170. mmio_write_16(wdog_base + WDOG_WSR, 0xaaaa);
  171. while (1)
  172. ;
  173. }
  174. void __dead2 imx_system_reset(void)
  175. {
  176. #ifdef IMX_WDOG_B_RESET
  177. imx_wdog_restart(true);
  178. #else
  179. imx_wdog_restart(false);
  180. #endif
  181. }
  182. int imx_system_reset2(int is_vendor, int reset_type, u_register_t cookie)
  183. {
  184. imx_wdog_restart(false);
  185. /*
  186. * imx_wdog_restart cannot return (as it's a __dead function),
  187. * however imx_system_reset2 has to return some value according
  188. * to PSCI v1.1 spec.
  189. */
  190. return 0;
  191. }
  192. void __dead2 imx_system_off(void)
  193. {
  194. uint32_t val;
  195. val = mmio_read_32(IMX_SNVS_BASE + SNVS_LPCR);
  196. val |= SNVS_LPCR_SRTC_ENV | SNVS_LPCR_DP_EN | SNVS_LPCR_TOP;
  197. mmio_write_32(IMX_SNVS_BASE + SNVS_LPCR, val);
  198. while (1)
  199. ;
  200. }
  201. void __dead2 imx_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
  202. {
  203. /*
  204. * before enter WAIT or STOP mode with PLAT(SCU) power down,
  205. * rbc count need to be enabled to make sure PLAT is
  206. * power down successfully even if the the wakeup IRQ is pending
  207. * early before the power down sequence. the RBC counter is
  208. * drived by the 32K OSC, so delay 30us to make sure the counter
  209. * is really running.
  210. */
  211. if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
  212. imx_set_rbc_count();
  213. udelay(30);
  214. }
  215. while (1)
  216. wfi();
  217. }