Skip to content

Commit b1395ea

Browse files
SuperHeroAbnerkartben
authored andcommitted
drivers: rtwdog: add NXP rtwdog driver
Port NXP rtwdog driver to Zephyr. Signed-off-by: Ruijia Wang <ruijia.wang@nxp.com>
1 parent e643b28 commit b1395ea

File tree

7 files changed

+324
-0
lines changed

7 files changed

+324
-0
lines changed

boards/nxp/mimxrt1180_evk/doc/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ configuration supports the following hardware features:
124124
+-----------+------------+-------------------------------------+
125125
| SPI | on-chip | spi |
126126
+-----------+------------+-------------------------------------+
127+
| RTWDOG | on-chip | rtwdog |
128+
+-----------+------------+-------------------------------------+
127129

128130
The default configuration can be found in the defconfig file:
129131
:zephyr_file:`boards/nxp/mimxrt1180_evk/mimxrt1180_evk_mimxrt1189_cm33_defconfig`

boards/nxp/mimxrt1180_evk/mimxrt1180_evk_mimxrt1189_cm33.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ supported:
2626
- i3c
2727
- dma
2828
- spi
29+
- watchdog
2930
vendor: nxp

drivers/watchdog/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ zephyr_library_sources_ifdef(CONFIG_WDT_ITE_IT8XXX2 wdt_ite_it8xxx2.c)
2121
zephyr_library_sources_ifdef(CONFIG_WDT_LITEX wdt_litex.c)
2222
zephyr_library_sources_ifdef(CONFIG_WDT_MAX32 wdt_max32.c)
2323
zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_IMX_WDOG wdt_mcux_imx_wdog.c)
24+
zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_RTWDOG wdt_mcux_rtwdog.c)
2425
zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_WDOG wdt_mcux_wdog.c)
2526
zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_WDOG32 wdt_mcux_wdog32.c)
2627
zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_WWDT wdt_mcux_wwdt.c)

drivers/watchdog/Kconfig.mcux

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,10 @@ config WDT_MCUX_WWDT_WARNING_INTERRUPT_CFG
3737
the number of watchdog counter ticks before timeout.
3838

3939
endif # WDT_MCUX_WWDT
40+
41+
config WDT_MCUX_RTWDOG
42+
bool "MCUX RTWDOG driver"
43+
default y
44+
depends on DT_HAS_NXP_RTWDOG_ENABLED
45+
help
46+
Enable the mcux rtwdog driver.

drivers/watchdog/wdt_mcux_rtwdog.c

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
/*
2+
* Copyright 2024, NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT nxp_rtwdog
8+
9+
#include <zephyr/drivers/pinctrl.h>
10+
#include <zephyr/drivers/watchdog.h>
11+
#include <zephyr/drivers/clock_control.h>
12+
#include <zephyr/sys_clock.h>
13+
#include <fsl_rtwdog.h>
14+
15+
#define LOG_LEVEL CONFIG_WDT_LOG_LEVEL
16+
#include <zephyr/logging/log.h>
17+
#include <zephyr/irq.h>
18+
LOG_MODULE_REGISTER(wdt_mcux_rtwdog);
19+
20+
#define MSEC_TO_RTWDOG_TICKS(clock_freq, divider, msec) \
21+
((uint32_t)(clock_freq * msec / 1000U / divider))
22+
23+
#define RTWDOG_MIN_TIMEOUT 1U
24+
25+
struct mcux_rtwdog_config {
26+
RTWDOG_Type *base;
27+
uint32_t clock_frequency;
28+
rtwdog_clock_source_t clk_source;
29+
rtwdog_clock_prescaler_t clk_divider;
30+
void (*irq_config_func)(const struct device *dev);
31+
};
32+
33+
struct mcux_rtwdog_data {
34+
wdt_callback_t callback;
35+
rtwdog_config_t wdog_config;
36+
bool timeout_valid;
37+
bool enabled;
38+
};
39+
40+
static int mcux_rtwdog_setup(const struct device *dev, uint8_t options)
41+
{
42+
const struct mcux_rtwdog_config *config = dev->config;
43+
struct mcux_rtwdog_data *data = dev->data;
44+
RTWDOG_Type *base = config->base;
45+
46+
if (!data->timeout_valid) {
47+
LOG_ERR("No valid timeouts installed");
48+
return -EINVAL;
49+
}
50+
51+
if (data->enabled) {
52+
LOG_ERR("This watchdog has been enabled");
53+
return -EBUSY;
54+
}
55+
56+
if ((options & WDT_OPT_PAUSE_IN_SLEEP) != 0U) {
57+
LOG_ERR("Not support WDT_OPT_PAUSE_IN_SLEEP");
58+
return -ENOTSUP;
59+
}
60+
61+
data->wdog_config.workMode.enableDebug = ((options & WDT_OPT_PAUSE_HALTED_BY_DBG) == 0U);
62+
63+
RTWDOG_Init(base, &data->wdog_config);
64+
data->enabled = true;
65+
LOG_DBG("Setup the watchdog");
66+
67+
return 0;
68+
}
69+
70+
static int mcux_rtwdog_disable(const struct device *dev)
71+
{
72+
const struct mcux_rtwdog_config *config = dev->config;
73+
struct mcux_rtwdog_data *data = dev->data;
74+
RTWDOG_Type *base = config->base;
75+
76+
data->timeout_valid = false;
77+
78+
if (!data->enabled) {
79+
LOG_ERR("Disabled when watchdog is not enabled");
80+
return -EFAULT;
81+
}
82+
83+
RTWDOG_Deinit(base);
84+
data->enabled = false;
85+
LOG_DBG("Disabled the watchdog");
86+
87+
return 0;
88+
}
89+
90+
static int mcux_rtwdog_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *cfg)
91+
{
92+
const struct mcux_rtwdog_config *config = dev->config;
93+
struct mcux_rtwdog_data *data = dev->data;
94+
uint32_t clock_freq;
95+
uint32_t clk_divider;
96+
97+
if (data->enabled) {
98+
LOG_ERR("Timeout can not be installed while watchdog has already been setup");
99+
return -EBUSY;
100+
}
101+
102+
if (data->timeout_valid) {
103+
LOG_ERR("No more timeouts can be installed");
104+
return -ENOMEM;
105+
}
106+
107+
if (cfg->flags == WDT_FLAG_RESET_NONE) {
108+
LOG_ERR("Not support WDT_FLAG_RESET_NONE");
109+
return -ENOTSUP;
110+
}
111+
112+
RTWDOG_GetDefaultConfig(&data->wdog_config);
113+
114+
clock_freq = config->clock_frequency;
115+
clk_divider = config->clk_divider == kRTWDOG_ClockPrescalerDivide1 ? 1U : 256U;
116+
117+
data->wdog_config.clockSource = config->clk_source;
118+
data->wdog_config.prescaler = config->clk_divider;
119+
data->wdog_config.timeoutValue =
120+
MSEC_TO_RTWDOG_TICKS(clock_freq, clk_divider, cfg->window.max);
121+
122+
if (data->wdog_config.timeoutValue > UINT16_MAX) {
123+
LOG_ERR("Invalid window max");
124+
return -EINVAL;
125+
}
126+
127+
if (cfg->window.min != 0U) {
128+
data->wdog_config.enableWindowMode = true;
129+
data->wdog_config.windowValue =
130+
MSEC_TO_RTWDOG_TICKS(clock_freq, clk_divider, cfg->window.min);
131+
} else {
132+
data->wdog_config.enableWindowMode = false;
133+
data->wdog_config.windowValue = 0;
134+
}
135+
136+
if ((data->wdog_config.timeoutValue < RTWDOG_MIN_TIMEOUT) ||
137+
(data->wdog_config.timeoutValue <= data->wdog_config.windowValue)) {
138+
LOG_ERR("Invalid timeout");
139+
return -EINVAL;
140+
}
141+
142+
data->wdog_config.enableInterrupt = cfg->callback != NULL;
143+
data->callback = cfg->callback;
144+
data->timeout_valid = true;
145+
146+
return 0;
147+
}
148+
149+
static int mcux_rtwdog_feed(const struct device *dev, int channel_id)
150+
{
151+
const struct mcux_rtwdog_config *config = dev->config;
152+
struct mcux_rtwdog_data *data = dev->data;
153+
RTWDOG_Type *base = config->base;
154+
155+
if (channel_id != 0) {
156+
LOG_ERR("Invalid channel id");
157+
return -EINVAL;
158+
}
159+
160+
if (!data->enabled) {
161+
LOG_ERR("Feed disabled watchdog");
162+
return -EINVAL;
163+
}
164+
165+
RTWDOG_Refresh(base);
166+
LOG_DBG("Fed the watchdog");
167+
168+
return 0;
169+
}
170+
171+
static void mcux_rtwdog_isr(const struct device *dev)
172+
{
173+
const struct mcux_rtwdog_config *config = dev->config;
174+
struct mcux_rtwdog_data *data = dev->data;
175+
RTWDOG_Type *base = config->base;
176+
177+
RTWDOG_ClearStatusFlags(base, kRTWDOG_InterruptFlag);
178+
179+
if (data->callback) {
180+
data->callback(dev, 0);
181+
}
182+
}
183+
184+
static int mcux_rtwdog_init(const struct device *dev)
185+
{
186+
const struct mcux_rtwdog_config *config = dev->config;
187+
188+
config->irq_config_func(dev);
189+
190+
return 0;
191+
}
192+
193+
static DEVICE_API(wdt, mcux_rtwdog_api) = {
194+
.setup = mcux_rtwdog_setup,
195+
.disable = mcux_rtwdog_disable,
196+
.install_timeout = mcux_rtwdog_install_timeout,
197+
.feed = mcux_rtwdog_feed,
198+
};
199+
200+
#define TO_RTWDOG_CLK_SRC(val) _DO_CONCAT(kRTWDOG_ClockSource, val)
201+
#define TO_RTWDOG_CLK_DIV(val) _DO_CONCAT(kRTWDOG_ClockPrescalerDivide, val)
202+
203+
#define MCUX_RTWDOG_INIT(n) \
204+
\
205+
static struct mcux_rtwdog_data mcux_rtwdog_data_##n; \
206+
static void mcux_rtwdog_config_func_##n(const struct device *dev); \
207+
\
208+
static const struct mcux_rtwdog_config mcux_rtwdog_config_##n = { \
209+
.base = (RTWDOG_Type *)DT_INST_REG_ADDR(n), \
210+
.irq_config_func = mcux_rtwdog_config_func_##n, \
211+
.clock_frequency = DT_INST_PROP_BY_PHANDLE(n, clocks, clock_frequency), \
212+
.clk_source = TO_RTWDOG_CLK_SRC(DT_INST_PROP(n, clk_source)), \
213+
.clk_divider = TO_RTWDOG_CLK_DIV(DT_INST_PROP(n, clk_divider)), \
214+
}; \
215+
static void mcux_rtwdog_config_func_##n(const struct device *dev) \
216+
{ \
217+
IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), mcux_rtwdog_isr, \
218+
DEVICE_DT_INST_GET(n), 0); \
219+
irq_enable(DT_INST_IRQN(n)); \
220+
}; \
221+
DEVICE_DT_INST_DEFINE(n, &mcux_rtwdog_init, NULL, &mcux_rtwdog_data_##n, \
222+
&mcux_rtwdog_config_##n, POST_KERNEL, \
223+
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &mcux_rtwdog_api);
224+
225+
DT_INST_FOREACH_STATUS_OKAY(MCUX_RTWDOG_INIT)

dts/arm/nxp/nxp_rt118x.dtsi

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#include <zephyr/dt-bindings/pwm/pwm.h>
1212

1313
/ {
14+
aliases {
15+
watchdog0 = &rtwdog0;
16+
};
17+
1418
cpus {
1519
#address-cells = <1>;
1620
#size-cells = <0>;
@@ -74,6 +78,12 @@
7478
compatible = "nxp,imx-ccm-rev2";
7579
reg = <0x4450000 0x4000>;
7680
#clock-cells = <3>;
81+
82+
lpo: lpo32k {
83+
compatible = "fixed-clock";
84+
clock-frequency = <32000>;
85+
#clock-cells = <0>;
86+
};
7787
};
7888

7989
lpuart1: uart@4380000 {
@@ -1070,6 +1080,56 @@
10701080
#address-cells = <1>;
10711081
#size-cells = <0>;
10721082
};
1083+
1084+
rtwdog0: wdog@42d0000 {
1085+
compatible = "nxp,rtwdog";
1086+
reg = <0x42d0000 0x10>;
1087+
status = "okay";
1088+
interrupts = <38 0>;
1089+
clocks = <&lpo>;
1090+
clk-source = <1>;
1091+
clk-divider = <1>;
1092+
};
1093+
1094+
rtwdog1: wdog@42e0000 {
1095+
compatible = "nxp,rtwdog";
1096+
reg = <0x42e0000 0x10>;
1097+
status = "disabled";
1098+
interrupts = <39 0>;
1099+
clocks = <&lpo>;
1100+
clk-source = <1>;
1101+
clk-divider = <1>;
1102+
};
1103+
1104+
rtwdog2: wdog@2490000 {
1105+
compatible = "nxp,rtwdog";
1106+
reg = <0x2490000 0x10>;
1107+
status = "disabled";
1108+
interrupts = <79 0>;
1109+
clocks = <&lpo>;
1110+
clk-source = <1>;
1111+
clk-divider = <1>;
1112+
};
1113+
1114+
rtwdog3: wdog@24a0000 {
1115+
compatible = "nxp,rtwdog";
1116+
reg = <0x24a0000 0x10>;
1117+
status = "disabled";
1118+
interrupts = <80 0>;
1119+
clocks = <&lpo>;
1120+
clk-source = <1>;
1121+
clk-divider = <1>;
1122+
};
1123+
1124+
rtwdog4: wdog@24b0000 {
1125+
compatible = "nxp,rtwdog";
1126+
reg = <0x24b0000 0x10>;
1127+
status = "disabled";
1128+
interrupts = <81 0>;
1129+
clocks = <&lpo>;
1130+
clk-source = <1>;
1131+
clk-divider = <1>;
1132+
};
10731133
};
10741134

10751135
&flexspi {

dts/bindings/watchdog/nxp,rtwdog.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright 2024, NXP
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: NXP RT watchdog
5+
6+
compatible: "nxp,rtwdog"
7+
8+
include: base.yaml
9+
10+
properties:
11+
reg:
12+
required: true
13+
14+
interrupts:
15+
required: true
16+
17+
clocks:
18+
required: true
19+
20+
clk-source:
21+
type: int
22+
required: true
23+
description: Watchdog counter clock source
24+
25+
clk-divider:
26+
type: int
27+
description: Watchdog counter clock divider
28+
required: true

0 commit comments

Comments
 (0)