dw_wdt.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /******************************************************************************
  17. * @file dw_wdt.c
  18. * @brief CSI Source File for WDT Driver
  19. * @version V1.0
  20. * @date 02. June 2017
  21. ******************************************************************************/
  22. #include <stdio.h>
  23. #include "csi_core.h"
  24. #include "drv_wdt.h"
  25. #include "dw_wdt.h"
  26. #include "soc.h"
  27. #define ERR_WDT(errno) (CSI_DRV_ERRNO_WDT_BASE | errno)
  28. static uint32_t timeout_ms[16] = {4, 7, 13, 26, 52, 105, 210, 419, 839, 1678, 3355, 6711,
  29. 13422, 26844, 53687, 107374
  30. };
  31. #define WDT_NULL_PARAM_CHK(para) \
  32. do { \
  33. if (para == NULL) { \
  34. return ERR_WDT(EDRV_PARAMETER); \
  35. } \
  36. } while (0)
  37. typedef struct {
  38. uint32_t base;
  39. uint32_t irq;
  40. wdt_event_cb_t cb_event;
  41. } dw_wdt_priv_t;
  42. static dw_wdt_priv_t wdt_instance[CONFIG_WDT_NUM];
  43. /* Driver Capabilities */
  44. static const wdt_capabilities_t wdt_capabilities = {
  45. .interrupt = 1, ///< supports interrupt
  46. };
  47. static inline void dw_wdt_enable(dw_wdt_reg_t *addr)
  48. {
  49. uint32_t value = addr->WDT_CR;
  50. value |= 1 << 0;
  51. addr->WDT_CR = value;
  52. }
  53. static inline void dw_wdt_disable(dw_wdt_reg_t *addr)
  54. {
  55. uint32_t value = addr->WDT_CR;
  56. value &= ~(1 << 0);
  57. addr->WDT_CR = value;
  58. }
  59. void dw_wdt_irqhandler(int32_t idx)
  60. {
  61. dw_wdt_priv_t *wdt_priv = &wdt_instance[idx];
  62. dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
  63. addr->WDT_EOI;
  64. if (wdt_priv->cb_event) {
  65. wdt_priv->cb_event(WDT_EVENT_TIMEOUT);
  66. }
  67. }
  68. int32_t __attribute__((weak)) target_get_wdt_count(void)
  69. {
  70. return 0;
  71. }
  72. int32_t __attribute__((weak)) target_get_wdt(uint32_t idx, uint32_t *base, uint32_t *irq)
  73. {
  74. return NULL;
  75. }
  76. /**
  77. \brief get wdt instance count.
  78. \return wdt instance count
  79. */
  80. int32_t csi_wdt_get_instance_count(void)
  81. {
  82. return target_get_wdt_count();
  83. }
  84. /**
  85. \brief Initialize WDT Interface. 1. Initializes the resources needed for the WDT interface 2.registers event callback function
  86. \param[in] idx must not exceed return value of csi_wdt_get_instance_count()
  87. \param[in] cb_event Pointer to \ref wdt_event_cb_t
  88. \return pointer to wdt instance
  89. */
  90. wdt_handle_t csi_wdt_initialize(int32_t idx, wdt_event_cb_t cb_event)
  91. {
  92. if (idx < 0 || idx >= CONFIG_WDT_NUM) {
  93. return NULL;
  94. }
  95. uint32_t base = 0u;
  96. uint32_t irq = 0u;
  97. int32_t real_idx = target_get_wdt(idx, &base, &irq);
  98. if (real_idx != idx) {
  99. return NULL;
  100. }
  101. dw_wdt_priv_t *wdt_priv = &wdt_instance[idx];
  102. wdt_priv->base = base;
  103. wdt_priv->irq = irq;
  104. wdt_priv->cb_event = cb_event;
  105. drv_nvic_enable_irq(wdt_priv->irq);
  106. return (wdt_handle_t)wdt_priv;
  107. }
  108. /**
  109. \brief De-initialize WDT Interface. stops operation and releases the software resources used by the interface
  110. \param[in] instance wdt instance to operate.
  111. \return \ref execution_status
  112. */
  113. int32_t csi_wdt_uninitialize(wdt_handle_t handle)
  114. {
  115. WDT_NULL_PARAM_CHK(handle);
  116. dw_wdt_priv_t *wdt_priv = handle;
  117. wdt_priv->cb_event = NULL;
  118. drv_nvic_disable_irq(wdt_priv->irq);
  119. return 0;
  120. }
  121. /**
  122. \brief Get driver capabilities.
  123. \param[in] wdt instance to operate.
  124. \return \ref wdt_capabilities_t
  125. */
  126. wdt_capabilities_t csi_wdt_get_capabilities(wdt_handle_t handle)
  127. {
  128. return wdt_capabilities;
  129. }
  130. /**
  131. \brief Set the WDT value. value = (2^t*0xffff * 10^6 /freq)/10^3(t: 0 ~ 15).
  132. \param[in] handle wdt handle to operate.
  133. \param[in] value the timeout value(ms) \ref:timeout_ms[]
  134. \return \ref execution_status
  135. */
  136. int32_t csi_wdt_set_timeout(wdt_handle_t handle, uint32_t value)
  137. {
  138. WDT_NULL_PARAM_CHK(handle);
  139. uint32_t i = 0u;
  140. for (i = 0; i <= 15 ; i++) {
  141. if (timeout_ms[i] == value) {
  142. break;
  143. }
  144. if (i == 15) {
  145. return ERR_WDT(EDRV_PARAMETER);
  146. }
  147. }
  148. dw_wdt_priv_t *wdt_priv = handle;
  149. dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
  150. uint32_t config = addr->WDT_CR;
  151. uint32_t en_stat = 0; /*origin wdt enable status*/
  152. if ((config & 0x1) != 0) {
  153. en_stat = 1;
  154. }
  155. config = 0;
  156. addr->WDT_CR = config;
  157. /*before configuration, must disable wdt first*/
  158. dw_wdt_disable(addr);
  159. i += i << 4;
  160. addr->WDT_TORR = i;
  161. if (en_stat == 1) {
  162. dw_wdt_enable(addr);
  163. csi_wdt_restart(handle);
  164. }
  165. return 0;
  166. }
  167. /**
  168. \brief Start the WDT.
  169. \param[in] handle wdt handle to operate.
  170. \return \ref execution_status
  171. */
  172. int32_t csi_wdt_start(wdt_handle_t handle)
  173. {
  174. WDT_NULL_PARAM_CHK(handle);
  175. dw_wdt_priv_t *wdt_priv = handle;
  176. dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
  177. dw_wdt_enable(addr);
  178. csi_wdt_restart(handle);
  179. return 0;
  180. }
  181. /**
  182. \brief Stop the WDT.
  183. \param[in] handle wdt handle to operate.
  184. \return \ref execution_status
  185. */
  186. int32_t csi_wdt_stop(wdt_handle_t handle)
  187. {
  188. WDT_NULL_PARAM_CHK(handle);
  189. return ERR_WDT(EDRV_UNSUPPORTED);
  190. }
  191. /**
  192. \brief Restart the WDT.
  193. \param[in] handle wdt handle to operate.
  194. \return \ref execution_status
  195. */
  196. int32_t csi_wdt_restart(wdt_handle_t handle)
  197. {
  198. WDT_NULL_PARAM_CHK(handle);
  199. dw_wdt_priv_t *wdt_priv = handle;
  200. dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
  201. addr->WDT_CRR = DW_WDT_CRR_RESET;
  202. return 0;
  203. }
  204. /**
  205. \brief Read the WDT Current value.
  206. \param[in] handle wdt handle to operate.
  207. \param[in] value Pointer to the Value.
  208. \return \ref execution_status
  209. */
  210. int32_t csi_wdt_read_current_value(wdt_handle_t handle, uint32_t *value)
  211. {
  212. WDT_NULL_PARAM_CHK(handle);
  213. dw_wdt_priv_t *wdt_priv = handle;
  214. dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
  215. *value = addr->WDT_CCVR;
  216. return 0;
  217. }