drv_wdt.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /*
  2. * Copyright (c) 2021 - 2022 HPMicro
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. *
  6. */
  7. #include <rthw.h>
  8. #include <rtdevice.h>
  9. #include <rtdbg.h>
  10. #include "board.h"
  11. #include "drv_wdt.h"
  12. #include "hpm_wdg_drv.h"
  13. #include "hpm_sysctl_drv.h"
  14. #ifdef BSP_USING_WDG
  15. typedef struct hpm_wdog
  16. {
  17. WDG_Type *wdog_base;
  18. char *device_name;
  19. clock_name_t clock_name;
  20. uint32_t irq_num;
  21. rt_watchdog_t *wdog;
  22. wdg_control_t wdog_ctrl;
  23. }hpm_wdog_t;
  24. static rt_err_t hpm_wdog_init(rt_watchdog_t *wdt);
  25. static rt_err_t hpm_wdog_open(rt_watchdog_t *wdt, rt_uint16_t oflag);
  26. static rt_err_t hpm_wdog_close(rt_watchdog_t *wdt);
  27. static rt_err_t hpm_wdog_refresh(rt_watchdog_t *wdt);
  28. static rt_err_t hpm_wdog_control(rt_watchdog_t *wdt, int cmd, void *args);
  29. static void hpm_wdog_isr(rt_watchdog_t *wdt);
  30. #if defined(BSP_USING_WDG0)
  31. rt_watchdog_t wdog0;
  32. SDK_DECLARE_EXT_ISR_M(IRQn_WDG0, wdog0_isr)
  33. void wdog0_isr(void)
  34. {
  35. hpm_wdog_isr(&wdog0);
  36. }
  37. #endif
  38. #if defined(BSP_USING_WDG1)
  39. rt_watchdog_t wdog1;
  40. SDK_DECLARE_EXT_ISR_M(IRQn_WDG1, wdog1_isr)
  41. void wdog1_isr(void)
  42. {
  43. hpm_wdog_isr(&wdog1);
  44. }
  45. #endif
  46. #if defined(BSP_USING_WDG2)
  47. rt_watchdog_t wdog2;
  48. SDK_DECLARE_EXT_ISR_M(IRQn_WDG2, wdog2_isr)
  49. void wdog2_isr(void)
  50. {
  51. hpm_wdog_isr(&wdog2);
  52. }
  53. #endif
  54. #if defined(BSP_USING_WDG3)
  55. rt_watchdog_t wdog3;
  56. SDK_DECLARE_EXT_ISR_M(IRQn_WDG3, wdog3_isr)
  57. void wdog3_isr(void)
  58. {
  59. hpm_wdog_isr(&wdog3);
  60. }
  61. #endif
  62. static hpm_wdog_t wdogs[] = {
  63. #ifdef BSP_USING_WDG0
  64. {
  65. .wdog_base = HPM_WDG0,
  66. .device_name = "wdt0",
  67. .clock_name = clock_watchdog0,
  68. .irq_num = IRQn_WDG0,
  69. .wdog = &wdog0,
  70. .wdog_ctrl = {
  71. .reset_interval = reset_interval_clock_period_mult_16k,
  72. .interrupt_interval = interrupt_interval_clock_period_multi_8k,
  73. .reset_enable = true,
  74. .interrupt_enable = false,
  75. .clksrc = wdg_clksrc_extclk,
  76. .wdg_enable = false,
  77. },
  78. },
  79. #endif
  80. #ifdef BSP_USING_WDG1
  81. {
  82. .wdog_base = HPM_WDG1,
  83. .device_name = "wdt1",
  84. .clock_name = clock_watchdog1,
  85. .irq_num = IRQn_WDG1,
  86. .wdog = &wdog1,
  87. .wdog_ctrl = {
  88. .reset_interval = reset_interval_clock_period_mult_16k,
  89. .interrupt_interval = interrupt_interval_clock_period_multi_8k,
  90. .reset_enable = true,
  91. .interrupt_enable = false,
  92. .clksrc = wdg_clksrc_extclk,
  93. .wdg_enable = false,
  94. },
  95. },
  96. #endif
  97. #ifdef BSP_USING_WDG2
  98. {
  99. .wdog_base = HPM_WDG2,
  100. .device_name = "wdt2",
  101. .clock_name = clock_watchdog2,
  102. .irq_num = IRQn_WDG2,
  103. .wdog = &wdog2,
  104. .wdog_ctrl = {
  105. .reset_interval = reset_interval_clock_period_mult_16k,
  106. .interrupt_interval = interrupt_interval_clock_period_multi_8k,
  107. .reset_enable = true,
  108. .interrupt_enable = false,
  109. .clksrc = wdg_clksrc_extclk,
  110. .wdg_enable = false,
  111. },
  112. },
  113. #endif
  114. #ifdef BSP_USING_WDG3
  115. {
  116. .wdog_base = HPM_WDG3,
  117. .device_name = "wdt3",
  118. .clock_name = clock_watchdog3,
  119. .irq_num = IRQn_WDG3,
  120. .wdog = &wdog3,
  121. .wdog_ctrl = {
  122. .reset_interval = reset_interval_clock_period_mult_16k,
  123. .interrupt_interval = interrupt_interval_clock_period_multi_8k,
  124. .reset_enable = true,
  125. .interrupt_enable = false,
  126. .clksrc = wdg_clksrc_extclk,
  127. .wdg_enable = false,
  128. },
  129. },
  130. #endif
  131. };
  132. static struct rt_watchdog_ops hpm_wdog_ops = {
  133. .init = hpm_wdog_init,
  134. .control = hpm_wdog_control,
  135. };
  136. static rt_err_t hpm_wdog_init(rt_watchdog_t *wdt)
  137. {
  138. hpm_wdog_t *hpm_wdog = (hpm_wdog_t*)wdt->parent.user_data;
  139. WDG_Type *base = hpm_wdog->wdog_base;
  140. clock_add_to_group(hpm_wdog->clock_name, BOARD_RUNNING_CORE & 0x1);
  141. wdg_init(base, &hpm_wdog->wdog_ctrl);
  142. return RT_EOK;
  143. }
  144. static rt_err_t hpm_wdog_open(rt_watchdog_t *wdt, rt_uint16_t oflag)
  145. {
  146. hpm_wdog_t *hpm_wdog = (hpm_wdog_t*)wdt->parent.user_data;
  147. WDG_Type *base = hpm_wdog->wdog_base;
  148. rt_enter_critical();
  149. wdg_enable(base);
  150. rt_exit_critical();
  151. return RT_EOK;
  152. }
  153. static rt_err_t hpm_wdog_close(rt_watchdog_t *wdt)
  154. {
  155. hpm_wdog_t *hpm_wdog = (hpm_wdog_t*)wdt->parent.user_data;
  156. WDG_Type *base = hpm_wdog->wdog_base;
  157. rt_enter_critical();
  158. wdg_disable(base);
  159. rt_exit_critical();
  160. return RT_EOK;
  161. }
  162. static rt_err_t hpm_wdog_refresh(rt_watchdog_t *wdt)
  163. {
  164. hpm_wdog_t *hpm_wdog = (hpm_wdog_t*)wdt->parent.user_data;
  165. WDG_Type *base = hpm_wdog->wdog_base;
  166. rt_enter_critical();
  167. wdg_restart(base);
  168. rt_exit_critical();
  169. return RT_EOK;
  170. }
  171. static rt_err_t hpm_wdog_control(rt_watchdog_t *wdt, int cmd, void *args)
  172. {
  173. rt_err_t ret = RT_EOK;
  174. hpm_wdog_t *hpm_wdog = (hpm_wdog_t*)wdt->parent.user_data;
  175. WDG_Type *base = hpm_wdog->wdog_base;
  176. wdg_control_t *wdog_ctrl = &hpm_wdog->wdog_ctrl;
  177. uint32_t temp;
  178. switch (cmd)
  179. {
  180. case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
  181. temp = wdg_get_total_reset_interval_in_us(base, WDG_EXT_CLK_FREQ);
  182. temp /= 1000000UL; /* Convert to seconds */
  183. *(uint32_t *)args = temp;
  184. break;
  185. case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
  186. RT_ASSERT(*(uint32_t *)args != 0);
  187. temp = *(uint32_t *)args;
  188. temp *= 1000000U; /* Convert to microseconds */
  189. wdog_ctrl->interrupt_interval = wdg_convert_interrupt_interval_from_us(WDG_EXT_CLK_FREQ, temp);
  190. wdog_ctrl->reset_interval = reset_interval_clock_period_mult_128; /* Intentionally hard-coded */
  191. wdog_ctrl->reset_enable = true;
  192. wdog_ctrl->interrupt_enable = true;
  193. wdog_ctrl->clksrc = wdg_clksrc_extclk;
  194. wdog_ctrl->wdg_enable = false;
  195. hpm_wdog_init(wdt);
  196. break;
  197. case RT_DEVICE_CTRL_WDT_KEEPALIVE:
  198. hpm_wdog_refresh(wdt);
  199. break;
  200. case RT_DEVICE_CTRL_WDT_START:
  201. hpm_wdog_open(wdt, *(uint16_t*)args);
  202. break;
  203. case RT_DEVICE_CTRL_WDT_STOP:
  204. hpm_wdog_close(wdt);
  205. break;
  206. default:
  207. ret = RT_EINVAL;
  208. break;
  209. }
  210. return ret;
  211. }
  212. void hpm_wdog_isr(rt_watchdog_t *wdt)
  213. {
  214. hpm_wdog_t *hpm_wdog = (hpm_wdog_t*)wdt->parent.user_data;
  215. WDG_Type *base = hpm_wdog->wdog_base;
  216. uint32_t status = wdg_get_status(base);
  217. if (IS_HPM_BITMASK_SET(status, WDG_ST_INTEXPIRED_MASK)) {
  218. wdg_clear_status(base, WDG_ST_INTEXPIRED_MASK);
  219. }
  220. }
  221. int rt_hw_wdt_init(void)
  222. {
  223. rt_err_t err = RT_EOK;
  224. #if defined(BSP_USING_WDG)
  225. for (uint32_t i = 0; i < sizeof(wdogs) / sizeof(wdogs[0]); i++)
  226. {
  227. wdogs[i].wdog->ops = &hpm_wdog_ops;
  228. clock_add_to_group(wdogs[i].clock_name, BOARD_RUNNING_CORE & 0x1);
  229. err = rt_hw_watchdog_register(wdogs[i].wdog, wdogs[i].device_name, RT_DEVICE_FLAG_RDWR, (void *)&wdogs[i]);
  230. if (err != RT_EOK)
  231. {
  232. LOG_E("rt device %s failed, status=%d\n", wdogs[i].device_name, err);
  233. }
  234. }
  235. #endif
  236. return err;
  237. }
  238. INIT_BOARD_EXPORT(rt_hw_wdt_init);
  239. #endif /* RT_USING_WDT */