wdt: dw: Extraction of common functions from the wdt_dw driver
Functions that can be used by other wdt_dw based drivers have been moved to wdt_dw_common. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
This commit is contained in:
parent
884e6b98f4
commit
1d964d8fba
|
@ -33,6 +33,6 @@ 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_TI_TPS382X wdt_ti_tps382x.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_WDT_DW wdt_dw.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_WDT_DW wdt_dw.c wdt_dw_common.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE wdt_handlers.c)
|
||||
|
|
|
@ -13,11 +13,10 @@
|
|||
#include <zephyr/math/ilog2.h>
|
||||
|
||||
#include "wdt_dw.h"
|
||||
#include "wdt_dw_common.h"
|
||||
|
||||
LOG_MODULE_REGISTER(wdt_dw, CONFIG_WDT_LOG_LEVEL);
|
||||
|
||||
#define WDT_DW_FLAG_CONFIGURED 0x80000000
|
||||
|
||||
#define WDT_IS_INST_IRQ_EN(inst) DT_NODE_HAS_PROP(DT_DRV_INST(inst), interrupts)
|
||||
#define WDT_CHECK_INTERRUPT_USED(inst) WDT_IS_INST_IRQ_EN(inst) ||
|
||||
#define WDT_DW_INTERRUPT_SUPPORT DT_INST_FOREACH_STATUS_OKAY(WDT_CHECK_INTERRUPT_USED) 0
|
||||
|
@ -44,55 +43,21 @@ static int dw_wdt_setup(const struct device *dev, uint8_t options)
|
|||
{
|
||||
const struct dw_wdt_dev_cfg *const dev_config = dev->config;
|
||||
struct dw_wdt_dev_data *const dev_data = dev->data;
|
||||
uint32_t period;
|
||||
|
||||
if (options & WDT_OPT_PAUSE_HALTED_BY_DBG) {
|
||||
LOG_ERR("Pausing watchdog by debugger is not supported.");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (options & WDT_OPT_PAUSE_IN_SLEEP) {
|
||||
LOG_ERR("Pausing watchdog in sleep is not supported.");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (!(dev_data->config & WDT_DW_FLAG_CONFIGURED)) {
|
||||
LOG_ERR("Timeout not installed.");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Configure timeout */
|
||||
period = dev_data->config & ~WDT_DW_FLAG_CONFIGURED;
|
||||
|
||||
if (dw_wdt_dual_timeout_period_get(dev_config->base)) {
|
||||
dw_wdt_timeout_period_init_set(dev_config->base, period);
|
||||
}
|
||||
|
||||
dw_wdt_timeout_period_set(dev_config->base, period);
|
||||
dw_wdt_check_options(options);
|
||||
|
||||
#if WDT_DW_INTERRUPT_SUPPORT
|
||||
/* Configure response mode */
|
||||
dw_wdt_response_mode_set(dev_config->base, !!dev_data->callback);
|
||||
#endif
|
||||
|
||||
/* Enable watchdog */
|
||||
dw_wdt_enable(dev_config->base);
|
||||
dw_wdt_counter_restart(dev_config->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_wdt_disable(const struct device *dev)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
return dw_wdt_configure(dev_config->base, dev_data->config);
|
||||
}
|
||||
|
||||
static int dw_wdt_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *config)
|
||||
{
|
||||
const struct dw_wdt_dev_cfg *const dev_config = dev->config;
|
||||
struct dw_wdt_dev_data *const dev_data = dev->data;
|
||||
uint64_t period64;
|
||||
uint32_t period;
|
||||
|
||||
#if WDT_DW_INTERRUPT_SUPPORT
|
||||
if (config->callback && !dev_config->irq_config) {
|
||||
|
@ -103,36 +68,17 @@ static int dw_wdt_install_timeout(const struct device *dev, const struct wdt_tim
|
|||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Window timeout is not supported by this driver */
|
||||
if (config->window.min) {
|
||||
LOG_ERR("Window timeout is not supported.");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (config->flags) {
|
||||
LOG_ERR("Watchdog behavior is not configurable.");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
period64 = (uint64_t)dev_config->clk_freq * config->window.max;
|
||||
period64 /= 1000;
|
||||
if (!period64 || (period64 >> 31)) {
|
||||
LOG_ERR("Window max is out of range.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
period = period64 - 1;
|
||||
period = ilog2(period);
|
||||
|
||||
if (period >= dw_wdt_cnt_width_get(dev_config->base)) {
|
||||
LOG_ERR("Watchdog timeout too long.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The minimum counter value is 64k, maximum 2G */
|
||||
dev_data->config = WDT_DW_FLAG_CONFIGURED | (period >= 15 ? period - 15 : 0);
|
||||
#ifdef WDT_DW_INTERRUPT_SUPPORT
|
||||
dev_data->callback = config->callback;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return dw_wdt_calc_period(dev_config->base, dev_config->clk_freq, config,
|
||||
&dev_data->config);
|
||||
}
|
||||
|
||||
static int dw_wdt_feed(const struct device *dev, int channel_id)
|
||||
|
@ -159,14 +105,11 @@ static const struct wdt_driver_api dw_wdt_api = {
|
|||
static int dw_wdt_init(const struct device *dev)
|
||||
{
|
||||
const struct dw_wdt_dev_cfg *const dev_config = dev->config;
|
||||
int ret;
|
||||
|
||||
/* Check component type */
|
||||
if (dw_wdt_comp_type_get(dev_config->base) != WDT_COMP_TYPE_VALUE) {
|
||||
LOG_ERR("Invalid component type %x", dw_wdt_comp_type_get(dev_config->base));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dw_wdt_reset_pulse_length_set(dev_config->base, dev_config->reset_pulse_length);
|
||||
ret = dw_wdt_probe(dev_config->base, dev_config->reset_pulse_length);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#if WDT_DW_INTERRUPT_SUPPORT
|
||||
if (dev_config->irq_config) {
|
||||
|
|
110
drivers/watchdog/wdt_dw_common.c
Normal file
110
drivers/watchdog/wdt_dw_common.c
Normal file
|
@ -0,0 +1,110 @@
|
|||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023 Intel Corporation
|
||||
*
|
||||
* Author: Adrian Warecki <adrian.warecki@intel.com>
|
||||
*/
|
||||
|
||||
#include <zephyr/drivers/watchdog.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/sys_clock.h>
|
||||
#include <zephyr/math/ilog2.h>
|
||||
|
||||
#include "wdt_dw_common.h"
|
||||
#include "wdt_dw.h"
|
||||
|
||||
LOG_MODULE_REGISTER(wdt_dw_common, CONFIG_WDT_LOG_LEVEL);
|
||||
|
||||
#define WDT_DW_FLAG_CONFIGURED 0x80000000
|
||||
|
||||
int dw_wdt_check_options(const uint8_t options)
|
||||
{
|
||||
if (options & WDT_OPT_PAUSE_HALTED_BY_DBG) {
|
||||
LOG_ERR("Pausing watchdog by debugger is not supported.");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (options & WDT_OPT_PAUSE_IN_SLEEP) {
|
||||
LOG_ERR("Pausing watchdog in sleep is not supported.");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dw_wdt_configure(const uint32_t base, const uint32_t config)
|
||||
{
|
||||
uint32_t period;
|
||||
|
||||
if (!(config & WDT_DW_FLAG_CONFIGURED)) {
|
||||
LOG_ERR("Timeout not installed.");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Configure timeout */
|
||||
period = config & ~WDT_DW_FLAG_CONFIGURED;
|
||||
|
||||
if (dw_wdt_dual_timeout_period_get(base)) {
|
||||
dw_wdt_timeout_period_init_set(base, period);
|
||||
}
|
||||
|
||||
dw_wdt_timeout_period_set(base, period);
|
||||
|
||||
/* Enable watchdog */
|
||||
dw_wdt_enable(base);
|
||||
dw_wdt_counter_restart(base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dw_wdt_calc_period(const uint32_t base, const uint32_t clk_freq,
|
||||
const struct wdt_timeout_cfg *config, uint32_t *period_out)
|
||||
{
|
||||
uint64_t period64;
|
||||
uint32_t period;
|
||||
|
||||
/* Window timeout is not supported by this driver */
|
||||
if (config->window.min) {
|
||||
LOG_ERR("Window timeout is not supported.");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
period64 = (uint64_t)clk_freq * config->window.max;
|
||||
period64 /= 1000;
|
||||
if (!period64 || (period64 >> 31)) {
|
||||
LOG_ERR("Window max is out of range.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
period = period64 - 1;
|
||||
period = ilog2(period);
|
||||
|
||||
if (period >= dw_wdt_cnt_width_get(base)) {
|
||||
LOG_ERR("Watchdog timeout too long.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The minimum counter value is 64k, maximum 2G */
|
||||
*period_out = WDT_DW_FLAG_CONFIGURED | (period >= 15 ? period - 15 : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dw_wdt_probe(const uint32_t base, const uint32_t reset_pulse_length)
|
||||
{
|
||||
/* Check component type */
|
||||
const uint32_t type = dw_wdt_comp_type_get(base);
|
||||
|
||||
if (type != WDT_COMP_TYPE_VALUE) {
|
||||
LOG_ERR("Invalid component type %x", type);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dw_wdt_reset_pulse_length_set(base, reset_pulse_length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dw_wdt_disable(const struct device *dev)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
65
drivers/watchdog/wdt_dw_common.h
Normal file
65
drivers/watchdog/wdt_dw_common.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023 Intel Corporation
|
||||
*
|
||||
* Author: Adrian Warecki <adrian.warecki@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_WATCHDOG_WDT_DW_COMMON_H_
|
||||
#define ZEPHYR_DRIVERS_WATCHDOG_WDT_DW_COMMON_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Check watchdog configuration options
|
||||
*
|
||||
* Check options value passed to a watchdog setup function. Returns error if unsupported option
|
||||
* is used.
|
||||
*
|
||||
* @param options options value passed to a watchdog setup function.
|
||||
* @return Error code, 0 on success.
|
||||
*/
|
||||
int dw_wdt_check_options(const uint8_t options);
|
||||
|
||||
/**
|
||||
* @brief Configure watchdog device
|
||||
*
|
||||
* @param base Device base address.
|
||||
* @param config device configuration word
|
||||
* @return Error code, 0 on success.
|
||||
*/
|
||||
int dw_wdt_configure(const uint32_t base, const uint32_t config);
|
||||
|
||||
/**
|
||||
* @brief Calculate period
|
||||
*
|
||||
* @param [in]base Device base address.
|
||||
* @param [in]clk_freq frequency of a clock used by watchdog device
|
||||
* @param [in]config pointer to a watchdog configuration structure
|
||||
* @param [out]period_out pointer to a variable in which the period configuration word will be
|
||||
* placed
|
||||
* @return Error code, 0 on success.
|
||||
*/
|
||||
int dw_wdt_calc_period(const uint32_t base, const uint32_t clk_freq,
|
||||
const struct wdt_timeout_cfg *config, uint32_t *period_out);
|
||||
|
||||
/**
|
||||
* @brief Watchdog probe
|
||||
*
|
||||
* Checks device id register and configure a reset pulse length.
|
||||
*
|
||||
* @param base Device base address.
|
||||
* @param reset_pulse_length Length of a reset pulse produced by watchdog
|
||||
* @return Error code, 0 on success.
|
||||
*/
|
||||
int dw_wdt_probe(const uint32_t base, const uint32_t reset_pulse_length);
|
||||
|
||||
/**
|
||||
* @brief Watchdog disable function
|
||||
*
|
||||
* @param dev Device structure.
|
||||
* @return -ENOTSUP. The hardware does not support disabling.
|
||||
*/
|
||||
int dw_wdt_disable(const struct device *dev);
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_WATCHDOG_WDT_DW_COMMON_H_ */
|
Loading…
Reference in a new issue