plat_psci.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /*
  2. * Copyright 2018-2020 NXP
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. *
  6. */
  7. #include <common/debug.h>
  8. #include <plat_gic.h>
  9. #include <plat_common.h>
  10. #include <plat_psci.h>
  11. #ifdef NXP_WARM_BOOT
  12. #include <plat_warm_rst.h>
  13. #endif
  14. #include <platform_def.h>
  15. #if (SOC_CORE_OFF || SOC_CORE_PWR_DWN)
  16. static void __dead2 _no_return_wfi(void)
  17. {
  18. _bl31_dead_wfi:
  19. wfi();
  20. goto _bl31_dead_wfi;
  21. }
  22. #endif
  23. #if (SOC_CORE_RELEASE || SOC_CORE_PWR_DWN)
  24. /* the entry for core warm boot */
  25. static uintptr_t warmboot_entry = (uintptr_t) NULL;
  26. #endif
  27. #if (SOC_CORE_RELEASE)
  28. static int _pwr_domain_on(u_register_t mpidr)
  29. {
  30. int core_pos = plat_core_pos(mpidr);
  31. int rc = PSCI_E_INVALID_PARAMS;
  32. u_register_t core_mask;
  33. if (core_pos >= 0 && core_pos < PLATFORM_CORE_COUNT) {
  34. _soc_set_start_addr(warmboot_entry);
  35. dsb();
  36. isb();
  37. core_mask = (1 << core_pos);
  38. rc = _psci_cpu_on(core_mask);
  39. }
  40. return (rc);
  41. }
  42. #endif
  43. #if (SOC_CORE_OFF)
  44. static void _pwr_domain_off(const psci_power_state_t *target_state)
  45. {
  46. u_register_t core_mask = plat_my_core_mask();
  47. u_register_t core_state = _getCoreState(core_mask);
  48. /* set core state in internal data */
  49. core_state = CORE_OFF_PENDING;
  50. _setCoreState(core_mask, core_state);
  51. _psci_cpu_prep_off(core_mask);
  52. }
  53. #endif
  54. #if (SOC_CORE_OFF || SOC_CORE_PWR_DWN)
  55. static void __dead2 _pwr_down_wfi(const psci_power_state_t *target_state)
  56. {
  57. u_register_t core_mask = plat_my_core_mask();
  58. u_register_t core_state = _getCoreState(core_mask);
  59. switch (core_state) {
  60. #if (SOC_CORE_OFF)
  61. case CORE_OFF_PENDING:
  62. /* set core state in internal data */
  63. core_state = CORE_OFF;
  64. _setCoreState(core_mask, core_state);
  65. /* turn the core off */
  66. _psci_cpu_off_wfi(core_mask, warmboot_entry);
  67. break;
  68. #endif
  69. #if (SOC_CORE_PWR_DWN)
  70. case CORE_PWR_DOWN:
  71. /* power-down the core */
  72. _psci_cpu_pwrdn_wfi(core_mask, warmboot_entry);
  73. break;
  74. #endif
  75. #if (SOC_SYSTEM_PWR_DWN)
  76. case SYS_OFF_PENDING:
  77. /* set core state in internal data */
  78. core_state = SYS_OFF;
  79. _setCoreState(core_mask, core_state);
  80. /* power-down the system */
  81. _psci_sys_pwrdn_wfi(core_mask, warmboot_entry);
  82. break;
  83. #endif
  84. default:
  85. _no_return_wfi();
  86. break;
  87. }
  88. }
  89. #endif
  90. #if (SOC_CORE_RELEASE || SOC_CORE_RESTART)
  91. static void _pwr_domain_wakeup(const psci_power_state_t *target_state)
  92. {
  93. u_register_t core_mask = plat_my_core_mask();
  94. u_register_t core_state = _getCoreState(core_mask);
  95. switch (core_state) {
  96. case CORE_PENDING: /* this core is coming out of reset */
  97. /* soc per cpu setup */
  98. soc_init_percpu();
  99. /* gic per cpu setup */
  100. plat_gic_pcpu_init();
  101. /* set core state in internal data */
  102. core_state = CORE_RELEASED;
  103. _setCoreState(core_mask, core_state);
  104. break;
  105. #if (SOC_CORE_RESTART)
  106. case CORE_WAKEUP:
  107. /* this core is waking up from OFF */
  108. _psci_wakeup(core_mask);
  109. /* set core state in internal data */
  110. core_state = CORE_RELEASED;
  111. _setCoreState(core_mask, core_state);
  112. break;
  113. #endif
  114. }
  115. }
  116. #endif
  117. #if (SOC_CORE_STANDBY)
  118. static void _pwr_cpu_standby(plat_local_state_t cpu_state)
  119. {
  120. u_register_t core_mask = plat_my_core_mask();
  121. u_register_t core_state;
  122. if (cpu_state == PLAT_MAX_RET_STATE) {
  123. /* set core state to standby */
  124. core_state = CORE_STANDBY;
  125. _setCoreState(core_mask, core_state);
  126. _psci_core_entr_stdby(core_mask);
  127. /* when we are here, the core is waking up
  128. * set core state to released
  129. */
  130. core_state = CORE_RELEASED;
  131. _setCoreState(core_mask, core_state);
  132. }
  133. }
  134. #endif
  135. #if (SOC_CORE_PWR_DWN)
  136. static void _pwr_suspend(const psci_power_state_t *state)
  137. {
  138. u_register_t core_mask = plat_my_core_mask();
  139. u_register_t core_state;
  140. if (state->pwr_domain_state[PLAT_MAX_LVL] == PLAT_MAX_OFF_STATE) {
  141. #if (SOC_SYSTEM_PWR_DWN)
  142. _psci_sys_prep_pwrdn(core_mask);
  143. /* set core state */
  144. core_state = SYS_OFF_PENDING;
  145. _setCoreState(core_mask, core_state);
  146. #endif
  147. } else if (state->pwr_domain_state[PLAT_MAX_LVL]
  148. == PLAT_MAX_RET_STATE) {
  149. #if (SOC_SYSTEM_STANDBY)
  150. _psci_sys_prep_stdby(core_mask);
  151. /* set core state */
  152. core_state = CORE_STANDBY;
  153. _setCoreState(core_mask, core_state);
  154. #endif
  155. }
  156. else if (state->pwr_domain_state[PLAT_CLSTR_LVL] ==
  157. PLAT_MAX_OFF_STATE) {
  158. #if (SOC_CLUSTER_PWR_DWN)
  159. _psci_clstr_prep_pwrdn(core_mask);
  160. /* set core state */
  161. core_state = CORE_PWR_DOWN;
  162. _setCoreState(core_mask, core_state);
  163. #endif
  164. }
  165. else if (state->pwr_domain_state[PLAT_CLSTR_LVL] ==
  166. PLAT_MAX_RET_STATE) {
  167. #if (SOC_CLUSTER_STANDBY)
  168. _psci_clstr_prep_stdby(core_mask);
  169. /* set core state */
  170. core_state = CORE_STANDBY;
  171. _setCoreState(core_mask, core_state);
  172. #endif
  173. }
  174. else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_OFF_STATE) {
  175. #if (SOC_CORE_PWR_DWN)
  176. /* prep the core for power-down */
  177. _psci_core_prep_pwrdn(core_mask);
  178. /* set core state */
  179. core_state = CORE_PWR_DOWN;
  180. _setCoreState(core_mask, core_state);
  181. #endif
  182. }
  183. else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_RET_STATE) {
  184. #if (SOC_CORE_STANDBY)
  185. _psci_core_prep_stdby(core_mask);
  186. /* set core state */
  187. core_state = CORE_STANDBY;
  188. _setCoreState(core_mask, core_state);
  189. #endif
  190. }
  191. }
  192. #endif
  193. #if (SOC_CORE_PWR_DWN)
  194. static void _pwr_suspend_finish(const psci_power_state_t *state)
  195. {
  196. u_register_t core_mask = plat_my_core_mask();
  197. u_register_t core_state;
  198. if (state->pwr_domain_state[PLAT_MAX_LVL] == PLAT_MAX_OFF_STATE) {
  199. #if (SOC_SYSTEM_PWR_DWN)
  200. _psci_sys_exit_pwrdn(core_mask);
  201. /* when we are here, the core is back up
  202. * set core state to released
  203. */
  204. core_state = CORE_RELEASED;
  205. _setCoreState(core_mask, core_state);
  206. #endif
  207. } else if (state->pwr_domain_state[PLAT_MAX_LVL]
  208. == PLAT_MAX_RET_STATE) {
  209. #if (SOC_SYSTEM_STANDBY)
  210. _psci_sys_exit_stdby(core_mask);
  211. /* when we are here, the core is waking up
  212. * set core state to released
  213. */
  214. core_state = CORE_RELEASED;
  215. _setCoreState(core_mask, core_state);
  216. #endif
  217. }
  218. else if (state->pwr_domain_state[PLAT_CLSTR_LVL] ==
  219. PLAT_MAX_OFF_STATE) {
  220. #if (SOC_CLUSTER_PWR_DWN)
  221. _psci_clstr_exit_pwrdn(core_mask);
  222. /* when we are here, the core is waking up
  223. * set core state to released
  224. */
  225. core_state = CORE_RELEASED;
  226. _setCoreState(core_mask, core_state);
  227. #endif
  228. }
  229. else if (state->pwr_domain_state[PLAT_CLSTR_LVL] ==
  230. PLAT_MAX_RET_STATE) {
  231. #if (SOC_CLUSTER_STANDBY)
  232. _psci_clstr_exit_stdby(core_mask);
  233. /* when we are here, the core is waking up
  234. * set core state to released
  235. */
  236. core_state = CORE_RELEASED;
  237. _setCoreState(core_mask, core_state);
  238. #endif
  239. }
  240. else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_OFF_STATE) {
  241. #if (SOC_CORE_PWR_DWN)
  242. _psci_core_exit_pwrdn(core_mask);
  243. /* when we are here, the core is back up
  244. * set core state to released
  245. */
  246. core_state = CORE_RELEASED;
  247. _setCoreState(core_mask, core_state);
  248. #endif
  249. }
  250. else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_RET_STATE) {
  251. #if (SOC_CORE_STANDBY)
  252. _psci_core_exit_stdby(core_mask);
  253. /* when we are here, the core is waking up
  254. * set core state to released
  255. */
  256. core_state = CORE_RELEASED;
  257. _setCoreState(core_mask, core_state);
  258. #endif
  259. }
  260. }
  261. #endif
  262. #if (SOC_CORE_STANDBY || SOC_CORE_PWR_DWN)
  263. #define PWR_STATE_TYPE_MASK 0x00010000
  264. #define PWR_STATE_TYPE_STNDBY 0x0
  265. #define PWR_STATE_TYPE_PWRDWN 0x00010000
  266. #define PWR_STATE_LVL_MASK 0x03000000
  267. #define PWR_STATE_LVL_CORE 0x0
  268. #define PWR_STATE_LVL_CLSTR 0x01000000
  269. #define PWR_STATE_LVL_SYS 0x02000000
  270. #define PWR_STATE_LVL_MAX 0x03000000
  271. /* turns a requested power state into a target power state
  272. * based on SoC capabilities
  273. */
  274. static int _pwr_state_validate(uint32_t pwr_state,
  275. psci_power_state_t *state)
  276. {
  277. int stat = PSCI_E_INVALID_PARAMS;
  278. int pwrdn = (pwr_state & PWR_STATE_TYPE_MASK);
  279. int lvl = (pwr_state & PWR_STATE_LVL_MASK);
  280. switch (lvl) {
  281. case PWR_STATE_LVL_MAX:
  282. if (pwrdn && SOC_SYSTEM_PWR_DWN)
  283. state->pwr_domain_state[PLAT_MAX_LVL] =
  284. PLAT_MAX_OFF_STATE;
  285. else if (SOC_SYSTEM_STANDBY)
  286. state->pwr_domain_state[PLAT_MAX_LVL] =
  287. PLAT_MAX_RET_STATE;
  288. /* fallthrough */
  289. case PWR_STATE_LVL_SYS:
  290. if (pwrdn && SOC_SYSTEM_PWR_DWN)
  291. state->pwr_domain_state[PLAT_SYS_LVL] =
  292. PLAT_MAX_OFF_STATE;
  293. else if (SOC_SYSTEM_STANDBY)
  294. state->pwr_domain_state[PLAT_SYS_LVL] =
  295. PLAT_MAX_RET_STATE;
  296. /* fallthrough */
  297. case PWR_STATE_LVL_CLSTR:
  298. if (pwrdn && SOC_CLUSTER_PWR_DWN)
  299. state->pwr_domain_state[PLAT_CLSTR_LVL] =
  300. PLAT_MAX_OFF_STATE;
  301. else if (SOC_CLUSTER_STANDBY)
  302. state->pwr_domain_state[PLAT_CLSTR_LVL] =
  303. PLAT_MAX_RET_STATE;
  304. /* fallthrough */
  305. case PWR_STATE_LVL_CORE:
  306. stat = PSCI_E_SUCCESS;
  307. if (pwrdn && SOC_CORE_PWR_DWN)
  308. state->pwr_domain_state[PLAT_CORE_LVL] =
  309. PLAT_MAX_OFF_STATE;
  310. else if (SOC_CORE_STANDBY)
  311. state->pwr_domain_state[PLAT_CORE_LVL] =
  312. PLAT_MAX_RET_STATE;
  313. break;
  314. }
  315. return (stat);
  316. }
  317. #endif
  318. #if (SOC_SYSTEM_PWR_DWN)
  319. static void _pwr_state_sys_suspend(psci_power_state_t *req_state)
  320. {
  321. /* if we need to have per-SoC settings, then we need to
  322. * extend this by calling into psci_utils.S and from there
  323. * on down to the SoC.S files
  324. */
  325. req_state->pwr_domain_state[PLAT_MAX_LVL] = PLAT_MAX_OFF_STATE;
  326. req_state->pwr_domain_state[PLAT_SYS_LVL] = PLAT_MAX_OFF_STATE;
  327. req_state->pwr_domain_state[PLAT_CLSTR_LVL] = PLAT_MAX_OFF_STATE;
  328. req_state->pwr_domain_state[PLAT_CORE_LVL] = PLAT_MAX_OFF_STATE;
  329. }
  330. #endif
  331. #if defined(NXP_WARM_BOOT) && (SOC_SYSTEM_RESET2)
  332. static int psci_system_reset2(int is_vendor,
  333. int reset_type,
  334. u_register_t cookie)
  335. {
  336. int ret = 0;
  337. INFO("Executing the sequence of warm reset.\n");
  338. ret = prep_n_execute_warm_reset();
  339. return ret;
  340. }
  341. #endif
  342. static plat_psci_ops_t _psci_pm_ops = {
  343. #if (SOC_SYSTEM_OFF)
  344. .system_off = _psci_system_off,
  345. #endif
  346. #if (SOC_SYSTEM_RESET)
  347. .system_reset = _psci_system_reset,
  348. #endif
  349. #if defined(NXP_WARM_BOOT) && (SOC_SYSTEM_RESET2)
  350. .system_reset2 = psci_system_reset2,
  351. #endif
  352. #if (SOC_CORE_RELEASE || SOC_CORE_RESTART)
  353. /* core released or restarted */
  354. .pwr_domain_on_finish = _pwr_domain_wakeup,
  355. #endif
  356. #if (SOC_CORE_OFF)
  357. /* core shutting down */
  358. .pwr_domain_off = _pwr_domain_off,
  359. #endif
  360. #if (SOC_CORE_OFF || SOC_CORE_PWR_DWN)
  361. .pwr_domain_pwr_down_wfi = _pwr_down_wfi,
  362. #endif
  363. #if (SOC_CORE_STANDBY || SOC_CORE_PWR_DWN)
  364. /* cpu_suspend */
  365. .validate_power_state = _pwr_state_validate,
  366. #if (SOC_CORE_STANDBY)
  367. .cpu_standby = _pwr_cpu_standby,
  368. #endif
  369. #if (SOC_CORE_PWR_DWN)
  370. .pwr_domain_suspend = _pwr_suspend,
  371. .pwr_domain_suspend_finish = _pwr_suspend_finish,
  372. #endif
  373. #endif
  374. #if (SOC_SYSTEM_PWR_DWN)
  375. .get_sys_suspend_power_state = _pwr_state_sys_suspend,
  376. #endif
  377. #if (SOC_CORE_RELEASE)
  378. /* core executing psci_cpu_on */
  379. .pwr_domain_on = _pwr_domain_on
  380. #endif
  381. };
  382. #if (SOC_CORE_RELEASE || SOC_CORE_PWR_DWN)
  383. int plat_setup_psci_ops(uintptr_t sec_entrypoint,
  384. const plat_psci_ops_t **psci_ops)
  385. {
  386. warmboot_entry = sec_entrypoint;
  387. *psci_ops = &_psci_pm_ops;
  388. return 0;
  389. }
  390. #else
  391. int plat_setup_psci_ops(uintptr_t sec_entrypoint,
  392. const plat_psci_ops_t **psci_ops)
  393. {
  394. *psci_ops = &_psci_pm_ops;
  395. return 0;
  396. }
  397. #endif