psci.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-09-09 GuEe-GUI The first version
  9. */
  10. #include <psci.h>
  11. #include <smccc.h>
  12. #include <armv8.h>
  13. typedef uint64_t (*psci_call_handle)(uint32_t fn, uint64_t arg0, uint64_t arg1, uint64_t arg2);
  14. static uint64_t psci_smc_call(uint32_t fn, uint64_t arg0, uint64_t arg1, uint64_t arg2)
  15. {
  16. return arm_smc_call(fn, arg0, arg1, arg2, 0, 0, 0, 0).x0;
  17. }
  18. static uint64_t psci_hvc_call(uint32_t fn, uint64_t arg0, uint64_t arg1, uint64_t arg2)
  19. {
  20. return arm_hvc_call(fn, arg0, arg1, arg2, 0, 0, 0, 0).x0;
  21. }
  22. static psci_call_handle psci_call = psci_smc_call;
  23. static uint64_t shutdown_args[3] = {0, 0, 0};
  24. static uint64_t reboot_args[3] = {0, 0, 0};
  25. void arm_psci_init(uint64_t method, uint64_t *platform_shutdown_args, uint64_t *platform_reboot_args)
  26. {
  27. switch (method)
  28. {
  29. case PSCI_METHOD_SMC:
  30. psci_call = psci_smc_call;
  31. break;
  32. case PSCI_METHOD_HVC:
  33. if (rt_hw_get_current_el() < 2)
  34. {
  35. psci_call = psci_hvc_call;
  36. }
  37. break;
  38. }
  39. if (platform_shutdown_args != RT_NULL)
  40. {
  41. shutdown_args[0] = platform_shutdown_args[0];
  42. shutdown_args[1] = platform_shutdown_args[1];
  43. shutdown_args[2] = platform_shutdown_args[2];
  44. }
  45. if (platform_reboot_args != RT_NULL)
  46. {
  47. reboot_args[0] = platform_reboot_args[0];
  48. reboot_args[1] = platform_reboot_args[1];
  49. reboot_args[2] = platform_reboot_args[2];
  50. }
  51. }
  52. uint32_t arm_psci_get_version()
  53. {
  54. return (uint32_t)psci_call(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
  55. }
  56. uint32_t arm_psci_get_affinity_info(uint64_t target_affinity, uint64_t lowest_affinity_level)
  57. {
  58. return (uint32_t)psci_call(PSCI_0_2_FN_AFFINITY_INFO, target_affinity, lowest_affinity_level, 0);
  59. }
  60. uint32_t arm_psci_get_feature(uint32_t psci_func_id)
  61. {
  62. return (uint32_t)psci_call(PSCI_1_0_FN_PSCI_FEATURES, psci_func_id, 0, 0);
  63. }
  64. uint32_t arm_psci_cpu_off(uint64_t state)
  65. {
  66. return (uint32_t)psci_call(PSCI_0_2_FN_CPU_OFF, state, 0, 0);
  67. }
  68. uint32_t arm_psci_cpu_on(uint64_t mpid, uint64_t entry)
  69. {
  70. /* [40:63] and [24:31] must be zero, other is aff3, aff2, aff1, aff0 */
  71. mpid = mpid & 0xff00ffffff;
  72. return (uint32_t)psci_call(PSCI_0_2_FN_CPU_ON, mpid, entry, 0);
  73. }
  74. uint32_t arm_psci_cpu_suspend(uint32_t power_state, uint64_t entry)
  75. {
  76. return (uint32_t)psci_call(PSCI_0_2_FN_CPU_SUSPEND, power_state, entry, 0);
  77. }
  78. void arm_psci_system_off()
  79. {
  80. psci_call(PSCI_0_2_FN_SYSTEM_OFF, shutdown_args[0], shutdown_args[1], shutdown_args[2]);
  81. }
  82. void arm_psci_system_reboot()
  83. {
  84. psci_call(PSCI_0_2_FN_SYSTEM_RESET, reboot_args[0], reboot_args[1], reboot_args[2]);
  85. }