drv_timer.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024/08/08 ShichengChu first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include "drv_timer.h"
  13. #define DBG_LEVEL DBG_LOG
  14. #include <rtdbg.h>
  15. #define LOG_TAG "DRV.TIMER"
  16. #include "pinctrl.h"
  17. #include "mmio.h"
  18. #include "drv_ioremap.h"
  19. #define DW_NR_TIMERS 8
  20. #define TIMER_FREQ 25000000
  21. #define DW_TIMER_GET_RELOAD_VAL(_tim_, _frq_) ((_tim_ < 25000U) ? ((_frq_ * _tim_) / 1000U) : (_frq_ * (_tim_ / 1000U)))
  22. #define DW_TIMER0_BASE 0x030A0000UL
  23. #define DW_TIMER0_SIZE 0x14U
  24. #define DW_TIMER1_BASE (DW_TIMER0_BASE+DW_TIMER0_SIZE)
  25. #define DW_TIMER1_SIZE DW_TIMER0_SIZE
  26. #define DW_TIMER2_BASE (DW_TIMER1_BASE+DW_TIMER1_SIZE)
  27. #define DW_TIMER2_SIZE DW_TIMER1_SIZE
  28. #define DW_TIMER3_BASE (DW_TIMER2_BASE+DW_TIMER2_SIZE)
  29. #define DW_TIMER3_SIZE DW_TIMER2_SIZE
  30. #define DW_TIMER4_BASE (DW_TIMER3_BASE+DW_TIMER3_SIZE)
  31. #define DW_TIMER4_SIZE DW_TIMER3_SIZE
  32. #define DW_TIMER5_BASE (DW_TIMER4_BASE+DW_TIMER4_SIZE)
  33. #define DW_TIMER5_SIZE DW_TIMER4_SIZE
  34. #define DW_TIMER6_BASE (DW_TIMER5_BASE+DW_TIMER5_SIZE)
  35. #define DW_TIMER6_SIZE DW_TIMER5_SIZE
  36. #define DW_TIMER7_BASE (DW_TIMER6_BASE+DW_TIMER6_SIZE)
  37. #define DW_TIMER7_SIZE DW_TIMER6_SIZE
  38. #if defined(BSP_USING_CV18XX) || defined(SOC_CV18XX_AARCH64)
  39. #define TIMER_INTR_0 BSP_TIMER_IRQ_BASE + 0
  40. #define TIMER_INTR_1 BSP_TIMER_IRQ_BASE + 1
  41. #define TIMER_INTR_2 BSP_TIMER_IRQ_BASE + 2
  42. #define TIMER_INTR_3 BSP_TIMER_IRQ_BASE + 3
  43. #define TIMER_INTR_4 BSP_TIMER_IRQ_BASE + 4
  44. #define TIMER_INTR_5 BSP_TIMER_IRQ_BASE + 5
  45. #define TIMER_INTR_6 BSP_TIMER_IRQ_BASE + 6
  46. #define TIMER_INTR_7 BSP_TIMER_IRQ_BASE + 7
  47. #elif defined(BSP_USING_C906_LITTLE)
  48. #define TIMER_INTR_4 BSP_TIMER_IRQ_BASE + 0
  49. #define TIMER_INTR_5 BSP_TIMER_IRQ_BASE + 1
  50. #define TIMER_INTR_6 BSP_TIMER_IRQ_BASE + 2
  51. #define TIMER_INTR_7 BSP_TIMER_IRQ_BASE + 3
  52. #else
  53. #error "Unsupported CPU type!"
  54. #endif
  55. /*! Timer1 Control Reg, offset: 0x08 */
  56. #define DW_TIMER_CTL_ENABLE_SEL_Pos (0U)
  57. #define DW_TIMER_CTL_ENABLE_SEL_Msk (0x1U << DW_TIMER_CTL_ENABLE_SEL_Pos)
  58. #define DW_TIMER_CTL_ENABLE_SEL_EN DW_TIMER_CTL_ENABLE_SEL_Msk
  59. #define DW_TIMER_CTL_MODE_SEL_Pos (1U)
  60. #define DW_TIMER_CTL_MODE_SEL_Msk (0x1U << DW_TIMER_CTL_MODE_SEL_Pos)
  61. #define DW_TIMER_CTL_MODE_SEL_EN DW_TIMER_CTL_MODE_SEL_Msk
  62. #define DW_TIMER_CTL_INT_MASK_Pos (2U)
  63. #define DW_TIMER_CTL_INT_MASK_Msk (0x1U << DW_TIMER_CTL_INT_MASK_Pos)
  64. #define DW_TIMER_CTL_INT_MAKS_EN DW_TIMER_CTL_INT_MASK_Msk
  65. #define DW_TIMER_CTL_HARD_TRIG_Pos (4U)
  66. #define DW_TIMER_CTL_HARD_TRIG_Msk (0x1U << DW_TIMER_CTL_HARD_TRIG_Pos)
  67. #define DW_TIMER_CTL_HARD_TRIG_EN DW_TIMER_CTL_HARD_TRIG_Msk
  68. /*! Timer EOI, offset: 0x0c */
  69. #define DW_TIMER_EOI_REG_Pos (0U)
  70. #define DW_TIMER_EOI_REG_Msk (0x1U << DW_TIMER_EOI_REG_Pos)
  71. #define DW_TIMER_EOI_REG_EN DW_TIMER_EOI_REG_Msk
  72. /*! Timer Int Status, offset: 0x10 */
  73. #define DW_TIMER_INT_STATUS_Pos (0U)
  74. #define DW_TIMER_INT_STATUS_Msk (0x1U << DW_TIMER_INT_STATUS_Pos)
  75. #define DW_TIMER_INT_STATUS_EN DW_TIMER_INT_STATUS_Msk
  76. /*! Timers Int Status, offset: 0xa0 */
  77. #define DW_TIMERS_INT_STATUS_Pos (0U)
  78. #define DW_TIMERS_INT_STATUS_Msk (0x2U << DW_TIMERS_INT_STATUS_Pos)
  79. #define DW_TIMERS_INT_STATUS_EN DW_TIMERS_INT_STATUS_Msk
  80. /*! Timers EOI, offset: 0xa4 */
  81. #define DW_TIMERS_EOI_REG_Pos (0U)
  82. #define DW_TIMERS_EOI_REG_Msk (0x2U << DW_TIMERS_EOI_REG_Pos)
  83. #define DW_TIMERS_EOI_REG_EN DW_TIMERS_EOI_REG_Msk
  84. /*! Timers Raw Int Status,offset: 0xa8 */
  85. #define DW_TIMERS_RAW_INT_STA_Pos (0U)
  86. #define DW_TIMERS_RAW_INT_STA_Msk (0x2U << DW_TIMERS_RAW_INT_STA_Pos)
  87. #define DW_TIMERS_RAW_INT_STA_EN DW_TIMERS_RAW_INT_STA_Msk
  88. typedef struct {
  89. volatile uint32_t TLC; /* Offset: 0x000 (R/W) TimerLoadCount */
  90. volatile const uint32_t TCV; /* Offset: 0x004 (R/ ) TimerCurrentValue */
  91. volatile uint32_t TCR; /* Offset: 0x008 (R/W) TimerControlReg */
  92. volatile const uint32_t TEOI; /* Offset: 0x00c (R/ ) TimerEOI */
  93. volatile const uint32_t TIS; /* Offset: 0x010 (R/ ) TimerIntStatus */
  94. } dw_timer_regs_t;
  95. typedef struct {
  96. dw_timer_regs_t timer[DW_NR_TIMERS];
  97. volatile const uint32_t TSIS; /* Offset: 0x0a0 (R/ ) TimersIntStatus */
  98. volatile const uint32_t TSEOI; /* Offset: 0x0a4 (R/ ) TimersEOI */
  99. volatile const uint32_t TSRIS; /* Offset: 0x0a8 (R/ ) TimersRawIntStatus */
  100. } dw_timer_general_regs_t;
  101. typedef struct _timer
  102. {
  103. char *name;
  104. dw_timer_regs_t *base;
  105. rt_uint32_t irqno;
  106. rt_hwtimer_t timer;
  107. }_timer_t;
  108. static void _timer_init(rt_hwtimer_t *timer, rt_uint32_t state);
  109. static rt_err_t _timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode);
  110. static void _timer_stop(rt_hwtimer_t *timer);
  111. static rt_uint32_t _timer_count_get(rt_hwtimer_t *timer);
  112. static rt_err_t _timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args);
  113. static const struct rt_hwtimer_ops _timer_ops = {
  114. .init = _timer_init,
  115. .start = _timer_start,
  116. .stop = _timer_stop,
  117. .count_get = _timer_count_get,
  118. .control = _timer_control
  119. };
  120. static const struct rt_hwtimer_info _timer_info = {
  121. .maxfreq = 25000000UL,
  122. .minfreq = 25000000UL,
  123. .maxcnt = 0xFFFFFFFF,
  124. .cntmode = HWTIMER_MODE_PERIOD
  125. };
  126. static _timer_t _timer_obj[] =
  127. {
  128. #ifdef BSP_USING_TIMER0
  129. {
  130. .name = "timer0",
  131. .base = (dw_timer_regs_t *)DW_TIMER0_BASE,
  132. .irqno = TIMER_INTR_0
  133. },
  134. #endif /* BSP_USING_TIMER0 */
  135. #ifdef BSP_USING_TIMER1
  136. {
  137. .name = "timer1",
  138. .base = (dw_timer_regs_t *)DW_TIMER1_BASE,
  139. .irqno = TIMER_INTR_1
  140. },
  141. #endif /* BSP_USING_TIMER1 */
  142. #ifdef BSP_USING_TIMER2
  143. {
  144. .name = "timer2",
  145. .base = (dw_timer_regs_t *)DW_TIMER2_BASE,
  146. .irqno = TIMER_INTR_2
  147. },
  148. #endif /* BSP_USING_TIMER2 */
  149. #ifdef BSP_USING_TIMER3
  150. {
  151. .name = "timer3",
  152. .base = (dw_timer_regs_t *)DW_TIMER3_BASE,
  153. .irqno = TIMER_INTR_3
  154. },
  155. #endif /* BSP_USING_TIMER3 */
  156. #ifdef BSP_USING_TIMER4
  157. {
  158. .name = "timer4",
  159. .base = (dw_timer_regs_t *)DW_TIMER4_BASE,
  160. .irqno = TIMER_INTR_4
  161. },
  162. #endif /* BSP_USING_TIMER4 */
  163. #ifdef BSP_USING_TIMER5
  164. {
  165. .name = "timer5",
  166. .base = (dw_timer_regs_t *)DW_TIMER5_BASE,
  167. .irqno = TIMER_INTR_5
  168. },
  169. #endif /* BSP_USING_TIMER5 */
  170. #ifdef BSP_USING_TIMER6
  171. {
  172. .name = "timer6",
  173. .base = (dw_timer_regs_t *)DW_TIMER6_BASE,
  174. .irqno = TIMER_INTR_6
  175. },
  176. #endif /* BSP_USING_TIMER6 */
  177. #ifdef BSP_USING_TIMER7
  178. {
  179. .name = "timer7",
  180. .base = (dw_timer_regs_t *)DW_TIMER7_BASE,
  181. .irqno = TIMER_INTR_7
  182. },
  183. #endif /* BSP_USING_TIMER7 */
  184. };
  185. uint32_t hal_timer_read_load(dw_timer_regs_t *timer_base)
  186. {
  187. return (timer_base->TLC);
  188. }
  189. void hal_timer_write_load(dw_timer_regs_t *timer_base, uint32_t value)
  190. {
  191. timer_base->TLC = value;
  192. }
  193. uint32_t hal_timer_get_current(dw_timer_regs_t *timer_base)
  194. {
  195. return (timer_base->TCV);
  196. }
  197. void hal_timer_set_enable(dw_timer_regs_t *timer_base)
  198. {
  199. timer_base->TCR |= (DW_TIMER_CTL_ENABLE_SEL_EN);
  200. }
  201. void hal_timer_set_disable(dw_timer_regs_t *timer_base)
  202. {
  203. timer_base->TCR &= ~(DW_TIMER_CTL_ENABLE_SEL_EN);
  204. }
  205. uint32_t hal_timer_get_enable(dw_timer_regs_t *timer_base)
  206. {
  207. if ((timer_base->TCR) & DW_TIMER_CTL_ENABLE_SEL_EN)
  208. return 1;
  209. return 0;
  210. }
  211. void hal_timer_set_mode_free(dw_timer_regs_t *timer_base)
  212. {
  213. timer_base->TCR &= ~(DW_TIMER_CTL_MODE_SEL_EN);
  214. }
  215. void hal_timer_set_mode_load(dw_timer_regs_t *timer_base)
  216. {
  217. timer_base->TCR |= (DW_TIMER_CTL_MODE_SEL_EN);
  218. }
  219. uint32_t hal_timer_get_model(dw_timer_regs_t *timer_base)
  220. {
  221. if ((timer_base->TCR) & DW_TIMER_CTL_MODE_SEL_EN)
  222. return 1;
  223. return 0;
  224. }
  225. void hal_timer_set_mask(dw_timer_regs_t *timer_base)
  226. {
  227. timer_base->TCR |= (DW_TIMER_CTL_INT_MAKS_EN);
  228. }
  229. void hal_timer_set_unmask(dw_timer_regs_t *timer_base)
  230. {
  231. timer_base->TCR &= ~(DW_TIMER_CTL_INT_MAKS_EN);
  232. }
  233. uint32_t hal_timer_get_mask(dw_timer_regs_t *timer_base)
  234. {
  235. if ((timer_base->TCR) & DW_TIMER_CTL_INT_MAKS_EN)
  236. return 1;
  237. return 0;
  238. }
  239. void hal_timer_set_hardtrigger_en(dw_timer_regs_t *timer_base)
  240. {
  241. timer_base->TCR |= (DW_TIMER_CTL_HARD_TRIG_EN);
  242. }
  243. void hal_timer_set_hardtrigger_dis(dw_timer_regs_t *timer_base)
  244. {
  245. timer_base->TCR &= ~(DW_TIMER_CTL_HARD_TRIG_EN);
  246. }
  247. uint32_t hal_timer_get_hardtrigger(dw_timer_regs_t *timer_base)
  248. {
  249. if ((timer_base->TCR) & DW_TIMER_CTL_HARD_TRIG_EN)
  250. return 1;
  251. return 0;
  252. }
  253. uint32_t hal_timer_clear_irq(dw_timer_regs_t *timer_base)
  254. {
  255. if ((timer_base->TEOI) & DW_TIMER_EOI_REG_EN)
  256. return 1;
  257. return 0;
  258. }
  259. uint32_t hal_timer_get_int_status(dw_timer_regs_t *timer_base)
  260. {
  261. if ((timer_base->TIS) & DW_TIMER_INT_STATUS_EN)
  262. return 1;
  263. return 0;
  264. }
  265. void hal_timer_reset_register(dw_timer_regs_t *timer_base)
  266. {
  267. timer_base->TCR = 0U;
  268. timer_base->TLC = 0U;
  269. }
  270. uint32_t hal_timer_general_active_after_mask(dw_timer_general_regs_t *timer_base)
  271. {
  272. return ((timer_base->TSIS) & DW_TIMERS_INT_STATUS_EN);
  273. }
  274. uint32_t hal_timer_general_clear_irq(dw_timer_general_regs_t *timer_base)
  275. {
  276. return ((timer_base->TSEOI) & DW_TIMERS_EOI_REG_EN);
  277. }
  278. uint32_t hal_timer_general_active_prior_mask(dw_timer_general_regs_t *timer_base)
  279. {
  280. return ((timer_base->TSRIS) & DW_TIMERS_RAW_INT_STA_EN);
  281. }
  282. static void rt_hw_hwtmr_isr(int irqno, void *param)
  283. {
  284. _timer_t *_tmr = param;
  285. dw_timer_regs_t *timer_base = _tmr->base;
  286. if (hal_timer_get_int_status(timer_base))
  287. {
  288. hal_timer_clear_irq(timer_base);
  289. hal_timer_set_disable(timer_base);
  290. rt_device_hwtimer_isr(&_tmr->timer);
  291. if(_tmr->timer.mode == HWTIMER_MODE_PERIOD)
  292. {
  293. hal_timer_set_enable(timer_base);
  294. hal_timer_set_unmask(timer_base);
  295. }
  296. }
  297. }
  298. static void _timer_init(rt_hwtimer_t *timer, rt_uint32_t state)
  299. {
  300. _timer_t *_tmr = rt_container_of(timer, _timer_t, timer);
  301. RT_ASSERT(_tmr!=NULL)
  302. if(state)
  303. {
  304. hal_timer_reset_register(_tmr->base);
  305. }
  306. }
  307. static rt_err_t _timer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
  308. {
  309. _timer_t *_tmr = rt_container_of(timer, _timer_t, timer);
  310. uint32_t tmp_load = cnt;
  311. hal_timer_set_mode_load(_tmr->base);
  312. /*FIXME: no less than 10*/
  313. if (tmp_load < 10)
  314. {
  315. tmp_load = 10;
  316. }
  317. hal_timer_set_disable(_tmr->base);
  318. hal_timer_write_load(_tmr->base, tmp_load);
  319. hal_timer_set_enable(_tmr->base);
  320. hal_timer_set_unmask(_tmr->base);
  321. return RT_EOK;
  322. }
  323. static void _timer_stop(rt_hwtimer_t *timer)
  324. {
  325. _timer_t *_tmr = rt_container_of(timer, _timer_t, timer);
  326. hal_timer_set_mask(_tmr->base);
  327. hal_timer_set_disable(_tmr->base);
  328. }
  329. static rt_uint32_t _timer_count_get(rt_hwtimer_t *timer)
  330. {
  331. _timer_t *_tmr = rt_container_of(timer, _timer_t, timer);
  332. rt_uint32_t cnt = hal_timer_get_current(_tmr->base);
  333. return cnt;
  334. }
  335. static rt_err_t _timer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
  336. {
  337. rt_err_t err = RT_EOK;
  338. _timer_t *_tmr = rt_container_of(timer, _timer_t, timer);
  339. switch (cmd)
  340. {
  341. case HWTIMER_CTRL_FREQ_SET:
  342. err = -RT_ERROR;
  343. break;
  344. case HWTIMER_CTRL_INFO_GET:
  345. *(rt_hwtimer_t*)args = _tmr->timer;
  346. break;
  347. case HWTIMER_CTRL_MODE_SET:
  348. _tmr->timer.mode = *(rt_uint32_t*)args;
  349. break;
  350. case HWTIMER_CTRL_STOP:
  351. _timer_stop(timer);
  352. break;
  353. default:
  354. err = -RT_EINVAL;
  355. break;
  356. }
  357. return err;
  358. }
  359. int rt_hw_timer_init(void)
  360. {
  361. int ret = RT_EOK;
  362. for (uint32_t i = 0; i < sizeof(_timer_obj) / sizeof(_timer_obj[0]); i++)
  363. {
  364. _timer_obj[i].base = (dw_timer_regs_t *)DRV_IOREMAP((void*)_timer_obj[i].base, 0x10000);
  365. _timer_obj[i].timer.info = &_timer_info;
  366. _timer_obj[i].timer.ops = &_timer_ops;
  367. ret = rt_device_hwtimer_register(&_timer_obj[i].timer, _timer_obj[i].name, &_timer_obj[i]);
  368. if (ret != RT_EOK)
  369. {
  370. LOG_E("%s register failed", _timer_obj[i].name);
  371. }
  372. rt_hw_interrupt_install(_timer_obj[i].irqno, rt_hw_hwtmr_isr, &_timer_obj[i], _timer_obj[i].name);
  373. rt_hw_interrupt_umask(_timer_obj[i].irqno);
  374. }
  375. return ret;
  376. }
  377. INIT_DEVICE_EXPORT(rt_hw_timer_init);