drv_timer.c 14 KB

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