Skip to content

Commit 4de1d9a

Browse files
gmarullcarlescufi
authored andcommitted
drivers: watchdog: npm6001: initial version
Driver for the watchdog embedded in the nPM6001 PMIC. Signed-off-by: Gerard Marull-Paretas <[email protected]>
1 parent eaadea5 commit 4de1d9a

File tree

5 files changed

+215
-0
lines changed

5 files changed

+215
-0
lines changed

drivers/watchdog/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_WDOG wdt_mcux_wdog.c)
1919
zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_WDOG32 wdt_mcux_wdog32.c)
2020
zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_WWDT wdt_mcux_wwdt.c)
2121
zephyr_library_sources_ifdef(CONFIG_WDT_NPCX wdt_npcx.c)
22+
zephyr_library_sources_ifdef(CONFIG_WDT_NPM6001 wdt_npm6001.c)
2223
zephyr_library_sources_ifdef(CONFIG_WDT_NRFX wdt_nrfx.c)
2324
zephyr_library_sources_ifdef(CONFIG_WDT_RPI_PICO wdt_rpi_pico.c)
2425
zephyr_library_sources_ifdef(CONFIG_WDT_SAM wdt_sam.c)

drivers/watchdog/Kconfig

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

8989
source "drivers/watchdog/Kconfig.gd32"
9090

91+
source "drivers/watchdog/Kconfig.npm6001"
92+
9193
endif

drivers/watchdog/Kconfig.npm6001

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright (c) 2022 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config WDT_NPM6001
5+
bool "nPM6001 Watchdog driver"
6+
default y
7+
depends on DT_HAS_NORDIC_NPM6001_WDT_ENABLED
8+
select I2C
9+
help
10+
Enable nPM6001 Watchdog driver
11+
12+
config WDT_NPM6001_INIT_PRIORITY
13+
int "nPM6001 Watchdog driver initialization priority"
14+
depends on WDT_NPM6001
15+
default 60
16+
help
17+
Initialization priority for the nPM6001 Watchdog driver. It must be
18+
greater than the I2C controller init priority.

drivers/watchdog/wdt_npm6001.c

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/*
2+
* Copyright (c) 2022 Nordic Semiconductor ASA
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#define DT_DRV_COMPAT nordic_npm6001_wdt
7+
8+
#include <errno.h>
9+
10+
#include <zephyr/device.h>
11+
#include <zephyr/drivers/i2c.h>
12+
#include <zephyr/drivers/watchdog.h>
13+
#include <zephyr/sys/util_macro.h>
14+
#include <zephyr/toolchain.h>
15+
16+
/* nPM6001 Watchdog related registers */
17+
#define NPM6001_WDARMEDVALUE 0x54U
18+
#define NPM6001_WDARMEDSTROBE 0x55U
19+
#define NPM6001_WDTRIGGERVALUE0 0x56U
20+
#define NPM6001_WDTRIGGERVALUE1 0x57U
21+
#define NPM6001_WDTRIGGERVALUE2 0x58U
22+
#define NPM6001_WDDATASTROBE 0x5DU
23+
#define NPM6001_WDPWRUPVALUE 0x5EU
24+
#define NPM6001_WDPWRUPSTROBE 0x5FU
25+
#define NPM6001_WDKICK 0x60U
26+
#define NPM6001_WDREQPOWERDOWN 0x62U
27+
28+
/* nPM6001 WDTRIGGERVALUEx ms/LSB, min/max values */
29+
#define NPM6001_WDTRIGGERVALUE_MS_LSB 4000U
30+
#define NPM6001_WDTRIGGERVALUE_MIN 0x2U
31+
#define NPM6001_WDTRIGGERVALUE_MAX 0xFFFFFFU
32+
33+
/* nPM6001 WDPWRUPVALUE fields */
34+
#define NPM6001_WDPWRUPVALUE_OSC_ENABLE BIT(0)
35+
#define NPM6001_WDPWRUPVALUE_COUNTER_ENABLE BIT(1)
36+
#define NPM6001_WDPWRUPVALUE_LS_ENABLE BIT(2)
37+
38+
struct wdt_npm6001_config {
39+
struct i2c_dt_spec bus;
40+
};
41+
42+
static int wdt_npm6001_setup(const struct device *dev, uint8_t options)
43+
{
44+
ARG_UNUSED(dev);
45+
ARG_UNUSED(options);
46+
47+
return 0;
48+
}
49+
50+
static int wdt_npm6001_disable(const struct device *dev)
51+
{
52+
const struct wdt_npm6001_config *config = dev->config;
53+
uint8_t buf[4] = {NPM6001_WDARMEDVALUE, 1U, NPM6001_WDARMEDSTROBE, 1U};
54+
55+
return i2c_write_dt(&config->bus, buf, sizeof(buf));
56+
}
57+
58+
static int wdt_npm6001_install_timeout(const struct device *dev,
59+
const struct wdt_timeout_cfg *timeout)
60+
{
61+
const struct wdt_npm6001_config *config = dev->config;
62+
uint32_t window;
63+
uint8_t buf[2];
64+
int ret;
65+
66+
if (timeout->window.min != 0U) {
67+
return -EINVAL;
68+
}
69+
70+
/* round-up timeout, e.g. 5s -> 8s */
71+
window = (((timeout->window.max + NPM6001_WDTRIGGERVALUE_MS_LSB - 1U) /
72+
NPM6001_WDTRIGGERVALUE_MS_LSB) +
73+
1U);
74+
if ((window < NPM6001_WDTRIGGERVALUE_MIN) ||
75+
(window > NPM6001_WDTRIGGERVALUE_MAX)) {
76+
return -EINVAL;
77+
}
78+
79+
/* enable OSC/COUNTER/LS */
80+
buf[0] = NPM6001_WDPWRUPVALUE;
81+
buf[1] = NPM6001_WDPWRUPVALUE_OSC_ENABLE |
82+
NPM6001_WDPWRUPVALUE_COUNTER_ENABLE |
83+
NPM6001_WDPWRUPVALUE_LS_ENABLE;
84+
ret = i2c_write_dt(&config->bus, buf, sizeof(buf));
85+
if (ret < 0) {
86+
return ret;
87+
}
88+
89+
buf[0] = NPM6001_WDPWRUPSTROBE;
90+
buf[1] = 1U;
91+
ret = i2c_write_dt(&config->bus, buf, sizeof(buf));
92+
if (ret < 0) {
93+
return ret;
94+
}
95+
96+
/* write trigger value */
97+
buf[0] = NPM6001_WDTRIGGERVALUE0;
98+
buf[1] = (uint8_t)window;
99+
ret = i2c_write_dt(&config->bus, buf, sizeof(buf));
100+
if (ret < 0) {
101+
return ret;
102+
}
103+
104+
buf[0] = NPM6001_WDTRIGGERVALUE1;
105+
buf[1] = (uint8_t)(window >> 8U);
106+
ret = i2c_write_dt(&config->bus, buf, sizeof(buf));
107+
if (ret < 0) {
108+
return ret;
109+
}
110+
111+
buf[0] = NPM6001_WDTRIGGERVALUE2;
112+
buf[1] = (uint8_t)(window >> 16U);
113+
ret = i2c_write_dt(&config->bus, buf, sizeof(buf));
114+
if (ret < 0) {
115+
return ret;
116+
}
117+
118+
buf[0] = NPM6001_WDDATASTROBE;
119+
buf[1] = 1U;
120+
ret = i2c_write_dt(&config->bus, buf, sizeof(buf));
121+
if (ret < 0) {
122+
return ret;
123+
}
124+
125+
/* arm watchdog & kick */
126+
buf[0] = NPM6001_WDARMEDVALUE;
127+
buf[1] = 1U;
128+
ret = i2c_write_dt(&config->bus, buf, sizeof(buf));
129+
if (ret < 0) {
130+
return ret;
131+
}
132+
133+
buf[0] = NPM6001_WDARMEDSTROBE;
134+
buf[1] = 1U;
135+
ret = i2c_write_dt(&config->bus, buf, sizeof(buf));
136+
if (ret < 0) {
137+
return ret;
138+
}
139+
140+
buf[0] = NPM6001_WDKICK;
141+
buf[1] = 1U;
142+
ret = i2c_write_dt(&config->bus, buf, sizeof(buf));
143+
if (ret < 0) {
144+
return ret;
145+
}
146+
147+
return 0;
148+
}
149+
150+
static int wdt_npm6001_feed(const struct device *dev, int channel_id)
151+
{
152+
const struct wdt_npm6001_config *config = dev->config;
153+
uint8_t buf[2] = {NPM6001_WDKICK, 1U};
154+
155+
ARG_UNUSED(channel_id);
156+
157+
return i2c_write_dt(&config->bus, buf, sizeof(buf));
158+
}
159+
160+
static const struct wdt_driver_api wdt_npm6001_api = {
161+
.setup = wdt_npm6001_setup,
162+
.disable = wdt_npm6001_disable,
163+
.install_timeout = wdt_npm6001_install_timeout,
164+
.feed = wdt_npm6001_feed,
165+
};
166+
167+
static int wdt_npm6001_init(const struct device *dev)
168+
{
169+
const struct wdt_npm6001_config *config = dev->config;
170+
171+
if (!device_is_ready(config->bus.bus)) {
172+
return -ENODEV;
173+
}
174+
175+
return 0;
176+
}
177+
178+
#define WDT_NPM6001_DEFINE(n) \
179+
static const struct wdt_npm6001_config wdt_npm6001_config##n = { \
180+
.bus = I2C_DT_SPEC_GET(DT_INST_PARENT(n)), \
181+
}; \
182+
\
183+
DEVICE_DT_INST_DEFINE(n, &wdt_npm6001_init, NULL, NULL, \
184+
&wdt_npm6001_config##n, POST_KERNEL, \
185+
CONFIG_WDT_NPM6001_INIT_PRIORITY, \
186+
&wdt_npm6001_api);
187+
188+
DT_INST_FOREACH_STATUS_OKAY(WDT_NPM6001_DEFINE)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Copyright (c) 2022 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: nPM6001 Watchdog
5+
6+
compatible: "nordic,npm6001-wdt"

0 commit comments

Comments
 (0)