drv_timer.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
  2. *
  3. * Redistribution and use in source and binary forms, with or without
  4. * modification, are permitted provided that the following conditions are met:
  5. * 1. Redistributions of source code must retain the above copyright
  6. * notice, this list of conditions and the following disclaimer.
  7. * 2. Redistributions in binary form must reproduce the above copyright
  8. * notice, this list of conditions and the following disclaimer in the
  9. * documentation and/or other materials provided with the distribution.
  10. *
  11. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  12. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  13. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  14. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  15. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  16. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  17. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  18. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  19. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  21. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  22. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. /*
  26. * Copyright (c) 2006-2025, RT-Thread Development Team
  27. *
  28. * SPDX-License-Identifier: Apache-2.0
  29. */
  30. /*
  31. * K230 Hardware Timer Driver
  32. *
  33. * K230 provides 9 timers, 6 general-purpose timers (TIMER0-TIMER5) and
  34. * 3 STC timers.
  35. * This driver only implements the general-purpose timers (TIMER0-TIMER5).
  36. * This driver only supports the ONESHOT mode.
  37. * Support frequency options: 12.5M(min), 25M, 50M, 100M(max)
  38. */
  39. #include <rtthread.h>
  40. #include <rtdevice.h>
  41. #include "riscv_io.h"
  42. #include "board.h"
  43. #include "ioremap.h"
  44. #include <rtdbg.h>
  45. #include <stdbool.h>
  46. #include <stdio.h>
  47. #include <rthw.h>
  48. #include "sysctl_rst.h"
  49. #include "drv_timer.h"
  50. #include <dfs_posix.h>
  51. static void k230_timer_stop(rt_hwtimer_t *timer);
  52. static void k230_timer_init(rt_hwtimer_t *timer, rt_uint32_t state)
  53. {
  54. struct k230_timer *kd_timer = rt_container_of(timer, struct k230_timer, device);
  55. uint8_t id = kd_timer->id;
  56. if (state == 0)
  57. {
  58. k230_timer_stop(timer);
  59. }
  60. else
  61. {
  62. sysctl_clk_set_leaf_parent(kd_timer->clk, kd_timer->clk_src);
  63. if (timer->freq == timer->info->minfreq)
  64. sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 8);
  65. if (timer->freq == timer->info->maxfreq)
  66. sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 1);
  67. if (timer->freq == 50*MHz)
  68. sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 2);
  69. if (timer->freq == 25*MHz)
  70. sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 4);
  71. }
  72. }
  73. static rt_err_t k230_timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
  74. {
  75. struct k230_timer *kd_timer = rt_container_of(timer, struct k230_timer, device);
  76. uint8_t id = kd_timer->id;
  77. k230_timer_regs_t* reg = (k230_timer_regs_t *)kd_timer->base;
  78. reg->channel[id].load_count = cnt;
  79. reg->channel[id].control &= ~(TIMER_CR_INTERRUPT_MASK);
  80. reg->channel[id].control |= (TIMER_CR_USER_MODE | TIMER_CR_ENABLE);
  81. return RT_EOK;
  82. }
  83. static void k230_timer_stop(rt_hwtimer_t *timer)
  84. {
  85. struct k230_timer *kd_timer = rt_container_of(timer, struct k230_timer, device);
  86. uint8_t id = kd_timer->id;
  87. k230_timer_regs_t* reg = (k230_timer_regs_t *)kd_timer->base;
  88. reg->channel[id].control &= ~TIMER_CR_ENABLE;
  89. reg->channel[id].control |= TIMER_CR_INTERRUPT_MASK;
  90. }
  91. static rt_uint32_t k230_timer_get(rt_hwtimer_t *timer)
  92. {
  93. struct k230_timer *kd_timer = rt_container_of(timer, struct k230_timer, device);
  94. uint8_t id = kd_timer->id;
  95. k230_timer_regs_t* reg = (k230_timer_regs_t *)kd_timer->base;
  96. return reg->channel[id].current_value;
  97. }
  98. static rt_err_t k230_timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
  99. {
  100. struct k230_timer *kd_timer = rt_container_of(timer, struct k230_timer, device);
  101. switch (cmd)
  102. {
  103. case HWTIMER_CTRL_FREQ_SET:
  104. timer->freq = *((rt_uint32_t*)arg);
  105. sysctl_clk_set_leaf_parent(kd_timer->clk, kd_timer->clk_src);
  106. if (timer->freq == timer->info->minfreq)
  107. sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 8);
  108. if (timer->freq == timer->info->maxfreq)
  109. sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 1);
  110. if (timer->freq == 50*MHz)
  111. sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 2);
  112. if (timer->freq == 25*MHz)
  113. sysctl_clk_set_leaf_div(kd_timer->clk_src, 1, 4);
  114. break;
  115. case HWTIMER_CTRL_STOP:
  116. k230_timer_stop(timer);
  117. break;
  118. case HWTIMER_CTRL_INFO_GET:
  119. if (arg == RT_NULL)
  120. {
  121. LOG_E("HWTIMER_CTRL_INFO_GET arg is NULL");
  122. return -RT_ERROR;
  123. }
  124. *(struct rt_hwtimer_info *)arg = *(kd_timer->device.info);
  125. break;
  126. case HWTIMER_CTRL_MODE_SET:
  127. if (arg == RT_NULL)
  128. {
  129. LOG_E("HWTIMER_CTRL_MODE_SET arg is NULL");
  130. return -RT_ERROR;
  131. }
  132. timer->mode = *(rt_hwtimer_mode_t *)arg;
  133. if (timer->mode != HWTIMER_MODE_ONESHOT)
  134. {
  135. LOG_E("mode is invalid/unsupported, only ONESHOT is supported");
  136. return -RT_ERROR;
  137. }
  138. break;
  139. default:
  140. LOG_E("HWTIMER_CTRL cmd is invalid");
  141. return -RT_ERROR;
  142. }
  143. return RT_EOK;
  144. }
  145. static int k230_timer_fops_open(struct dfs_file* fd)
  146. {
  147. rt_device_t device = (rt_device_t)fd->vnode->data;
  148. return rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
  149. }
  150. static int k230_timer_fops_close(struct dfs_file* fd)
  151. {
  152. rt_device_t device = (rt_device_t)fd->vnode->data;
  153. return rt_device_close(device);
  154. }
  155. static const struct rt_hwtimer_info k230_timer_info =
  156. {
  157. 100000000, /* the maximum count frequency can be set */
  158. 12500000, /* the minimum count frequency can be set */
  159. 0xFFFFFFFF, /* the maximum counter value */
  160. HWTIMER_CNTMODE_DW, /* Increment or Decreasing count mode */
  161. };
  162. static const struct rt_hwtimer_ops k230_timer_ops =
  163. {
  164. .init = k230_timer_init,
  165. .start = k230_timer_start,
  166. .stop = k230_timer_stop,
  167. .count_get = k230_timer_get,
  168. .control = k230_timer_ctrl,
  169. };
  170. static const struct dfs_file_ops k230_timer_fops = {
  171. k230_timer_fops_open,
  172. k230_timer_fops_close,
  173. };
  174. void k230_hwtimer_isr(int vector, void *param)
  175. {
  176. uint32_t ret;
  177. struct k230_timer *kd_timer = (struct k230_timer *)param;
  178. rt_hwtimer_t *hwtimer = (rt_hwtimer_t *)&(kd_timer->device);
  179. RT_ASSERT(kd_timer != RT_NULL && hwtimer != RT_NULL);
  180. int id = kd_timer->id;
  181. k230_timer_regs_t* reg = (k230_timer_regs_t *)kd_timer->base;
  182. ret = (reg->channel[id].eoi);
  183. rt_device_hwtimer_isr(hwtimer);
  184. }
  185. static struct k230_timer timer_devices[] =
  186. {
  187. #ifdef BSP_USING_TIMER0
  188. {
  189. .device.info = &k230_timer_info,
  190. .device.ops = &k230_timer_ops,
  191. .device.parent.fops = &k230_timer_fops,
  192. .name = "hwtimer0",
  193. .id = 0,
  194. .clk = SYSCTL_CLK_TIMER0,
  195. .clk_src = SYSCTL_CLK_TIMER0_SRC,
  196. .irq_num = IRQN_TIMER_0_INTERRUPT
  197. },
  198. #endif /* BSP_USING_TIMER0 */
  199. #ifdef BSP_USING_TIMER1
  200. {
  201. .device.info = &k230_timer_info,
  202. .device.ops = &k230_timer_ops,
  203. .device.parent.fops = &k230_timer_fops,
  204. .name = "hwtimer1",
  205. .id = 1,
  206. .clk = SYSCTL_CLK_TIMER1,
  207. .clk_src = SYSCTL_CLK_TIMER1_SRC,
  208. .irq_num = IRQN_TIMER_1_INTERRUPT
  209. },
  210. #endif /* BSP_USING_TIMER1 */
  211. #ifdef BSP_USING_TIMER2
  212. {
  213. .device.info = &k230_timer_info,
  214. .device.ops = &k230_timer_ops,
  215. .device.parent.fops = &k230_timer_fops,
  216. .name = "hwtimer2",
  217. .id = 2,
  218. .clk = SYSCTL_CLK_TIMER2,
  219. .clk_src = SYSCTL_CLK_TIMER2_SRC,
  220. .irq_num = IRQN_TIMER_2_INTERRUPT
  221. },
  222. #endif /* BSP_USING_TIMER0 */
  223. #ifdef BSP_USING_TIMER3
  224. {
  225. .device.info = &k230_timer_info,
  226. .device.ops = &k230_timer_ops,
  227. .device.parent.fops = &k230_timer_fops,
  228. .name = "hwtimer3",
  229. .id = 3,
  230. .clk = SYSCTL_CLK_TIMER3,
  231. .clk_src = SYSCTL_CLK_TIMER3_SRC,
  232. .irq_num = IRQN_TIMER_3_INTERRUPT
  233. },
  234. #endif /* BSP_USING_TIMER3 */
  235. #ifdef BSP_USING_TIMER4
  236. {
  237. .device.info = &k230_timer_info,
  238. .device.ops = &k230_timer_ops,
  239. .device.parent.fops = &k230_timer_fops,
  240. .name = "hwtimer4",
  241. .id = 4,
  242. .clk = SYSCTL_CLK_TIMER4,
  243. .clk_src = SYSCTL_CLK_TIMER4_SRC,
  244. .irq_num = IRQN_TIMER_4_INTERRUPT
  245. },
  246. #endif /* BSP_USING_TIMER4 */
  247. #ifdef BSP_USING_TIMER5
  248. {
  249. .device.info = &k230_timer_info,
  250. .device.ops = &k230_timer_ops,
  251. .device.parent.fops = &k230_timer_fops,
  252. .name = "hwtimer5",
  253. .id = 5,
  254. .clk = SYSCTL_CLK_TIMER5,
  255. .clk_src = SYSCTL_CLK_TIMER5_SRC,
  256. .irq_num = IRQN_TIMER_5_INTERRUPT
  257. },
  258. #endif /* BSP_USING_TIMER5 */
  259. #if !defined(BSP_USING_TIMER0) && \
  260. !defined(BSP_USING_TIMER1) && \
  261. !defined(BSP_USING_TIMER2) && \
  262. !defined(BSP_USING_TIMER3) && \
  263. !defined(BSP_USING_TIMER4) && \
  264. !defined(BSP_USING_TIMER5)
  265. #error "No hardware timer device enabled!"
  266. #endif
  267. };
  268. int rt_hw_timer_init(void)
  269. {
  270. rt_uint8_t i, array_size;
  271. array_size = sizeof(timer_devices) / sizeof(struct k230_timer);
  272. if (array_size == 0)
  273. {
  274. LOG_E("No timer device defined!");
  275. return -RT_ERROR;
  276. }
  277. volatile void* base = (void *)rt_ioremap((void *)HW_TIMER_BASE_ADDR, HW_TIMER_IO_SIZE);
  278. for (i = 0; i < array_size; i++)
  279. {
  280. timer_devices[i].base = (rt_ubase_t)base;
  281. if (rt_device_hwtimer_register(&timer_devices[i].device, timer_devices[i].name, RT_NULL) != RT_EOK)
  282. {
  283. LOG_E("%s register failed!", timer_devices[i].name);
  284. return -RT_ERROR;
  285. }
  286. LOG_D("%s register OK!", timer_devices[i].name);
  287. rt_hw_interrupt_install(timer_devices[i].irq_num,
  288. k230_hwtimer_isr,
  289. &timer_devices[i],
  290. timer_devices[i].name);
  291. rt_hw_interrupt_umask(timer_devices[i].irq_num);
  292. }
  293. return RT_EOK;
  294. }
  295. INIT_BOARD_EXPORT(rt_hw_timer_init);