drv_wdt.c 5.7 KB

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