ch56x_timer.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-07-15 Emuzit first version
  9. */
  10. #include <rthw.h>
  11. #include <drivers/hwtimer.h>
  12. #include "ch56x_sys.h"
  13. #include "ch56x_timer.h"
  14. #include "isr_sp.h"
  15. #if !defined(BSP_USING_TMR0) && !defined(BSP_USING_TMR1) && !defined(BSP_USING_TMR2)
  16. #error "Please define at least one TMRx"
  17. #endif
  18. struct hwtimer_device
  19. {
  20. struct rt_hwtimer_device parent;
  21. struct rt_hwtimer_info hwtimer_info;
  22. volatile struct timer_registers *reg_base;
  23. rt_hwtimer_mode_t tmode;
  24. irq_number_t irqn;
  25. char *name;
  26. };
  27. #ifdef BSP_USING_TMR0
  28. static struct hwtimer_device hwtimer_device_0 =
  29. {
  30. .hwtimer_info =
  31. {
  32. .maxfreq = 80000000,
  33. .minfreq = 80000000,
  34. .maxcnt = 0x3ffffff,
  35. .cntmode = HWTIMER_CNTMODE_UP,
  36. },
  37. .reg_base = (struct timer_registers *)TMR0_REG_BASE,
  38. .tmode = HWTIMER_MODE_PERIOD,
  39. .irqn = TMR0_IRQn,
  40. .name = "timer0",
  41. };
  42. #endif
  43. #ifdef BSP_USING_TMR1
  44. static struct hwtimer_device hwtimer_device_1 =
  45. {
  46. .hwtimer_info =
  47. {
  48. .maxfreq = 80000000,
  49. .minfreq = 80000000,
  50. .maxcnt = 0x3ffffff,
  51. .cntmode = HWTIMER_CNTMODE_UP,
  52. },
  53. .reg_base = (struct timer_registers *)TMR1_REG_BASE,
  54. .tmode = HWTIMER_MODE_PERIOD,
  55. .irqn = TMR1_IRQn,
  56. .name = "timer1",
  57. };
  58. #endif
  59. #ifdef BSP_USING_TMR2
  60. static struct hwtimer_device hwtimer_device_2 =
  61. {
  62. .hwtimer_info =
  63. {
  64. .maxfreq = 80000000,
  65. .minfreq = 80000000,
  66. .maxcnt = 0x3ffffff,
  67. .cntmode = HWTIMER_CNTMODE_UP,
  68. },
  69. .reg_base = (struct timer_registers *)TMR2_REG_BASE,
  70. .tmode = HWTIMER_MODE_PERIOD,
  71. .irqn = TMR2_IRQn,
  72. .name = "timer2",
  73. };
  74. #endif
  75. static void hwtimer_stop(struct rt_hwtimer_device *timer);
  76. static void hwtimer_init(struct rt_hwtimer_device *timer, uint32_t state)
  77. {
  78. struct hwtimer_device *hwtimer_device = (void *)timer;
  79. RT_ASSERT(hwtimer_device != RT_NULL);
  80. /* no resource processing, `state` ignored */
  81. hwtimer_stop(timer);
  82. if (hwtimer_device->irqn != TMR0_IRQn)
  83. {
  84. hwtimer_device->reg_base->CTRL_DMA.reg = 0;
  85. }
  86. }
  87. static rt_err_t hwtimer_start(struct rt_hwtimer_device *timer, uint32_t cnt, rt_hwtimer_mode_t mode)
  88. {
  89. struct hwtimer_device *hwtimer_device = (void *)timer;
  90. volatile struct timer_registers *txreg;
  91. RT_ASSERT(hwtimer_device != RT_NULL);
  92. /* hwtimer_device->tmode may be different from timer->mode.
  93. * For multi-cycle ONESHOT, tmode is set to PERIOD at hwtimer_start.
  94. */
  95. hwtimer_device->tmode = mode;
  96. sys_clk_off_by_irqn(hwtimer_device->irqn, SYS_SLP_CLK_ON);
  97. txreg = hwtimer_device->reg_base;
  98. txreg->CNT_END = cnt;
  99. txreg->CTRL_MOD.reg = RB_TMR_ALL_CLEAR;
  100. txreg->CTRL_MOD.reg = RB_TMR_COUNT_EN;
  101. txreg->INTER_EN.cyc_end = 1;
  102. rt_hw_interrupt_umask(hwtimer_device->irqn);
  103. return RT_EOK;
  104. }
  105. static void hwtimer_stop(struct rt_hwtimer_device *timer)
  106. {
  107. struct hwtimer_device *hwtimer_device = (void *)timer;
  108. volatile struct timer_registers *txreg;
  109. RT_ASSERT(hwtimer_device != RT_NULL);
  110. rt_hw_interrupt_mask(hwtimer_device->irqn);
  111. /* note: RB_TMR_COUNT_EN cleared */
  112. txreg = hwtimer_device->reg_base;
  113. txreg->CTRL_MOD.reg = RB_TMR_ALL_CLEAR;
  114. txreg->INTER_EN.reg = 0;
  115. sys_clk_off_by_irqn(hwtimer_device->irqn, SYS_SLP_CLK_OFF);
  116. }
  117. static uint32_t hwtimer_count_get(struct rt_hwtimer_device *timer)
  118. {
  119. struct hwtimer_device *hwtimer_device = (void *)timer;
  120. RT_ASSERT(hwtimer_device != RT_NULL);
  121. return hwtimer_device->reg_base->COUNT;
  122. }
  123. static rt_err_t hwtimer_control(
  124. struct rt_hwtimer_device *timer, uint32_t cmd, void *args)
  125. {
  126. struct hwtimer_device *hwtimer_device = (void *)timer;
  127. rt_err_t result = RT_EOK;
  128. RT_ASSERT(hwtimer_device != RT_NULL);
  129. switch (cmd)
  130. {
  131. case HWTIMER_CTRL_FREQ_SET:
  132. /* clocking for ch56x timers are fixed to Fsys */
  133. if (args == RT_NULL || *(uint32_t *)args != timer->info->minfreq)
  134. {
  135. result = -RT_EINVAL;
  136. }
  137. break;
  138. case HWTIMER_CTRL_STOP:
  139. case HWTIMER_CTRL_INFO_GET:
  140. case HWTIMER_CTRL_MODE_SET:
  141. default:
  142. result = -RT_ENOSYS;
  143. }
  144. return result;
  145. }
  146. static const struct rt_hwtimer_ops hwtimer_ops =
  147. {
  148. .init = hwtimer_init,
  149. .start = hwtimer_start,
  150. .stop = hwtimer_stop,
  151. .count_get = hwtimer_count_get,
  152. .control = hwtimer_control,
  153. };
  154. static int rt_hw_hwtimer_init(void)
  155. {
  156. struct hwtimer_device *devices[3];
  157. uint32_t Fsys = sys_hclk_get();
  158. int n = 0;
  159. #ifdef BSP_USING_TMR2
  160. devices[n++] = &hwtimer_device_2;
  161. #endif
  162. #ifdef BSP_USING_TMR1
  163. devices[n++] = &hwtimer_device_1;
  164. #endif
  165. #ifdef BSP_USING_TMR0
  166. devices[n++] = &hwtimer_device_0;
  167. #endif
  168. while (--n >= 0)
  169. {
  170. struct hwtimer_device *hwtimer_device = devices[n];
  171. /* counting frequency is fixed to Fsys */
  172. hwtimer_device->hwtimer_info.maxfreq = Fsys;
  173. hwtimer_device->hwtimer_info.minfreq = Fsys;
  174. hwtimer_device->parent.info = &hwtimer_device->hwtimer_info;
  175. hwtimer_device->parent.ops = &hwtimer_ops;
  176. rt_device_hwtimer_register(
  177. &hwtimer_device->parent, hwtimer_device->name, RT_NULL);
  178. }
  179. return RT_EOK;
  180. }
  181. INIT_DEVICE_EXPORT(rt_hw_hwtimer_init);
  182. static void _hwtimer_isr_common(struct hwtimer_device *hwtimer_device)
  183. {
  184. volatile struct timer_registers *txreg = hwtimer_device->reg_base;
  185. if (txreg->INT_FLAG.cyc_end)
  186. {
  187. if (hwtimer_device->tmode == HWTIMER_MODE_ONESHOT)
  188. {
  189. /* disable timer to emulate oneshot */
  190. txreg->CTRL_MOD.reg = 0;
  191. }
  192. rt_device_hwtimer_isr(&hwtimer_device->parent);
  193. txreg->INT_FLAG.cyc_end = 1;
  194. }
  195. }
  196. #ifdef BSP_USING_TMR0
  197. void tmr0_irq_handler(void) __attribute__((interrupt()));
  198. void tmr0_irq_handler(void)
  199. {
  200. isr_sp_enter();
  201. rt_interrupt_enter();
  202. _hwtimer_isr_common(&hwtimer_device_0);
  203. rt_interrupt_leave();
  204. isr_sp_leave();
  205. }
  206. #endif
  207. #ifdef BSP_USING_TMR1
  208. void tmr1_irq_handler(void) __attribute__((interrupt()));
  209. void tmr1_irq_handler(void)
  210. {
  211. isr_sp_enter();
  212. rt_interrupt_enter();
  213. _hwtimer_isr_common(&hwtimer_device_1);
  214. rt_interrupt_leave();
  215. isr_sp_leave();
  216. }
  217. #endif
  218. #ifdef BSP_USING_TMR2
  219. void tmr2_irq_handler(void) __attribute__((interrupt()));
  220. void tmr2_irq_handler(void)
  221. {
  222. isr_sp_enter();
  223. rt_interrupt_enter();
  224. _hwtimer_isr_common(&hwtimer_device_2);
  225. rt_interrupt_leave();
  226. isr_sp_leave();
  227. }
  228. #endif