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  * 2022-05-16     shelton           first version
9  */
10 
11 #include "drivers/dev_watchdog.h"
12 #include "drv_common.h"
13 
14 #ifdef RT_USING_WDT
15 
16 #define LICK_VALUE                      40000
17 
18 //#define DRV_DEBUG
19 #define LOG_TAG                         "drv.wdt"
20 #include <drv_log.h>
21 
22 struct at32_wdt_obj
23 {
24     wdt_type *wdt_x;
25     wdt_division_type div;
26     rt_uint32_t reload;
27     rt_uint16_t is_start;
28 };
29 static struct at32_wdt_obj at32_wdt;
30 static struct rt_watchdog_ops ops;
31 static rt_watchdog_t watchdog;
32 
wdt_init(rt_watchdog_t * wdt)33 static rt_err_t wdt_init(rt_watchdog_t *wdt)
34 {
35     return RT_EOK;
36 }
37 
wdt_control(rt_watchdog_t * wdt,int cmd,void * arg)38 static rt_err_t wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
39 {
40     switch (cmd)
41     {
42     /* feed the watchdog */
43     case RT_DEVICE_CTRL_WDT_KEEPALIVE:
44         wdt_counter_reload();
45         break;
46     /* set watchdog timeout */
47     case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
48 #if defined(LICK_VALUE)
49         if(LICK_VALUE)
50         {
51             at32_wdt.reload = (*((rt_uint32_t*)arg)) * LICK_VALUE / 256 ;
52         }
53         else
54         {
55             LOG_E("Please define the value of LICK_VALUE!");
56         }
57         if(at32_wdt.reload > 0xFFF)
58         {
59             LOG_E("wdg set timeout parameter too large, please less than %ds", 0xFFF * 256 / LICK_VALUE);
60             return -RT_EINVAL;
61         }
62 #else
63   #error "Please define the value of LICK_VALUE!"
64 #endif
65         if(at32_wdt.is_start)
66         {
67             wdt_register_write_enable(TRUE);
68             wdt_divider_set(at32_wdt.div);
69             wdt_reload_value_set(at32_wdt.reload);
70             wdt_counter_reload();
71             wdt_register_write_enable(FALSE);
72             wdt_enable();
73         }
74         break;
75     case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
76 #if defined(LICK_VALUE)
77         if(LICK_VALUE)
78         {
79             (*((rt_uint32_t*)arg)) = at32_wdt.reload * 256 / LICK_VALUE;
80         }
81         else
82         {
83             LOG_E("Please define the value of LICK_VALUE!");
84         }
85 #else
86   #error "Please define the value of LICK_VALUE!"
87 #endif
88         break;
89     case RT_DEVICE_CTRL_WDT_START:
90         wdt_register_write_enable(TRUE);
91         wdt_divider_set(at32_wdt.div);
92         wdt_reload_value_set(at32_wdt.reload);
93         wdt_counter_reload();
94         wdt_register_write_enable(FALSE);
95         wdt_enable();
96         at32_wdt.is_start = 1;
97         break;
98     default:
99         LOG_W("This command is not supported.");
100         return -RT_ERROR;
101     }
102     return RT_EOK;
103 }
104 
rt_hw_wdt_init(void)105 int rt_hw_wdt_init(void)
106 {
107     at32_wdt.wdt_x = WDT;
108     at32_wdt.div = WDT_CLK_DIV_256;
109     at32_wdt.reload = 0x00000FFF;
110     at32_wdt.is_start = 0;
111 
112     ops.init = &wdt_init;
113     ops.control = &wdt_control;
114     watchdog.ops = &ops;
115     /* register watchdog device */
116     if (rt_hw_watchdog_register(&watchdog, "wdt", RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK)
117     {
118         LOG_E("wdt device register failed.");
119         return -RT_ERROR;
120     }
121     LOG_D("wdt device register success.");
122     return RT_EOK;
123 }
124 
125 INIT_BOARD_EXPORT(rt_hw_wdt_init);
126 
127 #endif /* RT_USING_WDT */
128