1 /*
2 * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 /**
17 * @file wm_watchdog.c
18 *
19 * @brief watchdog Driver Module
20 *
21 * @author kevin
22 *
23 * Copyright (c) 2014 Winner Microelectronics Co., Ltd.
24 */
25 #include "wm_debug.h"
26 #include "wm_regs.h"
27 #include "wm_irq.h"
28 #include "wm_cpu.h"
29 #include "wm_watchdog.h"
30
31 #define WDG_LOAD_VALUE_MAX (0xFFFFFFFF / 40)
32 #define WDG_LOAD_VALUE_DEF (20 * 1000 * 1000)
33
34 static volatile u8 wdg_reset = 0;
35 static volatile u8 wdg_enable = 0;
36 static volatile u32 wdg_value_us = WDG_LOAD_VALUE_DEF;
37 static volatile u32 wdg_jumpclear_flag = 0; /* 0:donot jump clear, 1: jump clear, 2:close wdg */
WDG_IRQHandler(void)38 ATTRIBUTE_ISR void WDG_IRQHandler(void)
39 {
40 csi_kernel_intrpt_enter();
41 if (wdg_reset) {
42 csi_kernel_intrpt_exit();
43 return;
44 }
45 csi_kernel_intrpt_exit();
46 }
47
48 /**
49 * @brief This function is used to clear watchdog irq in case watchdog reset
50 *
51 * @param None
52 *
53 * @return None
54 *
55 * @note None
56 */
tls_watchdog_clr(void)57 void tls_watchdog_clr(void)
58 {
59 if (wdg_jumpclear_flag == 0) {
60 tls_reg_write32(HR_WDG_INT_CLR, 0x01);
61 }
62 }
63
__tls_watchdog_init(u32 usec)64 static void __tls_watchdog_init(u32 usec)
65 {
66 tls_sys_clk sysclk;
67
68 tls_sys_clk_get(&sysclk);
69 tls_irq_enable(WDG_IRQn);
70
71 tls_reg_write32(HR_WDG_LOAD_VALUE, sysclk.apbclk * usec); /* 40M dominant frequency: 40 * 10^6 * (usec / 10^6) */
72 tls_reg_write32(HR_WDG_CTRL, 0x3); /* enable irq & reset */
73 }
74
__tls_watchdog_deinit(void)75 static void __tls_watchdog_deinit(void)
76 {
77 tls_irq_disable(WDG_IRQn);
78 tls_reg_write32(HR_WDG_CTRL, 0);
79 tls_reg_write32(HR_WDG_INT_CLR, 0x01);
80 }
81
82 /**
83 * @brief This function is used to init watchdog
84 *
85 * @param[in] usec microseconds
86 *
87 * @return None
88 *
89 * @note None
90 */
tls_watchdog_init(u32 usec)91 void tls_watchdog_init(u32 usec)
92 {
93 __tls_watchdog_init(usec);
94
95 wdg_value_us = usec;
96 wdg_enable = 1;
97 }
98
99 /**
100 * @brief This function is used to deinit watchdog
101 *
102 * @param[in] None
103 *
104 * @return None
105 *
106 * @note None
107 */
tls_watchdog_deinit(void)108 void tls_watchdog_deinit(void)
109 {
110 __tls_watchdog_deinit();
111
112 wdg_value_us = WDG_LOAD_VALUE_DEF;
113 wdg_enable = 0;
114 }
115
116 /**
117 * @brief This function is used to start calculating elapsed time.
118 *
119 * @param[in] None
120 *
121 * @return elapsed time, unit:millisecond
122 *
123 * @note None
124 */
tls_watchdog_start_cal_elapsed_time(void)125 void tls_watchdog_start_cal_elapsed_time(void)
126 {
127 if (wdg_enable) {
128 wdg_jumpclear_flag = 1;
129
130 __tls_watchdog_deinit();
131
132 __tls_watchdog_init(WDG_LOAD_VALUE_MAX);
133 } else {
134 wdg_jumpclear_flag = 2;
135 __tls_watchdog_init(WDG_LOAD_VALUE_MAX);
136 }
137 }
138
139 /**
140 * @brief This function is used to stop calculating & return elapsed time.
141 *
142 * @param[in] none
143 *
144 * @return elapsed time, unit:millisecond
145 *
146 * @note None
147 */
tls_watchdog_stop_cal_elapsed_time(void)148 u32 tls_watchdog_stop_cal_elapsed_time(void)
149 {
150 #define RT_TIME_BASE (40)
151 u32 val = 0;
152
153 switch (wdg_jumpclear_flag) {
154 case 1:
155 {
156 val = (tls_reg_read32(HR_WDG_LOAD_VALUE) - tls_reg_read32(HR_WDG_CUR_VALUE))/RT_TIME_BASE;
157 __tls_watchdog_deinit();
158 __tls_watchdog_init(wdg_value_us);
159 wdg_jumpclear_flag = 0;
160 }
161 break;
162
163 case 2:
164 {
165 val = (tls_reg_read32(HR_WDG_LOAD_VALUE) - tls_reg_read32(HR_WDG_CUR_VALUE))/RT_TIME_BASE;
166 __tls_watchdog_deinit();
167 wdg_jumpclear_flag = 0;
168 }
169 break;
170
171 default:
172 wdg_jumpclear_flag = 0;
173 break;
174 }
175
176 return val;
177 }
178 /**
179 * @brief This function is used to reset system
180 *
181 * @param None
182 *
183 * @return None
184 *
185 * @note None
186 */
tls_sys_reset(void)187 void tls_sys_reset(void)
188 {
189 tls_os_set_critical();
190 wdg_reset = 1;
191 __tls_watchdog_deinit();
192 tls_reg_write32(HR_WDG_LOCK, 0x1ACCE551);
193 tls_reg_write32(HR_WDG_LOAD_VALUE, 0x100);
194 tls_reg_write32(HR_WDG_CTRL, 0x3);
195 tls_reg_write32(HR_WDG_LOCK, 1);
196 while (1) {
197 }
198 }
199
200