Skip to content

Commit 5c354ca

Browse files
ene-stevenfabiobaltieri
authored andcommitted
drivers: watchdog: initial device driver for ENE KB1200
Add watchdog driver for ENE KB1200 Signed-off-by: Steven Chang <[email protected]>
1 parent 4fe1a85 commit 5c354ca

File tree

4 files changed

+185
-0
lines changed

4 files changed

+185
-0
lines changed

drivers/watchdog/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ zephyr_library_sources_ifdef(CONFIG_WDT_OPENTITAN wdt_opentitan.c)
4141
zephyr_library_sources_ifdef(CONFIG_WDT_AMBIQ wdt_ambiq.c)
4242
zephyr_library_sources_ifdef(CONFIG_WDT_XMC4XXX wdt_xmc4xxx.c)
4343
zephyr_library_sources_ifdef(CONFIG_WWDT_NUMAKER wdt_wwdt_numaker.c)
44+
zephyr_library_sources_ifdef(CONFIG_WDT_ENE_KB1200 wdt_ene_kb1200.c)
4445

4546
zephyr_library_sources_ifdef(CONFIG_WDT_DW wdt_dw.c wdt_dw_common.c)
4647
zephyr_library_sources_ifdef(CONFIG_WDT_INTEL_ADSP wdt_intel_adsp.c wdt_dw_common.c)

drivers/watchdog/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,6 @@ source "drivers/watchdog/Kconfig.xmc4xxx"
124124

125125
source "drivers/watchdog/Kconfig.numaker"
126126

127+
source "drivers/watchdog/Kconfig.ene"
128+
127129
endif # WATCHDOG

drivers/watchdog/Kconfig.ene

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2024 ENE Technology Inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config WDT_ENE_KB1200
5+
bool "ENE KB1200 watchdog driver"
6+
default y
7+
depends on DT_HAS_ENE_KB1200_WATCHDOG_ENABLED
8+
help
9+
This option enables the KB1200 watchdog driver.

drivers/watchdog/wdt_ene_kb1200.c

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* Copyright (c) 2024 ENE Technology Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT ene_kb1200_watchdog
8+
9+
#include <zephyr/irq.h>
10+
#include <zephyr/kernel.h>
11+
#include <zephyr/drivers/watchdog.h>
12+
#include <errno.h>
13+
#include <reg/wdt.h>
14+
15+
/* Device config */
16+
struct wdt_kb1200_config {
17+
struct wdt_regs *wdt;
18+
};
19+
20+
/* Device data */
21+
struct wdt_kb1200_data {
22+
wdt_callback_t cb;
23+
bool timeout_installed;
24+
};
25+
26+
/* WDT api functions */
27+
static int wdt_kb1200_setup(const struct device *dev, uint8_t options)
28+
{
29+
struct wdt_kb1200_config const *cfg = dev->config;
30+
struct wdt_kb1200_data *data = dev->data;
31+
32+
if (!data->timeout_installed) {
33+
printk("No valid WDT timeout installed");
34+
return -EINVAL;
35+
}
36+
if (options & WDT_OPT_PAUSE_HALTED_BY_DBG) {
37+
printk("WDT_OPT_PAUSE_HALTED_BY_DBG is not supported");
38+
return -ENOTSUP;
39+
}
40+
41+
/* Setting Clock Source */
42+
if (options & WDT_OPT_PAUSE_IN_SLEEP) {
43+
cfg->wdt->WDTCFG = WDT_ADCO32K;
44+
} else {
45+
cfg->wdt->WDTCFG = WDT_PHER32K;
46+
}
47+
/* Clear Pending Flag */
48+
cfg->wdt->WDTPF = (WDT_HALF_WAY_EVENT | WDT_RESET_EVENT);
49+
/* WDT enable */
50+
cfg->wdt->WDTCFG |= WDT_FUNCTON_ENABLE;
51+
52+
return 0;
53+
}
54+
55+
static int wdt_kb1200_disable(const struct device *dev)
56+
{
57+
struct wdt_kb1200_config const *cfg = dev->config;
58+
struct wdt_kb1200_data *data = dev->data;
59+
60+
if (!(cfg->wdt->WDTCFG & WDT_FUNCTON_ENABLE)) {
61+
return -EALREADY;
62+
}
63+
/* WDT disable, write bit 7~4 = 1001b */
64+
cfg->wdt->WDTCFG = (cfg->wdt->WDTCFG & ~WDT_FUNCTON_ENABLE) | WDT_DISABLE_PASSWORD;
65+
/* Clear Pending Flag */
66+
cfg->wdt->WDTPF = (WDT_HALF_WAY_EVENT | WDT_RESET_EVENT);
67+
/* Need disable IE,or the wdt-half-event interrupt will be entered */
68+
cfg->wdt->WDTIE &= ~WDT_HALF_WAY_EVENT;
69+
data->timeout_installed = false;
70+
71+
return 0;
72+
}
73+
74+
static int wdt_kb1200_install_timeout(const struct device *dev,
75+
const struct wdt_timeout_cfg *config)
76+
{
77+
struct wdt_kb1200_config const *cfg = dev->config;
78+
struct wdt_kb1200_data *data = dev->data;
79+
80+
/* Watchdog Counter Match Value */
81+
if (config->window.min > 0U) {
82+
data->timeout_installed = false;
83+
return -EINVAL;
84+
}
85+
cfg->wdt->WDTM = (config->window.max) / WDT_SAMPLE_TIME;
86+
/* (HW design) The counter match value must be >= 3 */
87+
if (cfg->wdt->WDTM < WDT_MIN_CNT) {
88+
data->timeout_installed = false;
89+
return -EINVAL;
90+
}
91+
92+
/* Watchdog behavior flags */
93+
if ((config->flags & WDT_FLAG_RESET_MASK) == WDT_FLAG_RESET_SOC) {
94+
/* Reset: SoC */
95+
cfg->wdt->WDTCFG_T = WDT_RESET_WHOLE_CHIP_WO_GPIO;
96+
} else if ((config->flags & WDT_FLAG_RESET_MASK) == WDT_FLAG_RESET_CPU_CORE) {
97+
/* Reset: CPU core */
98+
cfg->wdt->WDTCFG_T = WDT_RESET_WHOLE_CHIP;
99+
} else {
100+
/* Reset: none */
101+
cfg->wdt->WDTCFG_T = WDT_RESET_ONLY_MCU;
102+
}
103+
104+
/* Watchdog callback function */
105+
data->cb = config->callback;
106+
if (data->cb) {
107+
cfg->wdt->WDTIE |= WDT_HALF_WAY_EVENT;
108+
} else {
109+
/* If the callback function is NULL,the SoC will be reset directly.
110+
* But still need enable interrupt.
111+
*/
112+
cfg->wdt->WDTIE |= WDT_HALF_WAY_EVENT;
113+
}
114+
data->timeout_installed = true;
115+
116+
return 0;
117+
}
118+
119+
static int wdt_kb1200_feed(const struct device *dev, int channel_id)
120+
{
121+
struct wdt_kb1200_config const *cfg = dev->config;
122+
123+
ARG_UNUSED(dev);
124+
ARG_UNUSED(channel_id);
125+
126+
if (!(cfg->wdt->WDTCFG & WDT_FUNCTON_ENABLE)) {
127+
return -EINVAL;
128+
}
129+
/* Re-enable to reset counter */
130+
cfg->wdt->WDTCFG |= WDT_FUNCTON_ENABLE;
131+
/* Clear Pending Flag */
132+
cfg->wdt->WDTPF = WDT_HALF_WAY_EVENT;
133+
134+
return 0;
135+
}
136+
137+
static void wdt_kb1200_isr(const struct device *dev)
138+
{
139+
struct wdt_kb1200_data *data = dev->data;
140+
141+
if (data->cb) {
142+
data->cb(dev, 0);
143+
}
144+
}
145+
146+
static const struct wdt_driver_api wdt_kb1200_api = {
147+
.setup = wdt_kb1200_setup,
148+
.disable = wdt_kb1200_disable,
149+
.install_timeout = wdt_kb1200_install_timeout,
150+
.feed = wdt_kb1200_feed,
151+
};
152+
153+
static int wdt_kb1200_init(const struct device *dev)
154+
{
155+
if (IS_ENABLED(CONFIG_WDT_DISABLE_AT_BOOT)) {
156+
wdt_kb1200_disable(dev);
157+
}
158+
159+
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), wdt_kb1200_isr,
160+
DEVICE_DT_INST_GET(0), 0);
161+
irq_enable(DT_INST_IRQN(0));
162+
163+
return 0;
164+
}
165+
166+
static const struct wdt_kb1200_config wdt_kb1200_config = {
167+
.wdt = (struct wdt_regs *)DT_INST_REG_ADDR(0),
168+
};
169+
170+
static struct wdt_kb1200_data wdt_kb1200_dev_data;
171+
172+
DEVICE_DT_INST_DEFINE(0, wdt_kb1200_init, NULL, &wdt_kb1200_dev_data, &wdt_kb1200_config,
173+
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &wdt_kb1200_api);

0 commit comments

Comments
 (0)