fpsci.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * Copyright : (C) 2023 Phytium Information Technology, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is OPEN SOURCE software: you can redistribute it and/or modify it
  6. * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
  7. * either version 1.0 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
  10. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. * See the Phytium Public License for more details.
  12. *
  13. *
  14. * FilePath: fpsci.c
  15. * Created Date: 2023-06-21 10:36:53
  16. * Last Modified: 2023-06-30 13:32:06
  17. * Description: This file is for
  18. *
  19. * Modify History:
  20. * Ver Who Date Changes
  21. * ----- ---------- -------- ---------------------------------
  22. * 1.0 huanghe 2023-06-21 first release
  23. */
  24. #include <stdio.h>
  25. #include "fsmcc.h" /* 根据你的平台和编译环境来确定这个路径 */
  26. #include "fpsci.h"
  27. #include "fassert.h"
  28. #include "fcompiler.h"
  29. #include "fdebug.h"
  30. #include "fcpu_info.h"
  31. #define FPSCI_DEBUG_TAG "FPSCI"
  32. #define FPSCI_DEBUG(format, ...) FT_DEBUG_PRINT_D(FPSCI_DEBUG_TAG, format, ##__VA_ARGS__)
  33. #define FPSCI_INFO(format, ...) FT_DEBUG_PRINT_I(FPSCI_DEBUG_TAG, format, ##__VA_ARGS__)
  34. #define FPSCI_WARN(format, ...) FT_DEBUG_PRINT_W(FPSCI_DEBUG_TAG, format, ##__VA_ARGS__)
  35. #define FPSCI_ERROR(format, ...) FT_DEBUG_PRINT_E(FPSCI_DEBUG_TAG, format, ##__VA_ARGS__)
  36. /* 定义PSCI 函数值 */
  37. #define FPSCI_0_2_FN32_BASE 0x84000000
  38. #define FPSCI_0_2_FN64_BASE 0xC4000000
  39. #define FPSCI_VERSION (FPSCI_0_2_FN32_BASE + 0x000)
  40. #define FPSCI_FEATURES (FPSCI_0_2_FN32_BASE + 0x00a)
  41. #define FPSCI_CPU_SUSPEND_AARCH32 (FPSCI_0_2_FN32_BASE + 0x001)
  42. #define FPSCI_CPU_SUSPEND_AARCH64 (FPSCI_0_2_FN64_BASE + 0x001)
  43. #define FPSCI_CPU_OFF (FPSCI_0_2_FN32_BASE + 0x002)
  44. #define FPSCI_CPU_ON_AARCH32 (FPSCI_0_2_FN32_BASE + 0x003)
  45. #define FPSCI_CPU_ON_AARCH64 (FPSCI_0_2_FN64_BASE + 0x003)
  46. #define FPSCI_FAFFINITY_INFO_AARCH32 (FPSCI_0_2_FN32_BASE + 0x004)
  47. #define FPSCI_FAFFINITY_INFO_AARCH64 (FPSCI_0_2_FN64_BASE + 0x004)
  48. #define FPSCI_SYSTEM_OFF (FPSCI_0_2_FN32_BASE + 0x008)
  49. #define FPSCI_SYSTEM_RESET (FPSCI_0_2_FN32_BASE + 0x009)
  50. #define FPSCI_SYSTEM_SUSPEND (FPSCI_0_2_FN32_BASE + 0x00E)
  51. /* 定义每个PSCI函数ID的位标记 */
  52. #define FPSCI_PSCI_VERSION_BIT (1 << 0)
  53. #define FPSCI_PSCI_FEATURES_BIT (1 << 1)
  54. #define FPSCI_CPU_SUSPEND_AARCH32_BIT (1 << 2)
  55. #define FPSCI_CPU_SUSPEND_AARCH64_BIT (1 << 3)
  56. #define FPSCI_CPU_OFF_BIT (1 << 4)
  57. #define FPSCI_CPU_ON_AARCH32_BIT (1 << 5)
  58. #define FPSCI_CPU_ON_AARCH64_BIT (1 << 6)
  59. #define FPSCI_AFFINITY_INFO_AARCH32_BIT (1 << 7)
  60. #define FPSCI_AFFINITY_INFO_AARCH64_BIT (1 << 8)
  61. #define FPSCI_SYSTEM_OFF_BIT (1 << 9)
  62. #define FPSCI_SYSTEM_RESET_BIT (1 << 10)
  63. static int fpsci_ringt_bit_flg = 0;
  64. /* 定义函数指针 */
  65. typedef void (*FPsciInvokeFun)(unsigned long arg0, unsigned long arg1,
  66. unsigned long arg2, unsigned long arg3,
  67. unsigned long arg4, unsigned long arg5,
  68. unsigned long arg6, unsigned long arg7,
  69. struct FSmcccRes *res);
  70. /* 为函数指针初始化为默认的函数 */
  71. FPsciInvokeFun f_psci_invoke = FSmcccSmcCall;
  72. /**
  73. * @name: FPsciVersion
  74. * @msg: Get the version of the PSCI implementation.
  75. * @return {int}: The version information of the PSCI implementation.
  76. * @note: This function returns the version information obtained from the PSCI VERSION function.
  77. */
  78. int FPsciVersion(void) {
  79. struct FSmcccRes res;
  80. FASSERT((*f_psci_invoke));
  81. (*f_psci_invoke)(FPSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
  82. return res.a0;
  83. }
  84. /**
  85. * @name: FPsciFeatures
  86. * @msg: Check whether a PSCI function is supported.
  87. * @param {u32} psci_fid: The function ID of the PSCI function to be checked.
  88. * @return {int}: 1 if the function is supported; 0 otherwise.
  89. * @note: This function returns whether the PSCI function represented by psci_fid is supported or not.
  90. */
  91. int FPsciFeatures(u32 psci_fid) {
  92. struct FSmcccRes res;
  93. FASSERT((*f_psci_invoke));
  94. (*f_psci_invoke)(FPSCI_FEATURES, psci_fid, 0, 0, 0, 0, 0, 0, &res);
  95. return res.a0 == FPSCI_SUCCESS ? 1 : 0;
  96. }
  97. /**
  98. * @name: FPsciCpuSuspend
  99. * @msg: Suspend execution on a particular CPU.
  100. * @param {u32} power_state: The power state to be entered.
  101. * @param {unsigned long} entry_point_address: The address to be executed upon waking up.
  102. * @param {unsigned long} context_id: The context-specific identifier.
  103. * @return {int}: The status code of the operation, as defined by the PSCI specification.
  104. * @note: This function suspends the execution on a particular CPU and returns a status code indicating whether the operation was successful or not.
  105. */
  106. int FPsciCpuSuspend(u32 power_state, unsigned long entry_point_address, unsigned long context_id) {
  107. struct FSmcccRes res;
  108. FASSERT((fpsci_ringt_bit_flg & FPSCI_CPU_SUSPEND_AARCH32_BIT) != 0);
  109. FASSERT((*f_psci_invoke));
  110. (*f_psci_invoke)(FPSCI_CPU_SUSPEND_AARCH32, power_state, entry_point_address, context_id, 0, 0, 0, 0, &res);
  111. return res.a0;
  112. }
  113. /**
  114. * @name: FPsciCpuOn
  115. * @msg: Power on a particular CPU.
  116. * @param {unsigned long} target_cpu: The target CPU to be powered on.
  117. * @param {unsigned long} entry_point_address: The address to be executed upon waking up.
  118. * @param {unsigned long} context_id: The context-specific identifier.
  119. * @return {int}: The status code of the operation, as defined by the PSCI specification.
  120. * @note: This function powers on a particular CPU and returns a status code indicating whether the operation was successful or not.
  121. */
  122. int FPsciCpuOn(unsigned long target_cpu, unsigned long entry_point_address, unsigned long context_id) {
  123. struct FSmcccRes res;
  124. unsigned long cpu_on_id ;
  125. #if defined(FAARCH64_USE)
  126. cpu_on_id = FPSCI_CPU_ON_AARCH64 ;
  127. #else
  128. cpu_on_id = FPSCI_CPU_ON_AARCH32;
  129. #endif
  130. FASSERT((fpsci_ringt_bit_flg & (FPSCI_CPU_ON_AARCH32_BIT|FPSCI_CPU_ON_AARCH64_BIT)) != 0);
  131. FASSERT((*f_psci_invoke));
  132. (*f_psci_invoke)(cpu_on_id, target_cpu, entry_point_address, context_id, 0, 0, 0, 0, &res);
  133. return res.a0;
  134. }
  135. /**
  136. * @name: FPsciCpuOff
  137. * @msg: This is a wrapper for the PSCI CPU Off interface, intended to turn off the current CPU.
  138. * @return: Returns the 'a0' field of the 'FSmcccRes' structure, indicating the result of the call. A return value of 0 (PSCI_SUCCESS) indicates success, any other value indicates an error occurred.
  139. * @note: A core that is powered down by CPU_OFF can only be powered up again in response to a CPU_ON.
  140. */
  141. int FPsciCpuOff(void) {
  142. struct FSmcccRes res;
  143. FASSERT((fpsci_ringt_bit_flg & FPSCI_CPU_OFF_BIT) != 0);
  144. FASSERT((*f_psci_invoke));
  145. (*f_psci_invoke)(FPSCI_CPU_OFF, 0, 0, 0, 0, 0, 0, 0, &res);
  146. return res.a0;
  147. }
  148. /**
  149. * @name: FPsciAffinityInfo
  150. * @msg: Get the power state of a particular affinity level.
  151. * @param {unsigned long} target_affinity: The target affinity level.
  152. * @param {u32} lowest_affinity_level: The lowest affinity level.
  153. * @return {int}: The power state of the specified affinity level, as defined by the PSCI specification.
  154. * @note: This function returns the power state of a particular affinity level.
  155. */
  156. int FPsciAffinityInfo(unsigned long target_affinity, u32 lowest_affinity_level) {
  157. struct FSmcccRes res;
  158. FASSERT((fpsci_ringt_bit_flg & (FPSCI_AFFINITY_INFO_AARCH32_BIT|FPSCI_AFFINITY_INFO_AARCH64_BIT)) != 0);
  159. FASSERT((*f_psci_invoke));
  160. unsigned long cpu_on_id ;
  161. #if defined(FAARCH64_USE)
  162. cpu_on_id = FPSCI_CPU_ON_AARCH64 ;
  163. #else
  164. cpu_on_id = FPSCI_CPU_ON_AARCH32;
  165. #endif
  166. (*f_psci_invoke)(FPSCI_FAFFINITY_INFO_AARCH32, target_affinity, lowest_affinity_level, 0, 0, 0, 0, 0, &res);
  167. return res.a0;
  168. }
  169. /**
  170. * @name: FPsciSystemReset
  171. * @msg: Reset the system.
  172. * @param {u32} reset_type: The type of the system reset (cold/warm).
  173. * @note: This function resets the system. The reset type is specified by the parameter reset_type.
  174. */
  175. void FPsciSystemReset(u32 reset_type) {
  176. struct FSmcccRes res;
  177. FASSERT((fpsci_ringt_bit_flg & FPSCI_SYSTEM_RESET_BIT) != 0);
  178. FASSERT((*f_psci_invoke));
  179. (*f_psci_invoke)(FPSCI_SYSTEM_RESET, reset_type, 0, 0, 0, 0, 0, 0, &res);
  180. }
  181. /**
  182. * @name: FPsciCheckFeatures
  183. * @msg: This function checks for the availability of various PSCI features and sets the corresponding bits in the 'fpsci_ringt_bit_flg' global flag accordingly.
  184. * @return: This function does not return a value.
  185. */
  186. static void FPsciCheckFeatures(void)
  187. {
  188. FPSCI_INFO("Checking PSCI features...\r\n");
  189. fpsci_ringt_bit_flg = 0 ;
  190. if (FPsciFeatures(FPSCI_CPU_SUSPEND_AARCH32))
  191. {
  192. fpsci_ringt_bit_flg |= FPSCI_CPU_SUSPEND_AARCH32_BIT;
  193. FPSCI_INFO("CPU_SUSPEND_AARCH32 supported.\r\n");
  194. }
  195. else
  196. {
  197. FPSCI_ERROR("CPU_SUSPEND_AARCH32 not supported.\r\n");
  198. }
  199. if (FPsciFeatures(FPSCI_CPU_OFF))
  200. {
  201. fpsci_ringt_bit_flg |= FPSCI_CPU_OFF_BIT;
  202. FPSCI_INFO("CPU_OFF supported.\r\n");
  203. }
  204. else
  205. {
  206. FPSCI_ERROR("CPU_OFF not supported.\r\n");
  207. }
  208. #if defined(FAARCH64_USE)
  209. if (FPsciFeatures(FPSCI_CPU_ON_AARCH64))
  210. {
  211. fpsci_ringt_bit_flg |= FPSCI_CPU_ON_AARCH64_BIT;
  212. FPSCI_INFO("CPU_ON_AARCH64 supported.\r\n");
  213. }
  214. else
  215. {
  216. FPSCI_ERROR("CPU_ON_AARCH64 not supported.\r\n");
  217. }
  218. #else
  219. if (FPsciFeatures(FPSCI_CPU_ON_AARCH32))
  220. {
  221. fpsci_ringt_bit_flg |= FPSCI_CPU_ON_AARCH32_BIT;
  222. FPSCI_INFO("CPU_ON_AARCH32 supported.\r\n");
  223. }
  224. else
  225. {
  226. FPSCI_ERROR("CPU_ON_AARCH32 not supported.\r\n");
  227. }
  228. #endif
  229. #if defined(FAARCH64_USE)
  230. if (FPsciFeatures(FPSCI_FAFFINITY_INFO_AARCH64))
  231. {
  232. fpsci_ringt_bit_flg |= FPSCI_AFFINITY_INFO_AARCH64_BIT;
  233. FPSCI_INFO("AFFINITY_INFO_AARCH64 supported.\r\n");
  234. }
  235. else
  236. {
  237. FPSCI_ERROR("AFFINITY_INFO_AARCH64 not supported.\r\n");
  238. }
  239. #else
  240. if (FPsciFeatures(FPSCI_FAFFINITY_INFO_AARCH32))
  241. {
  242. fpsci_ringt_bit_flg |= FPSCI_AFFINITY_INFO_AARCH32_BIT;
  243. FPSCI_INFO("FPSCI_AFFINITY_INFO_AARCH32 supported.\r\n");
  244. }
  245. else
  246. {
  247. FPSCI_ERROR("AFFINITY_INFO_AARCH32 not supported.\r\n");
  248. }
  249. #endif
  250. if (FPsciFeatures(FPSCI_SYSTEM_OFF))
  251. {
  252. fpsci_ringt_bit_flg |= FPSCI_SYSTEM_OFF_BIT;
  253. FPSCI_INFO("SYSTEM_OFF supported.\r\n");
  254. }
  255. else
  256. {
  257. FPSCI_ERROR("SYSTEM_OFF not supported.\r\n");
  258. }
  259. if (FPsciFeatures(FPSCI_SYSTEM_RESET))
  260. {
  261. fpsci_ringt_bit_flg |= FPSCI_SYSTEM_RESET_BIT;
  262. FPSCI_INFO("SYSTEM_RESET supported.\r\n");
  263. }
  264. else
  265. {
  266. FPSCI_ERROR("SYSTEM_RESET not supported.\r\n");
  267. }
  268. }
  269. /**
  270. * @name: FPsci_CpuOn
  271. * @msg: Power up a core
  272. * @in param cpu_id_mask: cpu id mask
  273. * @in param bootaddr: a 32-bit entry point physical address (or IPA).
  274. * @return int
  275. */
  276. int FPsciCpuMaskOn(s32 cpu_id_mask, uintptr bootaddr)
  277. {
  278. FError ret ;
  279. u64 cluster = 0;
  280. ret = GetCpuAffinityByMask(cpu_id_mask, &cluster);
  281. if (ret != ERR_SUCCESS)
  282. {
  283. return FPSCI_INVALID_PARAMS;
  284. }
  285. return FPsciCpuOn(cluster,(unsigned long)bootaddr,0) ;
  286. }
  287. static void FSmccInit(int method) {
  288. if (method == 1) {
  289. f_psci_invoke = FSmcccHvcCall;
  290. }
  291. else
  292. {
  293. f_psci_invoke = FSmcccSmcCall;
  294. }
  295. }
  296. int FPsciInit(void) {
  297. int psci_version = 0;
  298. FSmccInit(0);
  299. psci_version = FPsciVersion() ;
  300. FPSCI_INFO("major is 0x%x,minor is 0x%x \r\n", FPSCI_MAJOR_VERSION(psci_version),FPSCI_MINOR_VERSION(psci_version)) ;
  301. FPsciCheckFeatures();
  302. return 0;
  303. }