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
11 #include <rtthread.h>
12 #include <rtdevice.h>
13
14 #ifdef RT_USING_WDT
15
16 #include "drivers/dev_watchdog.h"
17 #include "drv_wdt.h"
18
19 #include "ls1c_wdog.h"
20 #include "ls1c_clock.h"
21
22 typedef enum
23 {
24 RESTENABLE = 0x0,
25 INTERRUPTENABLE = 0x1,
26 }wdt_enable_mode;
27
28 static rt_uint32_t heartbeat = 0;
29
wdt_stop(void)30 static rt_err_t wdt_stop(void)
31 {
32 rt_err_t ret = RT_EOK;
33
34 Wdog_Reset();
35 ret = (rt_err_t) Wdog_Disable();
36 if (ret != RT_EOK)
37 {
38 rt_kprintf("Wdog_Disable error!\n");
39 return -RT_ERROR;
40 }
41 return ret;
42 }
43
wdt_start(int mode)44 static rt_err_t wdt_start(int mode)
45 {
46 rt_err_t ret = RT_EOK;
47 wdt_enable_mode wdt_mode = RESTENABLE;
48
49 ret = (rt_err_t) Wdog_Disable();
50 if (ret != RT_EOK)
51 {
52 rt_kprintf("Wdog_Disable error!\n");
53 return -RT_ERROR;
54 }
55
56 if((mode == RESTENABLE) || (mode == INTERRUPTENABLE))
57 {
58 wdt_mode = mode;
59 }
60 Wdog_Enable();
61 Wdog_Set();
62 if (ret != RT_EOK)
63 {
64 rt_kprintf("Wdog_Enable error!\n");
65 return -RT_ERROR;
66 }
67
68 return ret;
69 }
70
wdt_keepalive(void)71 static rt_err_t wdt_keepalive(void)
72 {
73 rt_err_t ret = RT_EOK;
74 rt_uint32_t index = 0;
75
76 index = heartbeat * clk_get_apb_rate();
77 ret = (rt_err_t) Wdog_LoadValue(index);
78 Wdog_Set();
79 if (ret != 0)
80 {
81 rt_kprintf("LS1C_Wdog_ClrTimeout error!\n");
82 return -RT_ERROR;
83 }
84
85 return ret;
86 }
87
wdt_get_timeleft(void)88 static rt_uint32_t wdt_get_timeleft(void)
89 {
90 rt_uint32_t cnt = 0;
91 rt_uint32_t second = 0;
92
93 cnt = (rt_uint32_t) Wdog_GetValue();
94 second = cnt/clk_get_apb_rate();
95
96 return second;
97 }
98
wdt_set_timeout(rt_uint32_t second)99 static rt_err_t wdt_set_timeout(rt_uint32_t second)
100 {
101 rt_err_t ret = RT_EOK;
102 rt_uint32_t index = 0;
103
104 index = second * clk_get_apb_rate();
105 ret = (rt_err_t) Wdog_LoadValue(index);
106 if (ret != RT_EOK)
107 {
108 rt_kprintf("Wdog_LoadValue error!\n");
109 return -RT_ERROR;
110 }
111 return ret;
112 }
113
watchdog_init(rt_watchdog_t * wdt)114 static rt_err_t watchdog_init(rt_watchdog_t *wdt)
115 {
116 struct wdt_driver *wdt_drv = wdt->parent.user_data;
117 if (wdt_drv->in_use) return -RT_EBUSY;
118
119 Wdog_Init();
120
121 return RT_EOK;
122 }
123
watchdog_ctrl(rt_watchdog_t * wdt,int cmd,void * arg)124 static rt_err_t watchdog_ctrl(rt_watchdog_t *wdt, int cmd, void *arg)
125 {
126 rt_uint32_t val;
127 int mode;
128
129 switch (cmd)
130 {
131 case RT_DEVICE_CTRL_WDT_START:
132 mode = *((int *)(arg));
133 wdt_start(mode);
134 break;
135
136 case RT_DEVICE_CTRL_WDT_STOP:
137 Wdog_Disable();
138 break;
139
140 case RT_DEVICE_CTRL_WDT_KEEPALIVE:
141 wdt_keepalive();
142 break;
143
144 case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
145 heartbeat = *((rt_uint32_t *)(arg));
146 wdt_set_timeout(heartbeat);
147 break;
148
149 case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
150 arg = &heartbeat;
151 break;
152
153 case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
154 val = (rt_uint32_t) wdt_get_timeleft();
155 arg = &val;
156 break;
157
158 default:
159 return -RT_EIO;
160 }
161 return RT_EOK;
162 }
163
164 struct rt_watchdog_ops watchdog_ops =
165 {
166 .init = &watchdog_init,
167 .control = &watchdog_ctrl,
168 };
169
wdt_exit(void * priv_data)170 int wdt_exit(void *priv_data)
171 {
172 return 0;
173 }
174
rt_hw_wdt_init(void)175 int rt_hw_wdt_init(void)
176 {
177 rt_watchdog_t *wdt_dev;
178 struct wdt_driver *wdt_drv;
179
180 wdt_drv = (struct wdt_driver *)rt_malloc(sizeof(struct wdt_driver));
181 rt_memset(wdt_drv, 0, sizeof(struct wdt_driver));
182
183 wdt_dev = (rt_watchdog_t *)rt_malloc(sizeof(rt_watchdog_t));
184
185 if (wdt_dev == RT_NULL)
186 {
187 rt_kprintf("ERROR: %s rt_watchdog_t malloc failed\n", __func__);
188 }
189
190 wdt_dev->ops = &watchdog_ops;
191
192 rt_hw_watchdog_register(wdt_dev, "wdt", RT_DEVICE_OFLAG_RDWR, wdt_drv);
193
194 return 0;
195 }
196
197 INIT_BOARD_EXPORT(rt_hw_wdt_init);
198
199 #endif
200