From 66ccc2e241ee0775ee75a7ab75746de771feddea Mon Sep 17 00:00:00 2001 From: Audun Korneliussen Date: Tue, 1 Oct 2024 15:27:28 +0200 Subject: [PATCH] drivers: watchdog: npm2100: Add driver for npm2100 pmic Add watchdog driver for npm2100 pmic. This pmic has one timer that can be used for multiple functions, including a watchdog that can reset or power-cycle connected devices. Signed-off-by: Audun Korneliussen --- drivers/watchdog/CMakeLists.txt | 1 + drivers/watchdog/Kconfig | 2 + drivers/watchdog/Kconfig.npm2100 | 19 +++ drivers/watchdog/wdt_npm2100.c | 146 ++++++++++++++++++ dts/bindings/watchdog/nordic,npm2100-wdt.yaml | 8 + .../build_all/watchdog/i2c_devices.overlay | 9 ++ 6 files changed, 185 insertions(+) create mode 100644 drivers/watchdog/Kconfig.npm2100 create mode 100644 drivers/watchdog/wdt_npm2100.c create mode 100644 dts/bindings/watchdog/nordic,npm2100-wdt.yaml diff --git a/drivers/watchdog/CMakeLists.txt b/drivers/watchdog/CMakeLists.txt index 87dc99d76e7..e2ebb95cc76 100644 --- a/drivers/watchdog/CMakeLists.txt +++ b/drivers/watchdog/CMakeLists.txt @@ -26,6 +26,7 @@ zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_WDOG32 wdt_mcux_wdog32.c) zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_WWDT wdt_mcux_wwdt.c) zephyr_library_sources_ifdef(CONFIG_WDT_NPCX wdt_npcx.c) zephyr_library_sources_ifdef(CONFIG_WDT_NPM1300 wdt_npm1300.c) +zephyr_library_sources_ifdef(CONFIG_WDT_NPM2100 wdt_npm2100.c) zephyr_library_sources_ifdef(CONFIG_WDT_NPM6001 wdt_npm6001.c) zephyr_library_sources_ifdef(CONFIG_WDT_NRFX wdt_nrfx.c) zephyr_library_sources_ifdef(CONFIG_WDT_RPI_PICO wdt_rpi_pico.c) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 95eaf31216d..36515a1f7e4 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -96,6 +96,8 @@ source "drivers/watchdog/Kconfig.gd32" source "drivers/watchdog/Kconfig.npm1300" +source "drivers/watchdog/Kconfig.npm2100" + source "drivers/watchdog/Kconfig.npm6001" source "drivers/watchdog/Kconfig.nxp_s32" diff --git a/drivers/watchdog/Kconfig.npm2100 b/drivers/watchdog/Kconfig.npm2100 new file mode 100644 index 00000000000..35f5323267d --- /dev/null +++ b/drivers/watchdog/Kconfig.npm2100 @@ -0,0 +1,19 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config WDT_NPM2100 + bool "nPM2100 Watchdog driver" + default y + depends on DT_HAS_NORDIC_NPM2100_WDT_ENABLED + select I2C + select MFD + help + Enable nPM2100 Watchdog driver + +config WDT_NPM2100_INIT_PRIORITY + int "nPM2100 Watchdog driver initialization priority" + depends on WDT_NPM2100 + default 85 + help + Initialization priority for the nPM2100 Watchdog driver. + It must be greater than GPIO_NPM2100_INIT_PRIORITY. diff --git a/drivers/watchdog/wdt_npm2100.c b/drivers/watchdog/wdt_npm2100.c new file mode 100644 index 00000000000..04531edbbe2 --- /dev/null +++ b/drivers/watchdog/wdt_npm2100.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nordic_npm2100_wdt + +#include + +#include +#include +#include +#include + +#define TIMER_TASKS_START 0xB0U +#define TIMER_TASKS_STOP 0xB1U +#define TIMER_TASKS_KICK 0xB2U +#define TIMER_CONFIG 0xB3U +#define TIMER_TARGET_HI 0xB4U +#define TIMER_TARGET_MID 0xB5U +#define TIMER_TARGET_LO 0xB6U +#define TIMER_STATUS 0xB7U +#define TIMER_BOOT_MON 0xB8U + +struct wdt_npm2100_config { + const struct device *mfd; + struct i2c_dt_spec i2c; +}; + +struct wdt_npm2100_data { + bool timeout_valid; +}; + +static int wdt_npm2100_setup(const struct device *dev, uint8_t options) +{ + const struct wdt_npm2100_config *config = dev->config; + struct wdt_npm2100_data *data = dev->data; + + if (!data->timeout_valid) { + return -EINVAL; + } + + return mfd_npm2100_start_timer(config->mfd); +} + +static int wdt_npm2100_disable(const struct device *dev) +{ + const struct wdt_npm2100_config *config = dev->config; + struct wdt_npm2100_data *data = dev->data; + int ret; + + ret = i2c_reg_write_byte_dt(&config->i2c, TIMER_TASKS_STOP, 1U); + if (ret < 0) { + return ret; + } + + data->timeout_valid = false; + + return 0; +} + +static int wdt_npm2100_install_timeout(const struct device *dev, + const struct wdt_timeout_cfg *timeout) +{ + const struct wdt_npm2100_config *config = dev->config; + struct wdt_npm2100_data *data = dev->data; + uint8_t mode; + int ret; + + if (data->timeout_valid) { + return -ENOMEM; + } + + if (timeout->window.min != 0U) { + return -EINVAL; + } + + switch (timeout->flags & WDT_FLAG_RESET_MASK) { + case WDT_FLAG_RESET_NONE: + /* Watchdog expiry causes event only, and does not reset */ + mode = NPM2100_TIMER_MODE_GENERAL_PURPOSE; + break; + case WDT_FLAG_RESET_CPU_CORE: + /* Watchdog expiry asserts reset output */ + mode = NPM2100_TIMER_MODE_WDT_RESET; + break; + case WDT_FLAG_RESET_SOC: + /* Watchdog expiry causes full power cycle */ + mode = NPM2100_TIMER_MODE_WDT_POWER_CYCLE; + break; + default: + return -EINVAL; + } + + ret = mfd_npm2100_set_timer(config->mfd, timeout->window.max, mode); + if (ret < 0) { + return ret; + } + + data->timeout_valid = true; + + return 0; +} + +static int wdt_npm2100_feed(const struct device *dev, int channel_id) +{ + const struct wdt_npm2100_config *config = dev->config; + + if (channel_id != 0) { + return -EINVAL; + } + + return i2c_reg_write_byte_dt(&config->i2c, TIMER_TASKS_KICK, 1U); +} + +static DEVICE_API(wdt, wdt_npm2100_api) = { + .setup = wdt_npm2100_setup, + .disable = wdt_npm2100_disable, + .install_timeout = wdt_npm2100_install_timeout, + .feed = wdt_npm2100_feed, +}; + +static int wdt_npm2100_init(const struct device *dev) +{ + const struct wdt_npm2100_config *config = dev->config; + + if (!i2c_is_ready_dt(&config->i2c)) { + return -ENODEV; + } + + /* Disable boot monitor */ + return wdt_npm2100_disable(dev); +} + +#define WDT_NPM2100_DEFINE(n) \ + static struct wdt_npm2100_data data##n; \ + \ + static const struct wdt_npm2100_config config##n = { \ + .mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \ + .i2c = I2C_DT_SPEC_GET(DT_INST_PARENT(n)), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, &wdt_npm2100_init, NULL, &data##n, &config##n, POST_KERNEL, \ + CONFIG_WDT_NPM2100_INIT_PRIORITY, &wdt_npm2100_api); + +DT_INST_FOREACH_STATUS_OKAY(WDT_NPM2100_DEFINE) diff --git a/dts/bindings/watchdog/nordic,npm2100-wdt.yaml b/dts/bindings/watchdog/nordic,npm2100-wdt.yaml new file mode 100644 index 00000000000..160b53abea7 --- /dev/null +++ b/dts/bindings/watchdog/nordic,npm2100-wdt.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: nPM2100 Watchdog + +compatible: "nordic,npm2100-wdt" + +include: base.yaml diff --git a/tests/drivers/build_all/watchdog/i2c_devices.overlay b/tests/drivers/build_all/watchdog/i2c_devices.overlay index c02130a3ab6..fcecf91a122 100644 --- a/tests/drivers/build_all/watchdog/i2c_devices.overlay +++ b/tests/drivers/build_all/watchdog/i2c_devices.overlay @@ -32,6 +32,15 @@ compatible = "nordic,npm6001-wdt"; }; }; + + npm2100_pmic: pmic@1 { + compatible = "nordic,npm2100"; + reg = <0x1>; + + npm2100_wdt: watchdog { + compatible = "nordic,npm2100-wdt"; + }; + }; }; }; };