Skip to content

Commit 4e5bbea

Browse files
committed
bsp: k230: add watchdog driver
Signed-off-by: Wang Chen <[email protected]>
1 parent 6bdce0f commit 4e5bbea

File tree

3 files changed

+325
-0
lines changed

3 files changed

+325
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# RT-Thread building script for component
2+
3+
from building import *
4+
5+
cwd = GetCurrentDir()
6+
src = Glob('*.c') + Glob('*.S')
7+
CPPPATH = [cwd]
8+
9+
group = DefineGroup('WDT', src, depend = ['RT_USING_WDT'], CPPPATH = CPPPATH)
10+
11+
objs = [group]
12+
13+
list = os.listdir(cwd)
14+
15+
for item in list:
16+
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
17+
objs = objs + SConscript(os.path.join(item, 'SConscript'))
18+
19+
Return('objs')
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
2+
*
3+
* Redistribution and use in source and binary forms, with or without
4+
* modification, are permitted provided that the following conditions are met:
5+
* 1. Redistributions of source code must retain the above copyright
6+
* notice, this list of conditions and the following disclaimer.
7+
* 2. Redistributions in binary form must reproduce the above copyright
8+
* notice, this list of conditions and the following disclaimer in the
9+
* documentation and/or other materials provided with the distribution.
10+
*
11+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
12+
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
13+
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14+
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
16+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
17+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21+
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24+
*/
25+
26+
#include <rtthread.h>
27+
#include <rtdevice.h>
28+
#include <riscv_io.h>
29+
#include "board.h"
30+
#include "ioremap.h"
31+
#include "sysctl_clk.h"
32+
#include "drv_wdt.h"
33+
#include <rtdbg.h>
34+
#include <sys/ioctl.h>
35+
static rt_watchdog_t kd_watchdog;
36+
static kd_wdt_t *kd_wdt_reg;
37+
38+
/* There are sixteen TOPs (timeout periods) that can be set in the watchdog. */
39+
40+
static const rt_uint32_t *tops;
41+
42+
static const rt_uint32_t kd_wdt_fix_tops[KD_WDT_NUM_TOPS] = {
43+
KD_WDT_FIX_TOP(0), KD_WDT_FIX_TOP(1), KD_WDT_FIX_TOP(2),
44+
KD_WDT_FIX_TOP(3), KD_WDT_FIX_TOP(4), KD_WDT_FIX_TOP(5),
45+
KD_WDT_FIX_TOP(6), KD_WDT_FIX_TOP(7), KD_WDT_FIX_TOP(8),
46+
KD_WDT_FIX_TOP(9), KD_WDT_FIX_TOP(10), KD_WDT_FIX_TOP(11),
47+
KD_WDT_FIX_TOP(12), KD_WDT_FIX_TOP(13), KD_WDT_FIX_TOP(14),
48+
KD_WDT_FIX_TOP(15)
49+
};
50+
51+
static struct kd_wdt_timeout timeouts[KD_WDT_NUM_TOPS];
52+
static char rmod; //wdt reset mode,
53+
54+
static void kd_wdt_timeouts_init(void)
55+
{
56+
rt_uint32_t wdt_clk;
57+
rt_uint32_t time_value;
58+
rt_uint32_t i, t;
59+
rt_uint64_t msec;
60+
struct kd_wdt_timeout tout, *dst;
61+
/* caculate timeout value */
62+
wdt_clk = sysctl_clk_get_leaf_freq(SYSCTL_CLK_WDT_1_CLK);
63+
64+
for (i = 0; i < KD_WDT_NUM_TOPS; ++i)
65+
{
66+
tout.top_val = i;
67+
tout.sec = tops[i] / wdt_clk;
68+
msec = (rt_uint64_t)tops[i] * (rt_uint64_t)1000L;
69+
msec = msec / wdt_clk;
70+
tout.msec = msec - (rt_uint64_t)tout.sec * (rt_uint64_t)1000L;
71+
72+
for (t = 0; t < i; ++t)
73+
{
74+
dst = &timeouts[t];
75+
if (tout.sec > dst->sec || (tout.sec == dst->sec &&
76+
tout.msec >= dst->msec))
77+
continue;
78+
else
79+
swap(*dst, tout);
80+
}
81+
82+
timeouts[i] = tout;
83+
}
84+
rt_kprintf("watchdog timeout table init OK!\n");
85+
}
86+
87+
static rt_err_t kd_wdt_feed(rt_watchdog_t *wdt)
88+
{
89+
kd_wdt_t *reg = (kd_wdt_t *)wdt->parent.user_data;
90+
reg->crr = 0x76;
91+
92+
return RT_EOK;
93+
}
94+
95+
static rt_err_t kd_wdt_enable(rt_watchdog_t *wdt)
96+
{
97+
kd_wdt_t *reg = (kd_wdt_t *)wdt->parent.user_data;
98+
reg->crr = 0x76;
99+
reg->cr |= 0x1;
100+
101+
return RT_EOK;
102+
}
103+
104+
static rt_err_t kd_wdt_disable(rt_watchdog_t *wdt)
105+
{
106+
kd_wdt_t *reg = (kd_wdt_t *)wdt->parent.user_data;
107+
reg->crr = 0x76;
108+
reg->cr &= ~0x1;
109+
110+
return RT_EOK;
111+
}
112+
113+
static rt_err_t kd_wdt_set_timeout(rt_watchdog_t *wdt, rt_uint64_t timeout)
114+
{
115+
kd_wdt_t *reg = (kd_wdt_t *)wdt->parent.user_data;
116+
rt_uint32_t top_val;
117+
rt_uint32_t i;
118+
rt_uint32_t time = (timeout + rmod -1) / rmod;
119+
120+
for (i = 0; i < KD_WDT_NUM_TOPS; ++i)
121+
{
122+
if (timeouts[i].sec >= time)
123+
break;
124+
}
125+
126+
if (i == KD_WDT_NUM_TOPS)
127+
--i;
128+
129+
top_val = timeouts[i].top_val;
130+
131+
reg->torr = (top_val << 4) | (top_val << 0);
132+
133+
return RT_EOK;
134+
}
135+
136+
static rt_err_t kd_wdt_get_timeout(rt_watchdog_t *wdt, void *timeout)
137+
{
138+
rt_uint64_t top_val;
139+
rt_uint32_t i;
140+
kd_wdt_t *reg = (kd_wdt_t *)wdt->parent.user_data;
141+
top_val = ((reg->torr) & 0xf);
142+
143+
for (i = 0; i < KD_WDT_NUM_TOPS; ++i)
144+
{
145+
if (timeouts[i].top_val == top_val)
146+
break;
147+
}
148+
149+
*((rt_uint64_t *)timeout) = timeouts[i].sec * rmod;
150+
151+
return RT_EOK;
152+
}
153+
154+
static rt_err_t kd_wdt_init(rt_watchdog_t *wdt)
155+
{
156+
kd_wdt_t *reg = (kd_wdt_t *)wdt->parent.user_data;
157+
reg->cr &= ~(0x01 << 1);
158+
reg->cr |= (0x0 << 1); //default set wdt reset mode
159+
rmod = KD_WDT_RMOD_RESET;
160+
161+
if (reg->comp_param_1 & (1 << 6))
162+
{
163+
tops = kd_wdt_fix_tops;
164+
}
165+
166+
kd_wdt_timeouts_init();
167+
168+
if (!timeouts[KD_WDT_NUM_TOPS - 1].sec)
169+
{
170+
rt_kprintf("No any valid Timeout period detected\n");
171+
return -RT_EINVAL;
172+
}
173+
174+
return RT_EOK;
175+
}
176+
177+
static rt_err_t kd_wdt_control(rt_watchdog_t *wdt, int cmd, void *args)
178+
{
179+
RT_ASSERT(wdt != NULL);
180+
kd_wdt_t *reg = (kd_wdt_t *)wdt->parent.user_data;
181+
182+
switch(cmd)
183+
{
184+
case KD_DEVICE_CTRL_WDT_GET_TIMEOUT:
185+
kd_wdt_get_timeout(wdt, args);
186+
break;
187+
case KD_DEVICE_CTRL_WDT_SET_TIMEOUT:
188+
kd_wdt_set_timeout(wdt, *((rt_uint32_t*)args));
189+
break;
190+
case KD_DEVICE_CTRL_WDT_KEEPALIVE:
191+
kd_wdt_feed(wdt);
192+
break;
193+
case KD_DEVICE_CTRL_WDT_START:
194+
kd_wdt_enable(wdt);
195+
break;
196+
case RT_DEVICE_CTRL_WDT_STOP:
197+
case KD_DEVICE_CTRL_WDT_STOP:
198+
kd_wdt_disable(wdt);
199+
break;
200+
default:
201+
return -RT_EINVAL;
202+
}
203+
204+
return RT_EOK;
205+
}
206+
207+
static struct rt_watchdog_ops kd_wdt_ops =
208+
{
209+
.init = kd_wdt_init,
210+
.control = kd_wdt_control,
211+
};
212+
213+
int rt_hw_wdt_init(void)
214+
{
215+
rt_err_t ret = RT_EOK;
216+
kd_wdt_reg = (kd_wdt_t *)rt_ioremap((void *)WDT1_BASE_ADDR, WDT1_IO_SIZE);
217+
218+
kd_watchdog.ops = &kd_wdt_ops;
219+
220+
ret = rt_hw_watchdog_register(&kd_watchdog, "watchdog1", RT_DEVICE_FLAG_RDWR, kd_wdt_reg);
221+
222+
if (ret != RT_EOK)
223+
{
224+
LOG_E("rt device register failed %d\n", ret);
225+
}
226+
#ifndef RT_FASTBOOT
227+
rt_kprintf("watchdog register OK!\n");
228+
#endif
229+
return ret;
230+
}
231+
INIT_DEVICE_EXPORT(rt_hw_wdt_init);
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) 2011-2022, Shanghai Real-Thread Electronic Technology Co.,Ltd
3+
*
4+
* Change Logs:
5+
* Date Author Notes
6+
* 2022-04-01 SummerGift add i2c driver
7+
*/
8+
9+
#ifndef DRV_WDT_H_
10+
#define DRV_WDT_H_
11+
12+
#include <drivers/dev_watchdog.h>
13+
#include <sys/ioctl.h>
14+
15+
#define DEFUALT_TIMEOUT 30*1000 /* ms */
16+
#define KD_WDT_NUM_TOPS 16
17+
#define KD_WDT_FIX_TOP(_idx) (1U << (16 + _idx))
18+
#define KD_WDT_RMOD_RESET 1
19+
#define KD_WDT_RMOD_IRQ 2
20+
21+
#define KD_DEVICE_CTRL_WDT_GET_TIMEOUT _IOW('W', 1, int) /* get timeout(in seconds) */
22+
#define KD_DEVICE_CTRL_WDT_SET_TIMEOUT _IOW('W', 2, int) /* set timeout(in seconds) */
23+
#define KD_DEVICE_CTRL_WDT_GET_TIMELEFT _IOW('W', 3, int) /* get the left time before reboot(in seconds) */
24+
#define KD_DEVICE_CTRL_WDT_KEEPALIVE _IOW('W', 4, int) /* refresh watchdog */
25+
#define KD_DEVICE_CTRL_WDT_START _IOW('W', 5, int) /* start watchdog */
26+
#define KD_DEVICE_CTRL_WDT_STOP _IOW('W', 6, int) /* stop watchdog */
27+
28+
struct kd_wdt_timeout {
29+
rt_uint32_t top_val;
30+
rt_uint32_t sec;
31+
rt_uint32_t msec;
32+
};
33+
34+
#define swap(a, b) \
35+
do { struct kd_wdt_timeout __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
36+
37+
/* wdt register map */
38+
typedef struct _wdt
39+
{
40+
/* WDT Control Register (0x00) */
41+
volatile uint32_t cr;
42+
/* WDT Timeout Range Register (0x04) */
43+
volatile uint32_t torr;
44+
/* WDT Current Counter Value Register (0x08) */
45+
volatile uint32_t ccvr;
46+
/* WDT Counter Restart Register (0x0c) */
47+
volatile uint32_t crr;
48+
/* WDT Interrupt Status Register (0x10) */
49+
volatile uint32_t stat;
50+
/* WDT Interrupt Clear Register (0x14) */
51+
volatile uint32_t eoi;
52+
/* reserverd (0x18) */
53+
volatile uint32_t resv1;
54+
/* WDT Protection level Register (0x1c) */
55+
volatile uint32_t prot_level;
56+
/* reserved (0x20-0xe0) */
57+
volatile uint32_t resv4[49];
58+
/* WDT Component Parameters Register 5 (0xe4) */
59+
volatile uint32_t comp_param_5;
60+
/* WDT Component Parameters Register 4 (0xe8) */
61+
volatile uint32_t comp_param_4;
62+
/* WDT Component Parameters Register 3 (0xec) */
63+
volatile uint32_t comp_param_3;
64+
/* WDT Component Parameters Register 2 (0xf0) */
65+
volatile uint32_t comp_param_2;
66+
/* WDT Component Parameters Register 1 (0xf4) */
67+
volatile uint32_t comp_param_1;
68+
/* WDT Component Version Register (0xf8) */
69+
volatile uint32_t comp_version;
70+
/* WDT Component Type Register (0xfc) */
71+
volatile uint32_t comp_type;
72+
} __attribute__((packed, aligned(4))) kd_wdt_t;
73+
74+
75+
#endif /* DRV_WDT_H_ */

0 commit comments

Comments
 (0)