drv_wdt.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-05-06 sundm75 first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #ifdef RT_USING_WDT
  13. #include <drivers/watchdog.h>
  14. #include "drv_wdt.h"
  15. #include "ls1c_wdog.h"
  16. #include "ls1c_clock.h"
  17. typedef enum
  18. {
  19. RESTENABLE = 0x0,
  20. INTERRUPTENABLE = 0x1,
  21. }wdt_enable_mode;
  22. static rt_uint32_t heartbeat = 0;
  23. static rt_err_t wdt_stop(void)
  24. {
  25. rt_err_t ret = RT_EOK;
  26. Wdog_Reset();
  27. ret = (rt_err_t) Wdog_Disable();
  28. if (ret != RT_EOK)
  29. {
  30. rt_kprintf("Wdog_Disable error!\n");
  31. return RT_ERROR;
  32. }
  33. return ret;
  34. }
  35. static rt_err_t wdt_start(int mode)
  36. {
  37. rt_err_t ret = RT_EOK;
  38. wdt_enable_mode wdt_mode = RESTENABLE;
  39. ret = (rt_err_t) Wdog_Disable();
  40. if (ret != RT_EOK)
  41. {
  42. rt_kprintf("Wdog_Disable error!\n");
  43. return RT_ERROR;
  44. }
  45. if((mode == RESTENABLE) || (mode == INTERRUPTENABLE))
  46. {
  47. wdt_mode = mode;
  48. }
  49. Wdog_Enable();
  50. Wdog_Set();
  51. if (ret != RT_EOK)
  52. {
  53. rt_kprintf("Wdog_Enable error!\n");
  54. return RT_ERROR;
  55. }
  56. return ret;
  57. }
  58. static rt_err_t wdt_keepalive(void)
  59. {
  60. rt_err_t ret = RT_EOK;
  61. rt_uint32_t index = 0;
  62. index = heartbeat * clk_get_apb_rate();
  63. ret = (rt_err_t) Wdog_LoadValue(index);
  64. Wdog_Set();
  65. if (ret != 0)
  66. {
  67. rt_kprintf("LS1C_Wdog_ClrTimeout error!\n");
  68. return RT_ERROR;
  69. }
  70. return ret;
  71. }
  72. static rt_uint32_t wdt_get_timeleft(void)
  73. {
  74. rt_uint32_t cnt = 0;
  75. rt_uint32_t second = 0;
  76. cnt = (rt_uint32_t) Wdog_GetValue();
  77. second = cnt/clk_get_apb_rate();
  78. return second;
  79. }
  80. static rt_err_t wdt_set_timeout(rt_uint32_t second)
  81. {
  82. rt_err_t ret = RT_EOK;
  83. rt_uint32_t index = 0;
  84. index = second * clk_get_apb_rate();
  85. ret = (rt_err_t) Wdog_LoadValue(index);
  86. if (ret != RT_EOK)
  87. {
  88. rt_kprintf("Wdog_LoadValue error!\n");
  89. return RT_ERROR;
  90. }
  91. return ret;
  92. }
  93. static rt_err_t watchdog_init(rt_watchdog_t *wdt)
  94. {
  95. struct wdt_driver *wdt_drv = wdt->parent.user_data;
  96. if (wdt_drv->in_use) return -RT_EBUSY;
  97. Wdog_Init();
  98. return RT_EOK;
  99. }
  100. static rt_err_t watchdog_ctrl(rt_watchdog_t *wdt, int cmd, void *arg)
  101. {
  102. rt_uint32_t val;
  103. int mode;
  104. switch (cmd)
  105. {
  106. case RT_DEVICE_CTRL_WDT_START:
  107. mode = *((int *)(arg));
  108. wdt_start(mode);
  109. break;
  110. case RT_DEVICE_CTRL_WDT_STOP:
  111. Wdog_Disable();
  112. break;
  113. case RT_DEVICE_CTRL_WDT_KEEPALIVE:
  114. wdt_keepalive();
  115. break;
  116. case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
  117. heartbeat = *((rt_uint32_t *)(arg));
  118. wdt_set_timeout(heartbeat);
  119. break;
  120. case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
  121. arg = &heartbeat;
  122. break;
  123. case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
  124. val = (rt_uint32_t) wdt_get_timeleft();
  125. arg = &val;
  126. break;
  127. default:
  128. return -RT_EIO;
  129. }
  130. return RT_EOK;
  131. }
  132. struct rt_watchdog_ops watchdog_ops =
  133. {
  134. .init = &watchdog_init,
  135. .control = &watchdog_ctrl,
  136. };
  137. int wdt_exit(void *priv_data)
  138. {
  139. return 0;
  140. }
  141. int rt_hw_wdt_init(void)
  142. {
  143. rt_watchdog_t *wdt_dev;
  144. struct wdt_driver *wdt_drv;
  145. wdt_drv = (struct wdt_driver *)rt_malloc(sizeof(struct wdt_driver));
  146. rt_memset(wdt_drv, 0, sizeof(struct wdt_driver));
  147. wdt_dev = (rt_watchdog_t *)rt_malloc(sizeof(rt_watchdog_t));
  148. if (wdt_dev == RT_NULL)
  149. {
  150. rt_kprintf("ERROR: %s rt_watchdog_t malloc failed\n", __func__);
  151. }
  152. wdt_dev->ops = &watchdog_ops;
  153. rt_hw_watchdog_register(wdt_dev, "wdt", RT_DEVICE_OFLAG_RDWR, wdt_drv);
  154. return 0;
  155. }
  156. INIT_BOARD_EXPORT(rt_hw_wdt_init);
  157. #endif