599 lines
17 KiB
C
599 lines
17 KiB
C
/**
|
|
* @file sdrv_watchdog.c
|
|
* @brief Sdrv watchdog driver source.
|
|
*
|
|
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include <sdrv_watchdog.h>
|
|
#include <sdrv_ckgen.h>
|
|
#include <clock_ip.h>
|
|
#include <udelay/udelay.h>
|
|
#include <part.h>
|
|
#include "sdrv_wdt_reg.h"
|
|
|
|
#define DEFAULT_REG_POLL_RETRY 10000
|
|
|
|
/* watchdog clock source */
|
|
#define MHZ (1000 * 1000)
|
|
#define KHZ (1000)
|
|
#define WDT_MAIN_CLK (24 * MHZ)
|
|
#define WDT_LP_CLK (32 * KHZ)
|
|
|
|
static uint32_t sdrv_wdt_reg_poll(volatile uint32_t *reg, uint32_t start,
|
|
uint32_t width, uint32_t expect)
|
|
{
|
|
uint32_t retry = DEFAULT_REG_POLL_RETRY;
|
|
volatile uint32_t v = 0;
|
|
|
|
do {
|
|
v = *reg;
|
|
|
|
if (((v>>start) & ((1<<width)-1)) == expect) {
|
|
return retry;
|
|
}
|
|
} while (--retry);
|
|
|
|
return retry;
|
|
}
|
|
|
|
static void sdrv_wdt_set_refresh_mode(sdrv_wdt_t *base, sdrv_wdt_refresh_e refresh)
|
|
{
|
|
/* clear bit0-2 */
|
|
base->wrc_ctrl &= ~0x7u;
|
|
|
|
switch (refresh) {
|
|
case WDT_DIRECT_REFRESH:
|
|
base->wrc_ctrl |= (0x1u << WDT_WRC_CTRL_MODEM0);
|
|
break;
|
|
|
|
case WDT_WINDOW_REFRESH:
|
|
base->wrc_ctrl |= (0x1u << WDT_WRC_CTRL_MODEM0);
|
|
base->wrc_ctrl |= (0x1u << WDT_WRC_CTRL_MODEM1);
|
|
break;
|
|
|
|
case WDT_SEQUENCE_REFRESH:
|
|
base->wrc_ctrl |= (0x1u << WDT_WRC_CTRL_SEQ_REFR);
|
|
break;
|
|
|
|
case WDT_DIRECT_SEQUENCE_REFRESH:
|
|
base->wrc_ctrl |= (0x1u << WDT_WRC_CTRL_MODEM0);
|
|
base->wrc_ctrl |= (0x1u << WDT_WRC_CTRL_SEQ_REFR);
|
|
break;
|
|
|
|
case WDT_WINDOW_SEQUENCE_REFRESH:
|
|
base->wrc_ctrl |= (0x1u << WDT_WRC_CTRL_MODEM0);
|
|
base->wrc_ctrl |= (0x1u << WDT_WRC_CTRL_MODEM1);
|
|
base->wrc_ctrl |= (0x1u << WDT_WRC_CTRL_SEQ_REFR);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void sdrv_wdt_set_intr_enable(sdrv_wdt_t *base, sdrv_wdt_intr_e intr, bool enable)
|
|
{
|
|
uint32_t en_bit;
|
|
|
|
if (intr == WDT_ILL_WINDOW_REFRESH) {
|
|
en_bit = WDT_INT_ILL_WIN_REFE_INT_EN;
|
|
} else if (intr == WDT_ILL_SEQUENCE_RESRESH) {
|
|
en_bit = WDT_INT_ILL_SEQ_REFE_INT_EN;
|
|
} else if (intr == WDT_OVERFLOW) {
|
|
en_bit = WDT_INT_OVERFLOW_INT_EN;
|
|
}
|
|
|
|
base->intr &= ~(0x1u << en_bit);
|
|
|
|
if (enable) {
|
|
base->intr |= (0x1u << en_bit);
|
|
}
|
|
}
|
|
|
|
static void sdrv_wdt_set_internal_reset(sdrv_wdt_t *base, sdrv_wdt_internal_reset_t *int_rst)
|
|
{
|
|
base->rst_ctl = 0;
|
|
|
|
if (int_rst->reset_en) {
|
|
base->rst_ctl |= (0x1u << WDT_RST_CTRL_INT_RST_EN);
|
|
}
|
|
|
|
if (int_rst->reset_mode) {
|
|
base->rst_ctl |= (0x1u << WDT_RST_CTRL_INT_RST_MODE);
|
|
}
|
|
|
|
base->rst_ctl |= ((int_rst->reset_win & WDT_RST_CTRL_RST_WIN_MASK) << WDT_RST_CTRL_RST_WIN_LSB);
|
|
base->rst_ctl |= (int_rst->reset_cnt & WDT_RST_CTRL_RST_CNT_MASK);
|
|
|
|
if (int_rst->wdt_reset_en) {
|
|
base->rst_ctl |= (0x1u << WDT_RST_CTRL_WDT_RST_EN);
|
|
}
|
|
}
|
|
|
|
static void sdrv_wdt_set_external_reset(sdrv_wdt_t *base, sdrv_wdt_external_reset_t *ext_rst)
|
|
{
|
|
base->ext_rst_ctl = 0;
|
|
|
|
if (ext_rst->reset_en) {
|
|
base->ext_rst_ctl |= (0x1u << WDT_EXT_RST_CTRL_EXT_RST_EN);
|
|
}
|
|
|
|
if (ext_rst->reset_mode) {
|
|
base->ext_rst_ctl |= (0x1u << WDT_EXT_RST_CTRL_EXT_RST_MODE);
|
|
}
|
|
|
|
if (ext_rst->reset_pol) {
|
|
base->ext_rst_ctl |= (0x1u << WDT_EXT_RST_CTRL_EXT_RST_REQ_POL);
|
|
}
|
|
|
|
base->ext_rst_ctl |= ((ext_rst->reset_win & WDT_EXT_RST_CTRL_RST_WIN_MASK) << WDT_EXT_RST_CTRL_RST_WIN_LSB);
|
|
base->ext_rst_ctl |= (ext_rst->reset_cnt & WDT_EXT_RST_CTRL_RST_CNT_MASK);
|
|
}
|
|
|
|
static inline uint32_t sdrv_wdt_get_counter_cycle(sdrv_wdt_t *base)
|
|
{
|
|
sdrv_wdt_clock_e clk_src;
|
|
uint32_t pre_divide;
|
|
uint32_t freq;
|
|
|
|
clk_src = (sdrv_wdt_clock_e)((base->ctrl >> WDT_CTRL_CLK_SRC_LSB) & WDT_CTRL_CLK_SRC_MASK);
|
|
pre_divide = (base->ctrl >> WDT_CTRL_PRE_DIV_NUM_LSB) & WDT_CTRL_PRE_DIV_NUM_MASK;
|
|
pre_divide++;
|
|
|
|
if (clk_src == WDT_MAIN_CLOCK) {
|
|
freq = WDT_MAIN_CLK;
|
|
} else if (clk_src == WDT_LP_CLOCK) {
|
|
freq = WDT_LP_CLK;
|
|
} else if (clk_src == WDT_BUS_CLOCK) {
|
|
freq = sdrv_ckgen_bus_get_rate(CLK_NODE(g_ckgen_bus_cr5_sf), CKGEN_BUS_CLK_OUT_P);
|
|
} else {
|
|
return 0;
|
|
}
|
|
|
|
return (freq / pre_divide);
|
|
}
|
|
|
|
static uint32_t sdrv_wdt_get_counter_from_ms(sdrv_wdt_t *base, uint32_t ms)
|
|
{
|
|
uint32_t clk;
|
|
|
|
clk = sdrv_wdt_get_counter_cycle(base);
|
|
return clk ? (ms * (clk / 1000)) : 0;
|
|
}
|
|
|
|
#if (CONFIG_E3 == 1) || (CONFIG_E3L == 1) || (CONFIG_D3 == 1)
|
|
static status_t sdrv_wdt_register_init_after_lbist(sdrv_wdt_t *base)
|
|
{
|
|
base->ctrl |= (0x1u << WDT_CTRL_WDT_EN);
|
|
base->ctrl &= ~(0x1u << WDT_CTRL_DBG_HALT_EN);
|
|
base->ctrl |= (0x1u << WDT_CTRL_WDT_EN_SRC);
|
|
if (!sdrv_wdt_reg_poll(&base->ctrl, WDT_CTRL_WDT_EN_STA, 1, 1)) {
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
|
|
base->ctrl |= (0x1u << WDT_CTRL_SOFT_RST);
|
|
if (!sdrv_wdt_reg_poll(&base->ctrl, WDT_CTRL_SOFT_RST, 1, 0)) {
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
|
|
base->lock &= ~(0x1u << WDT_LOCK_EXT_RST_LOCK);
|
|
base->ext_rst_ctl &= ~(0x1u << WDT_EXT_RST_CTRL_EXT_RST_EN);
|
|
base->ext_rst_ctl &= ~(WDT_EXT_RST_CTRL_RST_WIN_MASK << WDT_EXT_RST_CTRL_RST_WIN_LSB);
|
|
base->ext_rst_ctl &= ~(0x1u << WDT_EXT_RST_CTRL_EXT_RST_MODE);
|
|
base->ext_rst_ctl = ((base->ext_rst_ctl & ~WDT_EXT_RST_CTRL_RST_CNT_MASK) | (0xffu));
|
|
|
|
base->rst_req_mon |= (0x1u << WDT_RST_REQ_MON_INT_RST_REQ_REC);
|
|
|
|
base->ctrl &= ~(0x1u << WDT_CTRL_WDT_EN);
|
|
base->ctrl |= (0x1u << WDT_CTRL_DBG_HALT_EN);
|
|
base->ctrl &= ~(0x1u << WDT_CTRL_WDT_EN_SRC);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @brief Get the default configuration for watchdog.
|
|
*
|
|
* This function get the default configuration for watchdog. When you want initialize,
|
|
* you can call this function first and modify some of them, then call sdrv_wdt_init.
|
|
*
|
|
* @param [in] config WDT config struct.
|
|
* @return SDRV_STATUS_OK represents success, SDRV_STATUS_FAIL represents failed.
|
|
*/
|
|
status_t sdrv_wdt_get_default_config(sdrv_wdt_config_t *config)
|
|
{
|
|
if (config) {
|
|
config->clk_src = WDT_MAIN_CLOCK;
|
|
config->pre_divide = 11999U;
|
|
config->wdt_en_src = 1;
|
|
config->wtc_src = 1;
|
|
config->auto_restart = 0;
|
|
config->refresh = WDT_DIRECT_REFRESH;
|
|
config->timeout = 0xFFFFFFFF;
|
|
config->window_low = 0xFFFFFFFF;
|
|
config->seq_delta = 0xFFFFFFFF;
|
|
config->intr_bitmap = WDT_OVERFLOW;
|
|
config->int_rst.reset_en = false;
|
|
config->int_rst.reset_mode = 1;
|
|
config->int_rst.reset_win = 0xF;
|
|
config->int_rst.reset_cnt = 0xFF;
|
|
config->int_rst.wdt_reset_en = false;
|
|
config->ext_rst.reset_en = false;
|
|
config->ext_rst.reset_mode = 1;
|
|
config->ext_rst.reset_pol = 0;
|
|
config->ext_rst.reset_win = 0xF;
|
|
config->ext_rst.reset_cnt = 0xFF;
|
|
}
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Initialize watchdog with config parameters.
|
|
*
|
|
* This function config watchdog with parameters in sdrv_wdt_config_t.
|
|
*
|
|
* @param [in] base WDT control base.
|
|
* @param [in] config WDT config struct.
|
|
* @return Return SDRV_STATUS_OK or error code.
|
|
*/
|
|
status_t sdrv_wdt_init(sdrv_wdt_t *base, sdrv_wdt_config_t *config)
|
|
{
|
|
base->lock = 0;
|
|
|
|
if (base->lock) {
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
|
|
#if (CONFIG_E3 == 1) || (CONFIG_E3L == 1) || (CONFIG_D3 == 1)
|
|
if (sdrv_wdt_register_init_after_lbist(base) != SDRV_STATUS_OK) {
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
#endif
|
|
|
|
if (config->clk_src == WDT_EXT_CLOCK
|
|
|| config->clk_src == WDT_TIE_OFF) {
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
|
|
/* WDT_CTRL */
|
|
base->ctrl = 0;
|
|
if (!sdrv_wdt_reg_poll(&base->ctrl, WDT_CTRL_WDT_EN_STA, 1, 0)) {
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
|
|
base->ctrl |= (0x1u << WDT_CTRL_DBG_HALT_EN);
|
|
|
|
base->ctrl |= ((config->clk_src & WDT_CTRL_CLK_SRC_MASK) << WDT_CTRL_CLK_SRC_LSB);
|
|
base->ctrl |= ((config->pre_divide & WDT_CTRL_PRE_DIV_NUM_MASK) << WDT_CTRL_PRE_DIV_NUM_LSB);
|
|
|
|
if (config->wdt_en_src) {
|
|
base->ctrl |= (0x1u << WDT_CTRL_WDT_EN_SRC);
|
|
}
|
|
|
|
if (config->wtc_src) {
|
|
base->ctrl |= (0x1u << WDT_CTRL_WTC_SRC);
|
|
}
|
|
|
|
if (config->auto_restart) {
|
|
base->ctrl |= (0x1u << WDT_CTRL_AUTO_RESTART);
|
|
}
|
|
|
|
sdrv_wdt_set_refresh_mode(base, config->refresh);
|
|
|
|
if(sdrv_wdt_clear_intr_status(base, WDT_ILL_WINDOW_REFRESH) < 0){
|
|
return SDRV_STATUS_INTR_UNCLEARED;
|
|
};
|
|
if(sdrv_wdt_clear_intr_status(base, WDT_ILL_SEQUENCE_RESRESH) < 0){
|
|
return SDRV_STATUS_INTR_UNCLEARED;
|
|
};
|
|
if(sdrv_wdt_clear_intr_status(base, WDT_OVERFLOW) < 0){
|
|
return SDRV_STATUS_INTR_UNCLEARED;
|
|
};
|
|
|
|
sdrv_wdt_set_intr_enable(base, WDT_ILL_WINDOW_REFRESH, !!(WDT_ILL_WINDOW_REFRESH & config->intr_bitmap));
|
|
sdrv_wdt_set_intr_enable(base, WDT_ILL_SEQUENCE_RESRESH, !!(WDT_ILL_SEQUENCE_RESRESH & config->intr_bitmap));
|
|
sdrv_wdt_set_intr_enable(base, WDT_OVERFLOW, !!(WDT_OVERFLOW & config->intr_bitmap));
|
|
|
|
sdrv_wdt_set_internal_reset(base, &config->int_rst);
|
|
sdrv_wdt_set_external_reset(base, &config->ext_rst);
|
|
|
|
if(sdrv_wdt_set_timeout(base, config->timeout) < 0){
|
|
return SDRV_STATUS_TIMEOUT_FAILED;
|
|
};
|
|
if(sdrv_wdt_set_window_low(base, config->window_low) < 0){
|
|
return SDRV_STATUS_WINDOW_LOW_FAILED;
|
|
};
|
|
if(sdrv_wdt_set_sequence_delta(base, config->seq_delta) < 0){
|
|
return SDRV_STATUS_DELTA_FAILED;
|
|
};
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief De-Initialize watchdog.
|
|
*
|
|
* This function disable watchdog interrupt and clear interrupt status.
|
|
* Disable internal and external reset config.
|
|
*
|
|
* @param [in] base WDT control base.
|
|
* @return SDRV_STATUS_OK represents success, SDRV_STATUS_FAIL represents failed,
|
|
* SDRV_STATUS_INTR_UNCLEARED represents interrupt not cleared.
|
|
*/
|
|
status_t sdrv_wdt_deinit(sdrv_wdt_t *base)
|
|
{
|
|
sdrv_wdt_set_intr_enable(base, WDT_ILL_WINDOW_REFRESH, false);
|
|
sdrv_wdt_set_intr_enable(base, WDT_ILL_SEQUENCE_RESRESH, false);
|
|
sdrv_wdt_set_intr_enable(base, WDT_OVERFLOW, false);
|
|
|
|
if(sdrv_wdt_clear_intr_status(base, WDT_ILL_WINDOW_REFRESH) < 0){
|
|
return SDRV_STATUS_INTR_UNCLEARED;
|
|
};
|
|
if(sdrv_wdt_clear_intr_status(base, WDT_ILL_SEQUENCE_RESRESH) < 0){
|
|
return SDRV_STATUS_INTR_UNCLEARED;
|
|
};
|
|
if(sdrv_wdt_clear_intr_status(base, WDT_OVERFLOW) < 0){
|
|
return SDRV_STATUS_INTR_UNCLEARED;
|
|
};
|
|
|
|
base->rst_ctl &= ~(0x1u << WDT_RST_CTRL_INT_RST_EN);
|
|
base->ext_rst_ctl &= ~(0x1u << WDT_EXT_RST_CTRL_EXT_RST_EN);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Enable watchdog.
|
|
*
|
|
* This function enable watchdog timer counter.
|
|
*
|
|
* @param [in] base WDT control base.
|
|
* @return SDRV_STATUS_OK represents success, SDRV_STATUS_FAIL represents failed.
|
|
*/
|
|
status_t sdrv_wdt_enable(sdrv_wdt_t *base)
|
|
{
|
|
base->ctrl |= (0x1u << WDT_CTRL_WDT_EN);
|
|
if (!sdrv_wdt_reg_poll(&base->ctrl, WDT_CTRL_WDT_EN_STA, 1, 1)) {
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
|
|
base->ctrl |= (0x1u << WDT_CTRL_SOFT_RST);
|
|
if (!sdrv_wdt_reg_poll(&base->ctrl, WDT_CTRL_SOFT_RST, 1, 0)) {
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Disable watchdog.
|
|
*
|
|
* This function disable watchdog timer counter.
|
|
*
|
|
* @param [in] base WDT control base
|
|
* @return SDRV_STATUS_OK represents success, SDRV_STATUS_FAIL represents failed.
|
|
*/
|
|
status_t sdrv_wdt_disable(sdrv_wdt_t *base)
|
|
{
|
|
base->ctrl |= (0x1u << WDT_CTRL_SOFT_RST);
|
|
if (!sdrv_wdt_reg_poll(&base->ctrl, WDT_CTRL_SOFT_RST, 1, 0)) {
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
|
|
base->ctrl &= ~(0x1u << WDT_CTRL_WDT_EN);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Set watchdog timeout value.
|
|
*
|
|
* This function get timeout value in milliseconds and convert to timer counter according
|
|
* to clock source pre-configed.
|
|
*
|
|
* @param [in] base WDT control base.
|
|
* @param [in] timeout unit: ms.
|
|
* @return SDRV_STATUS_OK represents success, SDRV_STATUS_FAIL represents failed,
|
|
* SDRV_STATUS_INVALID_PARAM represents invalid paramemt.
|
|
*/
|
|
status_t sdrv_wdt_set_timeout(sdrv_wdt_t *base, uint32_t timeout)
|
|
{
|
|
uint32_t count;
|
|
|
|
if(timeout > 0){
|
|
count = sdrv_wdt_get_counter_from_ms(base, timeout);
|
|
}
|
|
else{
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
sdrv_wdt_refresh(base);
|
|
base->wtc = 0;
|
|
base->wtc |= count;
|
|
sdrv_wdt_refresh(base);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Set watchdog time window low limit value.
|
|
*
|
|
* This function get time window low limit value in milliseconds and convert to timer
|
|
* counter according to clock source pre-configed.
|
|
*
|
|
* @param [in] base WDT control base.
|
|
* @param [in] low_limit unit: ms.
|
|
* @return SDRV_STATUS_OK represents success, SDRV_STATUS_FAIL represents failed,
|
|
* SDRV_STATUS_INVALID_PARAM represents invalid paramemt.
|
|
*/
|
|
status_t sdrv_wdt_set_window_low(sdrv_wdt_t *base, uint32_t low_limit)
|
|
{
|
|
uint32_t count;
|
|
|
|
if(low_limit > 0){
|
|
count = sdrv_wdt_get_counter_from_ms(base, low_limit);
|
|
}
|
|
else{
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
base->wrc_val = 0;
|
|
base->wrc_val |= count;
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Set watchdog sequence delta value.
|
|
*
|
|
* This function get sequence delta value in milliseconds and convert to timer
|
|
* counter according to clock source pre-configed.
|
|
*
|
|
* @param [in] base WDT control base.
|
|
* @param [in] delta unit: ms.
|
|
* @return SDRV_STATUS_OK represents success, SDRV_STATUS_FAIL represents failed,
|
|
* SDRV_STATUS_INVALID_PARAM represents invalid paramemt.
|
|
*/
|
|
status_t sdrv_wdt_set_sequence_delta(sdrv_wdt_t *base, uint32_t delta)
|
|
{
|
|
uint32_t count;
|
|
if(delta > 0){
|
|
count = sdrv_wdt_get_counter_from_ms(base, delta);
|
|
}
|
|
else{
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
base->wrc_seq = 0;
|
|
base->wrc_seq |= count;
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Feed watchdog.
|
|
*
|
|
* This function trigger watchdog do refresh.
|
|
*
|
|
* @param [in] base WDT control base.
|
|
* @return SDRV_STATUS_OK represents success, SDRV_STATUS_FAIL represents failed.
|
|
*/
|
|
status_t sdrv_wdt_refresh(sdrv_wdt_t *base)
|
|
{
|
|
base->wrc_ctrl |= (0x1u << WDT_WRC_CTRL_REFR_TRIG);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Read watchdog current counter.
|
|
*
|
|
* This function read watchdog current counter. When you enable sequence refresh, you need call
|
|
* this function first and store read value. Before time delta, use sdrv_wdt_write_timestamp with
|
|
* stored value. Otherwise, illeage sequential refresh interrupt status will set.
|
|
*
|
|
* @param [in] base WDT control base.
|
|
* @return current timer counter.
|
|
*/
|
|
uint32_t sdrv_wdt_read_timestamp(sdrv_wdt_t *base)
|
|
{
|
|
return base->cnt;
|
|
}
|
|
|
|
/**
|
|
* @brief Write watchdog counter to TSW register.
|
|
*
|
|
* This function write counter to TSW register. When config sequence base refresh,
|
|
* read timestamp first, then write read value to TSW before sequence delta.
|
|
*
|
|
* @param [in] base WDT control base.
|
|
* @param [in] timestamp last read wdt conunter.
|
|
* @return SDRV_STATUS_OK represents success, SDRV_STATUS_FAIL represents failed.
|
|
*/
|
|
status_t sdrv_wdt_write_timestamp(sdrv_wdt_t *base, uint32_t timestamp)
|
|
{
|
|
bool int_en = false;
|
|
uint32_t clk = 0;
|
|
uint32_t us = 1;
|
|
|
|
clk = sdrv_wdt_get_counter_cycle(base);
|
|
if (clk) {
|
|
us = (uint32_t)(1000000 * 6 / clk) + 1;
|
|
}
|
|
|
|
if (base->intr & (0x1U << WDT_INT_ILL_SEQ_REFE_INT_EN)) {
|
|
int_en = true;
|
|
base->intr &= ~(0x1U << WDT_INT_ILL_SEQ_REFE_INT_EN);
|
|
}
|
|
|
|
base->tsw = timestamp;
|
|
|
|
/* delay at least 6 wdt counter cycle */
|
|
udelay(us);
|
|
|
|
if (base->intr & (0x1U << WDT_INT_ILL_SEQ_REFE_INT_STA)) {
|
|
base->intr |= (0x1U << WDT_INT_ILL_SEQ_REFE_INT_CLR);
|
|
base->tsw = timestamp + 1;
|
|
}
|
|
|
|
if (int_en) {
|
|
base->intr |= (0x1U << WDT_INT_ILL_SEQ_REFE_INT_EN);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Get watchdog interrupt status of specific type.
|
|
*
|
|
* This function get specific type interrupt status.
|
|
*
|
|
* @param [in] base WDT control base.
|
|
* @param [in] intr interrupt type defined in sdrv_wdt_intr_e.
|
|
* @return true represents status is set, false represents status not set.
|
|
*/
|
|
status_t sdrv_wdt_get_intr_status(sdrv_wdt_t *base, sdrv_wdt_intr_e intr)
|
|
{
|
|
uint32_t status_bit;
|
|
|
|
if (intr == WDT_ILL_WINDOW_REFRESH) {
|
|
status_bit = WDT_INT_ILL_WIN_REFE_INT_STA;
|
|
} else if (intr == WDT_ILL_SEQUENCE_RESRESH) {
|
|
status_bit = WDT_INT_ILL_SEQ_REFE_INT_STA;
|
|
} else if (intr == WDT_OVERFLOW) {
|
|
status_bit = WDT_INT_OVERFLOW_INT_STA;
|
|
} else {
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
return (base->intr >> status_bit) & 0x1u;
|
|
}
|
|
|
|
/**
|
|
* @brief Clear watchdog interrupt status of specific type.
|
|
*
|
|
* @param [in] base WDT control base.
|
|
* @param [in] intr interrupt type defined in sdrv_wdt_intr_e.
|
|
* @return SDRV_STATUS_OK represents success, SDRV_STATUS_FAIL represents failed.
|
|
*/
|
|
status_t sdrv_wdt_clear_intr_status(sdrv_wdt_t *base, sdrv_wdt_intr_e intr)
|
|
{
|
|
uint32_t clear_bit;
|
|
|
|
if (intr == WDT_ILL_WINDOW_REFRESH) {
|
|
clear_bit = WDT_INT_ILL_WIN_REFE_INT_CLR;
|
|
} else if (intr == WDT_ILL_SEQUENCE_RESRESH) {
|
|
clear_bit = WDT_INT_ILL_SEQ_REFE_INT_CLR;
|
|
} else if (intr == WDT_OVERFLOW) {
|
|
clear_bit = WDT_INT_OVERFLOW_INT_CLR;
|
|
} else {
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
|
|
base->intr |= (0x1u << clear_bit);
|
|
|
|
return SDRV_STATUS_OK;
|
|
} |