Skip to content

Commit 1537763

Browse files
Ayush1325fabiobaltieri
authored andcommitted
drivers: watchdog: Add ti rti driver
- This driver is used in k3 generation CPUs from TI. - Does not support callbacks right now. Signed-off-by: Ayush Singh <[email protected]>
1 parent a86e84b commit 1537763

File tree

4 files changed

+208
-0
lines changed

4 files changed

+208
-0
lines changed

drivers/watchdog/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,6 @@ zephyr_library_sources_ifdef(CONFIG_WDT_SHELL wdt_shell.c)
6464
zephyr_library_sources_ifdef(CONFIG_WDT_RENESAS_RA wdt_renesas_ra.c)
6565
zephyr_library_sources_ifdef(CONFIG_WDT_NXP_EWM wdt_nxp_ewm.c)
6666

67+
zephyr_library_sources_ifdef(CONFIG_WDT_TI_RTI wdt_ti_rti.c)
68+
6769
zephyr_library_sources_ifdef(CONFIG_USERSPACE wdt_handlers.c)

drivers/watchdog/Kconfig

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

160160
source "drivers/watchdog/Kconfig.xilinx_wwdt"
161161

162+
source "drivers/watchdog/Kconfig.ti_rti"
163+
162164
endif # WATCHDOG

drivers/watchdog/Kconfig.ti_rti

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright (c) 2025, Ayush Singh BeagleBoard.org Foundation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config WDT_TI_RTI
5+
bool "Watchdog Driver for TI K3"
6+
default y
7+
depends on DT_HAS_TI_J7_RTI_WDT_ENABLED
8+
select HAS_WDT_DISABLE_AT_BOOT
9+
help
10+
Enable support for K3 Watchdog timer (RTI module) available in the K3 generation of processors.

drivers/watchdog/wdt_ti_rti.c

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
* Copyright (c) 2025 Ayush Singh, BeagleBoard.org Foundation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT ti_j7_rti_wdt
8+
9+
#include <zephyr/drivers/watchdog.h>
10+
#include <zephyr/kernel.h>
11+
#include <stdint.h>
12+
13+
#define WDENABLE_KEY 0xa98559da
14+
#define WDDISABLE_KEY 0x5312aced
15+
16+
#define WDKEY_SEQ0 0xe51a
17+
#define WDKEY_SEQ1 0xa35c
18+
19+
#define WDT_PRELOAD_SHIFT 13
20+
21+
#define WDT_PRELOAD_MAX 0xfff
22+
23+
#define RTIWWDRX_NMI 0xa
24+
#define RTIWWDRX_RESET 0x5
25+
26+
#define RTIGCTRL_HALT_BY_DBG 0
27+
#define RTIGCTRL_RUN_BY_DBG BIT(15)
28+
29+
#define RTIWWDSIZE_100P 0x5
30+
#define RTIWWDSIZE_50P 0x50
31+
#define RTIWWDSIZE_25P 0x500
32+
#define RTIWWDSIZE_12P5 0x5000
33+
#define RTIWWDSIZE_6P25 0x50000
34+
#define RTIWWDSIZE_3P125 0x500000
35+
36+
#define DEV_CFG(dev) ((const struct wdt_ti_rti_config *)(dev)->config)
37+
#define DEV_DATA(dev) ((struct wdt_ti_rti_data *)(dev)->data)
38+
#define DEV_REGS(dev) ((struct wdt_ti_rti_regs *)DEVICE_MMIO_GET(dev))
39+
40+
struct wdt_ti_rti_regs {
41+
/* RTI Global Control Register, offset: 0x00 */
42+
volatile uint32_t GCTRL;
43+
uint32_t pad[35];
44+
/* Digital Watchdog Control Register, offset: 0x90 */
45+
volatile uint32_t DWDCTRL;
46+
/* Digital Watchdog Preload Register, offset: 0x94 */
47+
volatile uint32_t DWDPRLD;
48+
/* Watchdog Status Register, offset: 0x98 */
49+
volatile uint32_t WDSTATUS;
50+
/* Watchdog Key Register, offset: 0x9C */
51+
volatile uint32_t WDKEY;
52+
/* Digital Watchdog Down Counter, offset: 0xA0 */
53+
volatile uint32_t DWDCNTR;
54+
/* Digital Windowed Watchdog Reaction Control, offset: 0xA4 */
55+
volatile uint32_t WWDRXNCTRL;
56+
/* Digital Windowed Watchdog Window Size Control, offset: 0xA8 */
57+
volatile uint32_t WWDSIZECTRL;
58+
};
59+
60+
struct wdt_ti_rti_data {
61+
DEVICE_MMIO_RAM;
62+
};
63+
64+
struct wdt_ti_rti_config {
65+
DEVICE_MMIO_ROM;
66+
67+
uint64_t freq;
68+
};
69+
70+
static int wdt_ti_rti_setup(const struct device *dev, uint8_t options)
71+
{
72+
ARG_UNUSED(options);
73+
74+
struct wdt_ti_rti_regs *regs = DEV_REGS(dev);
75+
76+
if (options & WDT_OPT_PAUSE_HALTED_BY_DBG) {
77+
regs->GCTRL = RTIGCTRL_HALT_BY_DBG;
78+
} else {
79+
regs->GCTRL = RTIGCTRL_RUN_BY_DBG;
80+
}
81+
82+
regs->DWDCTRL = WDENABLE_KEY;
83+
84+
return 0;
85+
}
86+
87+
static int wdt_ti_rti_disable(const struct device *dev)
88+
{
89+
struct wdt_ti_rti_regs *regs = DEV_REGS(dev);
90+
91+
regs->DWDCTRL = WDDISABLE_KEY;
92+
regs->WDKEY = 0;
93+
94+
return 0;
95+
}
96+
97+
static int wdt_ti_rti_window_size(const struct wdt_window window)
98+
{
99+
const int window_sizes[] = {RTIWWDSIZE_100P, RTIWWDSIZE_50P, RTIWWDSIZE_25P,
100+
RTIWWDSIZE_12P5, RTIWWDSIZE_6P25, RTIWWDSIZE_3P125};
101+
102+
if (window.max < window.min || window.max == 0) {
103+
return -EINVAL;
104+
}
105+
106+
for (uint32_t idx = 0; idx < ARRAY_SIZE(window_sizes); idx++) {
107+
uint32_t temp = (window.max - window.min) << idx;
108+
109+
if (temp == window.max) {
110+
return window_sizes[idx];
111+
} else if (temp > window.max) {
112+
break;
113+
}
114+
}
115+
116+
return -EINVAL;
117+
}
118+
119+
static int wdt_ti_rti_timeout(const struct device *dev, const struct wdt_timeout_cfg *cfg)
120+
{
121+
const struct wdt_ti_rti_config *config = DEV_CFG(dev);
122+
struct wdt_ti_rti_regs *regs = DEV_REGS(dev);
123+
uint32_t timer_margin;
124+
int window_size;
125+
126+
window_size = wdt_ti_rti_window_size(cfg->window);
127+
if (window_size < 0) {
128+
return window_size;
129+
}
130+
131+
timer_margin = (cfg->window.max * config->freq) / MSEC_PER_SEC;
132+
timer_margin >>= WDT_PRELOAD_SHIFT;
133+
if (timer_margin > WDT_PRELOAD_MAX) {
134+
return -EINVAL;
135+
}
136+
137+
if (cfg->flags == WDT_FLAG_RESET_SOC) {
138+
regs->WWDRXNCTRL = RTIWWDRX_NMI;
139+
}
140+
141+
regs->DWDPRLD = timer_margin;
142+
regs->WWDSIZECTRL = (uint32_t)window_size;
143+
144+
return 0;
145+
}
146+
147+
static int wdt_ti_rti_feed(const struct device *dev, int channel_id)
148+
{
149+
struct wdt_ti_rti_regs *regs = DEV_REGS(dev);
150+
151+
if (channel_id != 0) {
152+
return -EINVAL;
153+
}
154+
155+
regs->WDKEY = WDKEY_SEQ0;
156+
regs->WDKEY = WDKEY_SEQ1;
157+
158+
return 0;
159+
}
160+
161+
static int wdt_ti_rti_init(const struct device *dev)
162+
{
163+
struct wdt_ti_rti_regs *regs;
164+
165+
DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
166+
167+
regs = DEV_REGS(dev);
168+
if (!regs) {
169+
return -EINVAL;
170+
}
171+
172+
return 0;
173+
}
174+
175+
static DEVICE_API(wdt, wdt_ti_rti_api) = {
176+
.setup = wdt_ti_rti_setup,
177+
.disable = wdt_ti_rti_disable,
178+
.feed = wdt_ti_rti_feed,
179+
.install_timeout = wdt_ti_rti_timeout,
180+
};
181+
182+
#define WDT_TI_RTI_INIT(i) \
183+
static struct wdt_ti_rti_data wdt_ti_rti_data_##i = {}; \
184+
\
185+
static struct wdt_ti_rti_config wdt_ti_rti_config_##i = { \
186+
DEVICE_MMIO_ROM_INIT(DT_DRV_INST(i)), \
187+
.freq = DT_INST_PROP(i, clock_frequency), \
188+
}; \
189+
\
190+
DEVICE_DT_INST_DEFINE(i, wdt_ti_rti_init, NULL, &wdt_ti_rti_data_##i, \
191+
&wdt_ti_rti_config_##i, POST_KERNEL, \
192+
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &wdt_ti_rti_api);
193+
194+
DT_INST_FOREACH_STATUS_OKAY(WDT_TI_RTI_INIT)

0 commit comments

Comments
 (0)