hwtimer-arm_arch.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-12-20 GuEe-GUI first version
  9. * 2022-08-24 GuEe-GUI Add OFW support
  10. */
  11. #include <rthw.h>
  12. #include <rtthread.h>
  13. #include <rtdevice.h>
  14. /* support registers access and timer registers in libcpu */
  15. #include <cpu.h>
  16. #include <cpuport.h>
  17. typedef void (*timer_ctrl_handle)(rt_bool_t enable);
  18. typedef rt_uint64_t (*timer_value_handle)(rt_uint64_t val);
  19. static volatile rt_uint64_t timer_step;
  20. static int arm_arch_timer_irq = -1;
  21. static timer_ctrl_handle arm_arch_timer_ctrl_handle = RT_NULL;
  22. static timer_value_handle arm_arch_timer_value_handle = RT_NULL;
  23. /* CTL */
  24. static void mon_ptimer_ctrl(rt_bool_t enable)
  25. {
  26. rt_hw_sysreg_write(CNTPS_CTL, !!enable);
  27. }
  28. static void hyp_s_ptimer_ctrl(rt_bool_t enable)
  29. {
  30. #if ARCH_ARMV8_EXTENSIONS > 1
  31. rt_hw_sysreg_write(CNTHPS_CTL, !!enable);
  32. #endif
  33. }
  34. static void hyp_ns_ptimer_ctrl(rt_bool_t enable)
  35. {
  36. rt_hw_sysreg_write(CNTHP_CTL, !!enable);
  37. }
  38. static void hyp_s_vtimer_ctrl(rt_bool_t enable)
  39. {
  40. #if ARCH_ARMV8_EXTENSIONS > 1
  41. rt_hw_sysreg_write(CNTHVS_CTL, !!enable);
  42. #endif
  43. }
  44. static void hyp_ns_vtimer_ctrl(rt_bool_t enable)
  45. {
  46. #if ARCH_ARMV8_EXTENSIONS > 1
  47. rt_hw_sysreg_write(CNTHV_CTL, !!enable);
  48. #endif
  49. }
  50. static void os_ptimer_ctrl(rt_bool_t enable)
  51. {
  52. rt_hw_sysreg_write(CNTP_CTL, !!enable);
  53. }
  54. static void os_vtimer_ctrl(rt_bool_t enable)
  55. {
  56. rt_hw_sysreg_write(CNTV_CTL, !!enable);
  57. }
  58. /* TVAL */
  59. static rt_uint64_t mon_ptimer_value(rt_uint64_t val)
  60. {
  61. if (val)
  62. {
  63. rt_hw_sysreg_write(CNTPS_TVAL, val);
  64. }
  65. else
  66. {
  67. rt_hw_sysreg_read(CNTPS_TVAL, val);
  68. }
  69. return val;
  70. }
  71. static rt_uint64_t hyp_s_ptimer_value(rt_uint64_t val)
  72. {
  73. #if ARCH_ARMV8_EXTENSIONS > 1
  74. if (val)
  75. {
  76. rt_hw_sysreg_write(CNTHPS_TVAL, val);
  77. }
  78. else
  79. {
  80. rt_hw_sysreg_read(CNTHPS_TVAL, val);
  81. }
  82. return val;
  83. #else
  84. return 0;
  85. #endif
  86. }
  87. static rt_uint64_t hyp_ns_ptimer_value(rt_uint64_t val)
  88. {
  89. if (val)
  90. {
  91. rt_hw_sysreg_write(CNTHP_TVAL, val);
  92. }
  93. else
  94. {
  95. rt_hw_sysreg_read(CNTHP_TVAL, val);
  96. }
  97. return val;
  98. }
  99. static rt_uint64_t hyp_s_vtimer_value(rt_uint64_t val)
  100. {
  101. #if ARCH_ARMV8_EXTENSIONS > 1
  102. if (val)
  103. {
  104. rt_hw_sysreg_write(CNTHVS_TVAL, val);
  105. }
  106. else
  107. {
  108. rt_hw_sysreg_read(CNTHVS_TVAL, val);
  109. }
  110. return val;
  111. #else
  112. return 0;
  113. #endif
  114. }
  115. static rt_uint64_t hyp_ns_vtimer_value(rt_uint64_t val)
  116. {
  117. #if ARCH_ARMV8_EXTENSIONS > 1
  118. if (val)
  119. {
  120. rt_hw_sysreg_write(CNTHV_TVAL, val);
  121. }
  122. else
  123. {
  124. rt_hw_sysreg_read(CNTHV_TVAL, val);
  125. }
  126. return val;
  127. #else
  128. return 0;
  129. #endif
  130. }
  131. static rt_uint64_t os_ptimer_value(rt_uint64_t val)
  132. {
  133. if (val)
  134. {
  135. rt_hw_sysreg_write(CNTP_TVAL, val);
  136. }
  137. else
  138. {
  139. rt_hw_sysreg_read(CNTP_TVAL, val);
  140. }
  141. return val;
  142. }
  143. static rt_uint64_t os_vtimer_value(rt_uint64_t val)
  144. {
  145. if (val)
  146. {
  147. rt_hw_sysreg_write(CNTV_TVAL, val);
  148. }
  149. else
  150. {
  151. rt_hw_sysreg_read(CNTV_TVAL, val);
  152. }
  153. return val;
  154. }
  155. static timer_ctrl_handle ctrl_handle[] =
  156. {
  157. mon_ptimer_ctrl,
  158. hyp_s_ptimer_ctrl,
  159. hyp_ns_ptimer_ctrl,
  160. hyp_s_vtimer_ctrl,
  161. hyp_ns_vtimer_ctrl,
  162. os_ptimer_ctrl,
  163. os_vtimer_ctrl,
  164. };
  165. static timer_value_handle value_handle[] =
  166. {
  167. mon_ptimer_value,
  168. hyp_s_ptimer_value,
  169. hyp_ns_ptimer_value,
  170. hyp_s_vtimer_value,
  171. hyp_ns_vtimer_value,
  172. os_ptimer_value,
  173. os_vtimer_value,
  174. };
  175. static rt_err_t arm_arch_timer_local_enable(void)
  176. {
  177. rt_err_t ret = RT_EOK;
  178. if (arm_arch_timer_irq >= 0)
  179. {
  180. arm_arch_timer_ctrl_handle(RT_FALSE);
  181. arm_arch_timer_value_handle(timer_step);
  182. rt_hw_interrupt_umask(arm_arch_timer_irq);
  183. arm_arch_timer_ctrl_handle(RT_TRUE);
  184. }
  185. else
  186. {
  187. ret = -RT_ENOSYS;
  188. }
  189. return ret;
  190. }
  191. rt_used
  192. static rt_err_t arm_arch_timer_local_disable(void)
  193. {
  194. rt_err_t ret = RT_EOK;
  195. if (arm_arch_timer_ctrl_handle)
  196. {
  197. arm_arch_timer_ctrl_handle(RT_FALSE);
  198. rt_hw_interrupt_mask(arm_arch_timer_irq);
  199. }
  200. else
  201. {
  202. ret = -RT_ENOSYS;
  203. }
  204. return ret;
  205. }
  206. rt_used
  207. static rt_err_t arm_arch_timer_set_frequency(rt_uint64_t frq)
  208. {
  209. rt_err_t ret = RT_EOK;
  210. #ifdef ARCH_SUPPORT_TEE
  211. rt_hw_isb();
  212. rt_hw_sysreg_write(CNTFRQ, frq);
  213. rt_hw_dsb();
  214. #else
  215. ret = -RT_ENOSYS;
  216. #endif
  217. return ret;
  218. }
  219. rt_used
  220. static rt_uint64_t arm_arch_timer_get_frequency(void)
  221. {
  222. rt_uint64_t frq;
  223. rt_hw_isb();
  224. rt_hw_sysreg_read(CNTFRQ, frq);
  225. rt_hw_isb();
  226. return frq;
  227. }
  228. rt_used
  229. static rt_err_t arm_arch_timer_set_value(rt_uint64_t val)
  230. {
  231. rt_err_t ret = RT_EOK;
  232. if (arm_arch_timer_value_handle)
  233. {
  234. val = arm_arch_timer_value_handle(val);
  235. }
  236. else
  237. {
  238. ret = -RT_ENOSYS;
  239. }
  240. return ret;
  241. }
  242. rt_used
  243. static rt_uint64_t arm_arch_timer_get_value(void)
  244. {
  245. rt_uint64_t val = 0;
  246. if (arm_arch_timer_value_handle)
  247. {
  248. val = arm_arch_timer_value_handle(0);
  249. }
  250. return val;
  251. }
  252. static void arm_arch_timer_isr(int vector, void *param)
  253. {
  254. arm_arch_timer_set_value(timer_step);
  255. rt_tick_increase();
  256. }
  257. static int arm_arch_timer_post_init(void)
  258. {
  259. arm_arch_timer_local_enable();
  260. return 0;
  261. }
  262. INIT_SECONDARY_CPU_EXPORT(arm_arch_timer_post_init);
  263. static rt_err_t arm_arch_timer_probe(struct rt_platform_device *pdev)
  264. {
  265. int mode_idx, irq_idx;
  266. const char *irq_name[] =
  267. {
  268. "phys", /* Secure Phys IRQ */
  269. "virt", /* Non-secure Phys IRQ */
  270. "hyp-phys", /* Virt IRQ */
  271. "hyp-virt", /* Hyp IRQ */
  272. };
  273. #if defined(ARCH_SUPPORT_TEE)
  274. mode_idx = 0;
  275. irq_idx = 0;
  276. #elif defined(ARCH_SUPPORT_HYP)
  277. mode_idx = 2;
  278. irq_idx = 3;
  279. #else
  280. mode_idx = 5;
  281. irq_idx = 1;
  282. #endif
  283. arm_arch_timer_irq = rt_dm_dev_get_irq_by_name(&pdev->parent, irq_name[irq_idx]);
  284. if (arm_arch_timer_irq < 0)
  285. {
  286. arm_arch_timer_irq = rt_dm_dev_get_irq(&pdev->parent, irq_idx);
  287. }
  288. if (arm_arch_timer_irq < 0)
  289. {
  290. return -RT_EEMPTY;
  291. }
  292. arm_arch_timer_ctrl_handle = ctrl_handle[mode_idx];
  293. arm_arch_timer_value_handle = value_handle[mode_idx];
  294. rt_hw_interrupt_install(arm_arch_timer_irq, arm_arch_timer_isr, RT_NULL, "tick-arm-timer");
  295. timer_step = arm_arch_timer_get_frequency() / RT_TICK_PER_SECOND;
  296. arm_arch_timer_local_enable();
  297. return RT_EOK;
  298. }
  299. static const struct rt_ofw_node_id arm_arch_timer_ofw_ids[] =
  300. {
  301. { .compatible = "arm,armv7-timer", },
  302. { .compatible = "arm,armv8-timer", },
  303. { /* sentinel */ }
  304. };
  305. static struct rt_platform_driver arm_arch_timer_driver =
  306. {
  307. .name = "arm-arch-timer",
  308. .ids = arm_arch_timer_ofw_ids,
  309. .probe = arm_arch_timer_probe,
  310. };
  311. static int arm_arch_timer_drv_register(void)
  312. {
  313. rt_platform_driver_register(&arm_arch_timer_driver);
  314. return 0;
  315. }
  316. INIT_SUBSYS_EXPORT(arm_arch_timer_drv_register);