Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

123 lines
3.5 KiB

/*
* Copyright (c) 2024 BayLibre, SAS
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT ti_cc23x0_wdt
#include <zephyr/drivers/watchdog.h>
#include <zephyr/irq.h>
#include <soc.h>
#include <errno.h>
#include <inc/hw_ckmd.h>
#include <inc/hw_types.h>
#include <inc/hw_memmap.h>
#define LOG_LEVEL CONFIG_WDT_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(wdt_cc23x0);
#define CC23X0_WDT_UNLOCK(_base) (HWREG((_base) + CKMD_O_WDTLOCK) = 0x1ACCE551)
#define CC23X0_WDT_LOCK(_base) (HWREG((_base) + CKMD_O_WDTLOCK) = 0x1)
#define CC23X0_WDT_FEED(_base, _value) (HWREG((_base) + CKMD_O_WDTCNT) = (_value))
#define CC23X0_WDT_STALL_ENABLE(_base) (HWREG((_base) + CKMD_O_WDTTEST) = 0x1)
#define CC23X0_WDT_STALL_DISABLE(_base) (HWREG((_base) + CKMD_O_WDTTEST) = 0x0)
#define WDT_SOURCE_FREQ 32768
#define WDT_MS_RATIO (WDT_SOURCE_FREQ / 1000)
#define WDT_MAX_RELOAD_MS 0xffffffff / WDT_MS_RATIO
#define WDT_MS_TO_TICKS(_ms) ((_ms) * WDT_MS_RATIO)
struct wdt_cc23x0_data {
uint8_t enabled;
uint32_t reload;
uint8_t flags;
};
struct wdt_cc23x0_config {
uint32_t base;
};
static int wdt_cc23x0_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *cfg)
{
struct wdt_cc23x0_data *data = dev->data;
/* window watchdog not supported */
if (cfg->window.min != 0U || cfg->window.max == 0U) {
return -EINVAL;
}
if (cfg->window.max > WDT_MAX_RELOAD_MS) {
return -EINVAL;
}
data->reload = WDT_MS_TO_TICKS(cfg->window.max);
data->flags = cfg->flags;
LOG_DBG("raw reload value: %d", data->reload);
return 0;
}
static int wdt_cc23x0_setup(const struct device *dev, uint8_t options)
{
const struct wdt_cc23x0_config *config = dev->config;
/* Stall the WDT counter when halted by debugger */
if ((options & WDT_OPT_PAUSE_HALTED_BY_DBG) != 0U) {
CC23X0_WDT_STALL_ENABLE(config->base);
} else {
CC23X0_WDT_STALL_DISABLE(config->base);
}
return 0;
}
static int wdt_cc23x0_disable(const struct device *dev)
{
ARG_UNUSED(dev);
return -ENOTSUP;
}
static int wdt_cc23x0_feed(const struct device *dev, int channel_id)
{
ARG_UNUSED(channel_id);
const struct wdt_cc23x0_config *config = dev->config;
struct wdt_cc23x0_data *data = dev->data;
CC23X0_WDT_UNLOCK(config->base);
CC23X0_WDT_FEED(config->base, data->reload);
return 0;
}
static int wdt_cc23x0_init(const struct device *dev)
{
ARG_UNUSED(dev);
return 0;
}
static DEVICE_API(wdt, wdt_cc23x0_api) = {
.setup = wdt_cc23x0_setup,
.disable = wdt_cc23x0_disable,
.install_timeout = wdt_cc23x0_install_timeout,
.feed = wdt_cc23x0_feed,
};
#define CC23X0_WDT_INIT(index) \
static struct wdt_cc23x0_data wdt_cc23x0_data_##index = { \
.reload = WDT_MS_TO_TICKS(CONFIG_WDT_CC23X0_INITIAL_TIMEOUT), \
}; \
static struct wdt_cc23x0_config wdt_cc23x0_config_##index = { \
.base = DT_INST_REG_ADDR(index), \
}; \
DEVICE_DT_INST_DEFINE(index, wdt_cc23x0_init, NULL, &wdt_cc23x0_data_##index, \
&wdt_cc23x0_config_##index, POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &wdt_cc23x0_api);
DT_INST_FOREACH_STATUS_OKAY(CC23X0_WDT_INIT)