drivers: watchdog: implement Smartbond watchdog driver
This patch adds watchdog driver for Renesas Smartbond SOCs. Co-authored-by: Jerzy Kasenberg <jerzy.kasenberg@codecoup.pl> Signed-off-by: Ben Lauret <ben.lauret.wm@renesas.com>
This commit is contained in:
parent
36ac1ee2a2
commit
70c6befa88
8 changed files with 188 additions and 1 deletions
|
@ -59,6 +59,7 @@
|
|||
|
||||
aliases {
|
||||
led0 = &red_led;
|
||||
watchdog0 = &wdog;
|
||||
};
|
||||
|
||||
sysclk: system-clock {
|
||||
|
|
|
@ -10,3 +10,4 @@ toolchain:
|
|||
supported:
|
||||
- arduino_gpio
|
||||
- gpio
|
||||
- watchdog
|
||||
|
|
|
@ -29,6 +29,7 @@ zephyr_library_sources_ifdef(CONFIG_WDT_SIFIVE wdt_sifive.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_WDT_XEC wdt_mchp_xec.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_WDT_COUNTER wdt_counter.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_WDT_NXP_S32 wdt_nxp_s32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_WDT_SMARTBOND wdt_smartbond.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_WDT_DW wdt_dw.c)
|
||||
|
||||
|
|
|
@ -96,4 +96,6 @@ source "drivers/watchdog/Kconfig.nxp_s32"
|
|||
|
||||
source "drivers/watchdog/Kconfig.dw"
|
||||
|
||||
source "drivers/watchdog/Kconfig.smartbond"
|
||||
|
||||
endif # WATCHDOG
|
||||
|
|
26
drivers/watchdog/Kconfig.smartbond
Normal file
26
drivers/watchdog/Kconfig.smartbond
Normal file
|
@ -0,0 +1,26 @@
|
|||
# Smartbond watchdog driver config
|
||||
|
||||
# Copyright (c) 2022 Renesas Electronics Corporation and/or its affiliates
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config WDT_SMARTBOND
|
||||
bool "Watchdog Driver for Smartbond family of MCUs"
|
||||
default y
|
||||
depends on DT_HAS_RENESAS_SMARTBOND_WATCHDOG_ENABLED
|
||||
help
|
||||
Enable watchdog driver for Smartbond line of MCUs
|
||||
|
||||
config WDT_SMARTBOND_NMI
|
||||
bool "NMI pre-reset interrupt enable"
|
||||
default n
|
||||
depends on WDT_SMARTBOND
|
||||
select RUNTIME_NMI
|
||||
help
|
||||
Watchdog timer generates NMI at value 0, and WDOG (SYS)
|
||||
reset at <= -16. Timer can be frozen/resumed using
|
||||
SET_FREEZE_REG[FRZ_WDOG]/RESET_FREEZE_REG[FRZ_WDOG].
|
||||
When not set:
|
||||
Watchdog timer generates a WDOG (SYS)
|
||||
reset at value 0 and can not be frozen by Software.
|
||||
Note that this bit can only be set to 1 by SW and
|
||||
only be reset with a WDOG (SYS) reset or SW reset.
|
137
drivers/watchdog/wdt_smartbond.c
Normal file
137
drivers/watchdog/wdt_smartbond.c
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Renesas Electronics Corporation and/or its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <soc.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/watchdog.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_REGISTER(wdog_smartbond, CONFIG_WDT_LOG_LEVEL);
|
||||
|
||||
#define DT_DRV_COMPAT renesas_smartbond_watchdog
|
||||
|
||||
/* driver data */
|
||||
struct wdog_smartbond_data {
|
||||
/* Reload value calculated in setup */
|
||||
uint32_t reload_val;
|
||||
#ifdef CONFIG_WDT_SMARTBOND_NMI
|
||||
const struct device *wdog_device;
|
||||
wdt_callback_t callback;
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct wdog_smartbond_data wdog_smartbond_dev_data = {};
|
||||
|
||||
static int wdg_smartbond_setup(const struct device *dev, uint8_t options)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
if (options & WDT_OPT_PAUSE_IN_SLEEP) {
|
||||
LOG_ERR("Watchdog pause in sleep is not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wdg_smartbond_disable(const struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
if (SYS_WDOG->WATCHDOG_CTRL_REG & SYS_WDOG_WATCHDOG_CTRL_REG_NMI_RST_Msk) {
|
||||
/* watchdog cannot be stopped once started when NMI_RST is 1 */
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
GPREG->SET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_SYS_WDOG_Msk;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WDT_SMARTBOND_NMI
|
||||
extern void z_NmiHandlerSet(void (*pHandler)(void));
|
||||
|
||||
static void wdog_smartbond_nmi_isr(void)
|
||||
{
|
||||
if (wdog_smartbond_dev_data.callback) {
|
||||
wdog_smartbond_dev_data.callback(wdog_smartbond_dev_data.wdog_device, 0);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_RUNTIME_NMI */
|
||||
|
||||
static int wdg_smartbond_install_timeout(const struct device *dev,
|
||||
const struct wdt_timeout_cfg *config)
|
||||
{
|
||||
struct wdog_smartbond_data *data = (struct wdog_smartbond_data *)(dev)->data;
|
||||
uint32_t reload_val;
|
||||
|
||||
#ifndef CONFIG_WDT_SMARTBOND_NMI
|
||||
if (config->callback != NULL) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif
|
||||
/* For RC32K timer ticks every ~10ms, for RCX ~21ms */
|
||||
if (CRG_TOP->CLK_RCX_REG & CRG_TOP_CLK_RCX_REG_RCX_ENABLE_Msk) {
|
||||
reload_val = config->window.max / 21;
|
||||
} else {
|
||||
reload_val = config->window.max / 10;
|
||||
}
|
||||
|
||||
if (reload_val < 1 || reload_val >= 0x2000 || config->window.min != 0) {
|
||||
/* Out of range supported by watchdog */
|
||||
LOG_ERR("Watchdog timeout out of range");
|
||||
return -EINVAL;
|
||||
}
|
||||
#if CONFIG_WDT_SMARTBOND_NMI
|
||||
data->callback = config->callback;
|
||||
data->wdog_device = dev;
|
||||
z_NmiHandlerSet(wdog_smartbond_nmi_isr);
|
||||
SYS_WDOG->WATCHDOG_CTRL_REG = 2;
|
||||
#else
|
||||
SYS_WDOG->WATCHDOG_CTRL_REG = 2 | SYS_WDOG_WATCHDOG_CTRL_REG_NMI_RST_Msk;
|
||||
#endif
|
||||
|
||||
data->reload_val = reload_val;
|
||||
while (SYS_WDOG->WATCHDOG_CTRL_REG & SYS_WDOG_WATCHDOG_CTRL_REG_WRITE_BUSY_Msk) {
|
||||
/* wait */
|
||||
}
|
||||
SYS_WDOG->WATCHDOG_REG = reload_val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wdg_smartbond_feed(const struct device *dev, int channel_id)
|
||||
{
|
||||
struct wdog_smartbond_data *data = (struct wdog_smartbond_data *)(dev)->data;
|
||||
|
||||
ARG_UNUSED(channel_id);
|
||||
|
||||
while (SYS_WDOG->WATCHDOG_CTRL_REG & SYS_WDOG_WATCHDOG_CTRL_REG_WRITE_BUSY_Msk) {
|
||||
/* wait */
|
||||
}
|
||||
SYS_WDOG->WATCHDOG_REG = data->reload_val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct wdt_driver_api wdg_smartbond_api = {
|
||||
.setup = wdg_smartbond_setup,
|
||||
.disable = wdg_smartbond_disable,
|
||||
.install_timeout = wdg_smartbond_install_timeout,
|
||||
.feed = wdg_smartbond_feed,
|
||||
};
|
||||
|
||||
static int wdg_smartbond_init(const struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
#ifdef CONFIG_WDT_DISABLE_AT_BOOT
|
||||
GPREG->SET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_SYS_WDOG_Msk;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEVICE_DT_INST_DEFINE(0, wdg_smartbond_init, NULL, &wdog_smartbond_dev_data, NULL, POST_KERNEL,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &wdg_smartbond_api);
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Renesas Electronics Corporation
|
||||
* Copyright (c) 2022 Renesas Electronics Corporation and/or its affiliates
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
soc {
|
||||
sram0: memory@20000000 {
|
||||
compatible = "mmio-sram";
|
||||
|
@ -81,6 +82,12 @@
|
|||
};
|
||||
};
|
||||
|
||||
wdog: watchdog@50000700 {
|
||||
compatible = "renesas,smartbond-watchdog";
|
||||
reg = <0x50000700 0x8>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
uart: uart@50020000 {
|
||||
compatible = "renesas,smartbond-uart";
|
||||
reg = <0x50020000 0x100>;
|
||||
|
|
12
dts/bindings/watchdog/renesas,smartbond-watchdog.yaml
Normal file
12
dts/bindings/watchdog/renesas,smartbond-watchdog.yaml
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Copyright (c) 2022 Renesas Electronics Corporation and/or its affiliates
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Smartbond watchdog
|
||||
|
||||
compatible: "renesas,smartbond-watchdog"
|
||||
|
||||
include: base.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
Loading…
Add table
Add a link
Reference in a new issue