]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/wdt/dw_wdt.c
Introduce a port for T-HEAD CK802. A simple demo for T-HEAD CB2201 is also included.
[freertos] / FreeRTOS / Demo / T-HEAD_CB2201_CDK / csi / csi_driver / csky / common / wdt / dw_wdt.c
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 /******************************************************************************
18  * @file     dw_wdt.c
19  * @brief    CSI Source File for WDT Driver
20  * @version  V1.0
21  * @date     02. June 2017
22  ******************************************************************************/
23 #include <stdio.h>
24 #include "drv_wdt.h"
25 #include "dw_wdt.h"
26 #include "soc.h"
27 #include "csi_core.h"
28
29 #define ERR_WDT(errno) (CSI_DRV_ERRNO_WDT_BASE | errno)
30
31 static uint32_t timeout_ms[16] = {4, 7, 13, 26, 52, 105, 210, 419, 839, 1678, 3355, 6711,
32                                   13422, 26844, 53687, 107374
33                                  };
34
35 #define WDT_NULL_PARAM_CHK(para)                  \
36     do {                                    \
37         if (para == NULL) {                 \
38             return ERR_WDT(EDRV_PARAMETER);   \
39         }                                   \
40     } while (0)
41
42 typedef struct {
43     uint32_t base;
44     uint32_t irq;
45     wdt_event_cb_t cb_event;
46 } dw_wdt_priv_t;
47
48 extern int32_t target_get_wdt_count(void);
49 extern int32_t target_get_wdt(int32_t idx, uint32_t *base, uint32_t *irq);
50
51 static dw_wdt_priv_t wdt_instance[CONFIG_WDT_NUM];
52
53 /* Driver Capabilities */
54 static const wdt_capabilities_t wdt_capabilities = {
55     .interrupt = 1,      ///< supports interrupt
56 };
57
58 static inline void dw_wdt_enable(dw_wdt_reg_t *addr)
59 {
60     uint32_t value = addr->WDT_CR;
61     value |= 1 << 0;
62     addr->WDT_CR = value;
63 }
64
65 static inline void dw_wdt_disable(dw_wdt_reg_t *addr)
66 {
67     uint32_t value = addr->WDT_CR;
68     value &= ~(1 << 0);
69     addr->WDT_CR = value;
70 }
71
72
73 void dw_wdt_irqhandler(int32_t idx)
74 {
75     dw_wdt_priv_t *wdt_priv = &wdt_instance[idx];
76     dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
77
78     addr->WDT_EOI;
79
80     if (wdt_priv->cb_event) {
81         wdt_priv->cb_event(WDT_EVENT_TIMEOUT);
82     }
83 }
84
85 /**
86   \brief       get wdt instance count.
87   \return      wdt instance count
88 */
89 int32_t csi_wdt_get_instance_count(void)
90 {
91     return target_get_wdt_count();
92 }
93
94 /**
95   \brief       Initialize WDT Interface. 1. Initializes the resources needed for the WDT interface 2.registers event callback function
96   \param[in]   idx   must not exceed return value of csi_wdt_get_instance_count()
97   \param[in]   cb_event  Pointer to \ref wdt_event_cb_t
98   \return      pointer to wdt instance
99 */
100 wdt_handle_t csi_wdt_initialize(int32_t idx, wdt_event_cb_t cb_event)
101 {
102     if (idx < 0 || idx >= CONFIG_WDT_NUM) {
103         return NULL;
104     }
105
106     uint32_t base = 0u;
107     uint32_t irq = 0u;
108
109     int32_t real_idx = target_get_wdt(idx, &base, &irq);
110
111     if (real_idx != idx) {
112         return NULL;
113     }
114
115     dw_wdt_priv_t *wdt_priv = &wdt_instance[idx];
116     wdt_priv->base = base;
117     wdt_priv->irq  = irq;
118
119     wdt_priv->cb_event = cb_event;
120     drv_nvic_enable_irq(wdt_priv->irq);
121
122     return (wdt_handle_t)wdt_priv;
123 }
124
125 /**
126   \brief       De-initialize WDT Interface. stops operation and releases the software resources used by the interface
127   \param[in]   instance  wdt instance to operate.
128   \return      \ref execution_status
129 */
130 int32_t csi_wdt_uninitialize(wdt_handle_t handle)
131 {
132     WDT_NULL_PARAM_CHK(handle);
133
134     dw_wdt_priv_t *wdt_priv = handle;
135
136     wdt_priv->cb_event = NULL;
137     drv_nvic_disable_irq(wdt_priv->irq);
138     return 0;
139 }
140 /**
141   \brief       Get driver capabilities.
142   \param[in]   wdt instance to operate.
143   \return      \ref wdt_capabilities_t
144 */
145 wdt_capabilities_t csi_wdt_get_capabilities(wdt_handle_t handle)
146 {
147     return wdt_capabilities;
148 }
149
150 /**
151   \brief       Set the WDT value. value = (2^t*0xffff * 10^6 /freq)/10^3(t: 0 ~ 15).
152   \param[in]   handle wdt handle to operate.
153   \param[in]   value     the timeout value(ms) \ref:timeout_ms[]
154   \return      \ref execution_status
155 */
156 int32_t csi_wdt_set_timeout(wdt_handle_t handle, uint32_t value)
157 {
158     WDT_NULL_PARAM_CHK(handle);
159     uint32_t i = 0u;
160
161     for (i = 0; i <= 15 ; i++) {
162         if (timeout_ms[i] == value) {
163             break;
164         }
165
166         if (i == 15) {
167             return ERR_WDT(EDRV_PARAMETER);
168         }
169     }
170
171     dw_wdt_priv_t *wdt_priv = handle;
172     dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
173
174     uint32_t config = addr->WDT_CR;
175     uint32_t en_stat = 0;   /*origin wdt enable status*/
176
177     if ((config & 0x1) != 0) {
178         en_stat = 1;
179     }
180
181     config = 0;
182     addr->WDT_CR = config;
183
184     /*before configuration, must disable wdt first*/
185     dw_wdt_disable(addr);
186     i += i << 4;
187     addr->WDT_TORR = i;
188
189     if (en_stat == 1) {
190         dw_wdt_enable(addr);
191         csi_wdt_restart(handle);
192     }
193
194     return 0;
195 }
196
197 /**
198   \brief       Start the WDT.
199   \param[in]   handle wdt handle to operate.
200   \return      \ref execution_status
201 */
202 int32_t csi_wdt_start(wdt_handle_t handle)
203 {
204     WDT_NULL_PARAM_CHK(handle);
205
206     dw_wdt_priv_t *wdt_priv = handle;
207     dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
208
209     dw_wdt_enable(addr);
210     csi_wdt_restart(handle);
211     return 0;
212 }
213
214 /**
215   \brief       Stop the WDT.
216   \param[in]   handle wdt handle to operate.
217   \return      \ref execution_status
218 */
219 int32_t csi_wdt_stop(wdt_handle_t handle)
220 {
221     WDT_NULL_PARAM_CHK(handle);
222
223     return ERR_WDT(EDRV_UNSUPPORTED);
224 }
225
226 /**
227   \brief       Restart the WDT.
228   \param[in]   handle wdt handle to operate.
229   \return      \ref execution_status
230 */
231 int32_t csi_wdt_restart(wdt_handle_t handle)
232 {
233     WDT_NULL_PARAM_CHK(handle);
234
235     dw_wdt_priv_t *wdt_priv = handle;
236     dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
237
238     addr->WDT_CRR = DW_WDT_CRR_RESET;
239
240     return 0;
241 }
242
243 /**
244   \brief       Read the WDT Current value.
245   \param[in]   handle wdt handle to operate.
246   \param[in]   value     Pointer to the Value.
247   \return      \ref execution_status
248 */
249 int32_t csi_wdt_read_current_value(wdt_handle_t handle, uint32_t *value)
250 {
251     WDT_NULL_PARAM_CHK(handle);
252
253     dw_wdt_priv_t *wdt_priv = handle;
254     dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
255
256     *value = addr->WDT_CCVR;
257     return 0;
258 }
259