zephyr/drivers/watchdog/wdt_nxp_s32.c

209 lines
5.2 KiB
C

/*
* Copyright 2022 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/watchdog.h>
#include <zephyr/irq.h>
#include <Swt_Ip.h>
#include <Swt_Ip_Irq.h>
#define LOG_LEVEL CONFIG_WDT_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(swt_nxp_s32);
#define PARAM_UNUSED 0
struct swt_nxp_s32_config {
uint32_t clock_freq;
uint8_t instance;
};
struct swt_nxp_s32_data {
Swt_Ip_ConfigType swt_config;
wdt_callback_t callback;
bool timeout_valid;
};
static int swt_nxp_s32_setup(const struct device *dev, uint8_t options)
{
const struct swt_nxp_s32_config *config = dev->config;
struct swt_nxp_s32_data *data = dev->data;
Swt_Ip_StatusType status;
if (!data->timeout_valid) {
LOG_ERR("No valid timeouts installed");
return -EINVAL;
}
data->swt_config.bEnRunInStopMode =
(options & WDT_OPT_PAUSE_IN_SLEEP) == 0U;
data->swt_config.bEnRunInDebugMode =
(options & WDT_OPT_PAUSE_HALTED_BY_DBG) == 0U;
status = Swt_Ip_Init(config->instance, &data->swt_config);
if (status != SWT_IP_STATUS_SUCCESS) {
LOG_ERR("Setting up watchdog failed");
return -EIO;
}
return 0;
}
static int swt_nxp_s32_disable(const struct device *dev)
{
const struct swt_nxp_s32_config *config = dev->config;
struct swt_nxp_s32_data *data = dev->data;
Swt_Ip_StatusType status;
status = Swt_Ip_Deinit(config->instance);
if (status != SWT_IP_STATUS_SUCCESS) {
LOG_ERR("Disabling watchdog failed");
return -EIO;
}
data->timeout_valid = false;
return 0;
}
static int swt_nxp_s32_install_timeout(const struct device *dev,
const struct wdt_timeout_cfg *cfg)
{
const struct swt_nxp_s32_config *config = dev->config;
struct swt_nxp_s32_data *data = dev->data;
if (data->timeout_valid) {
LOG_ERR("No more timeouts can be installed");
return -ENOMEM;
}
data->swt_config.u32TimeoutValue = config->clock_freq / 1000U * cfg->window.max;
if (cfg->window.min) {
data->swt_config.bEnWindow = true;
data->swt_config.u32WindowValue =
config->clock_freq / 1000U * (cfg->window.max - cfg->window.min);
} else {
data->swt_config.bEnWindow = false;
data->swt_config.u32WindowValue = 0;
}
if ((data->swt_config.u32TimeoutValue < SWT_MIN_VALUE_TIMEOUT_U32) ||
(data->swt_config.u32TimeoutValue < data->swt_config.u32WindowValue)) {
LOG_ERR("Invalid timeout");
return -EINVAL;
}
data->swt_config.bEnInterrupt = cfg->callback != NULL;
data->callback = cfg->callback;
data->timeout_valid = true;
LOG_DBG("Installed timeout (timeoutValue = %d)",
data->swt_config.u32TimeoutValue);
return 0;
}
static int swt_nxp_s32_feed(const struct device *dev, int channel_id)
{
ARG_UNUSED(channel_id);
const struct swt_nxp_s32_config *config = dev->config;
Swt_Ip_Service(config->instance);
LOG_DBG("Fed the watchdog");
return 0;
}
static const struct wdt_driver_api swt_nxp_s32_driver_api = {
.setup = swt_nxp_s32_setup,
.disable = swt_nxp_s32_disable,
.install_timeout = swt_nxp_s32_install_timeout,
.feed = swt_nxp_s32_feed,
};
#define SWT_NODE(n) DT_NODELABEL(swt##n)
#define RTU0_SWT_OFFSET_IDX 2
#define RTU1_SWT_OFFSET_IDX 7
#define RTU_SWT(n) \
COND_CODE_1(CONFIG_NXP_S32_RTU_INDEX, (RTU1_SWT_OFFSET_IDX + n), \
(RTU0_SWT_OFFSET_IDX + n))
#define SWT_NXP_S32_CALLBACK(n) \
void swt_nxp_s32_##n##_callback(void) \
{ \
const struct device *dev = DEVICE_DT_GET(SWT_NODE(n)); \
struct swt_nxp_s32_data *data = dev->data; \
\
if (data->callback) { \
data->callback(dev, PARAM_UNUSED); \
} \
}
#define SWT_NXP_S32_DEVICE_INIT(n) \
SWT_NXP_S32_CALLBACK(n) \
static struct swt_nxp_s32_data swt_nxp_s32_data_##n = { \
.swt_config = { \
.u8MapEnBitmask = SWT_IP_ALL_MAP_DISABLE | \
SWT_IP_MAP0_ENABLE | SWT_IP_MAP1_ENABLE | \
SWT_IP_MAP2_ENABLE | SWT_IP_MAP3_ENABLE | \
SWT_IP_MAP4_ENABLE | SWT_IP_MAP5_ENABLE | \
SWT_IP_MAP6_ENABLE | SWT_IP_MAP7_ENABLE, \
.bEnResetOnInvalidAccess = TRUE, \
.eServiceMode = FALSE, \
.u16InitialKey = 0, \
.lockConfig = SWT_IP_UNLOCK, \
.pfSwtCallback = &swt_nxp_s32_##n##_callback, \
}, \
}; \
static const struct swt_nxp_s32_config swt_nxp_s32_config_##n = { \
.clock_freq = DT_PROP(SWT_NODE(n), clock_frequency), \
.instance = (uint8_t)(RTU_SWT(n)), \
}; \
\
static int swt_nxp_s32_##n##_init(const struct device *dev) \
{ \
IRQ_CONNECT(DT_IRQN(SWT_NODE(n)), \
DT_IRQ(SWT_NODE(n), priority), \
Swt_Ip_IrqHandler, \
(uint8_t)(RTU_SWT(n)), \
DT_IRQ(SWT_NODE(n), flags)); \
irq_enable(DT_IRQN(SWT_NODE(n))); \
\
return 0; \
} \
\
DEVICE_DT_DEFINE(SWT_NODE(n), \
swt_nxp_s32_##n##_init, \
NULL, \
&swt_nxp_s32_data_##n, \
&swt_nxp_s32_config_##n, \
POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
&swt_nxp_s32_driver_api);
#if DT_NODE_HAS_STATUS(SWT_NODE(0), okay)
SWT_NXP_S32_DEVICE_INIT(0)
#endif
#if DT_NODE_HAS_STATUS(SWT_NODE(1), okay)
SWT_NXP_S32_DEVICE_INIT(1)
#endif
#if DT_NODE_HAS_STATUS(SWT_NODE(2), okay)
SWT_NXP_S32_DEVICE_INIT(2)
#endif
#if DT_NODE_HAS_STATUS(SWT_NODE(3), okay)
SWT_NXP_S32_DEVICE_INIT(3)
#endif
#if DT_NODE_HAS_STATUS(SWT_NODE(4), okay)
SWT_NXP_S32_DEVICE_INIT(4)
#endif