修改上传所有文件
This commit is contained in:
599
e3_176_ref/drivers/source/watchdog/sdrv_watchdog.c
Normal file
599
e3_176_ref/drivers/source/watchdog/sdrv_watchdog.c
Normal file
@@ -0,0 +1,599 @@
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
85
e3_176_ref/drivers/source/watchdog/sdrv_wdt_reg.h
Normal file
85
e3_176_ref/drivers/source/watchdog/sdrv_wdt_reg.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @file sdrv_wdt_reg.h
|
||||
* @brief Sdrv watchdog head source.
|
||||
*
|
||||
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef SDRV_TAISHAN_WDT_REG_H_
|
||||
#define SDRV_TAISHAN_WDT_REG_H_
|
||||
|
||||
#define WDT_CTRL (0x00u)
|
||||
#define WDT_CTRL_SOFT_RST (0u)
|
||||
#define WDT_CTRL_WDT_EN (1u)
|
||||
#define WDT_CTRL_CLK_SRC_LSB (2u)
|
||||
#define WDT_CTRL_CLK_SRC_MASK (0x7u)
|
||||
#define WDT_CTRL_WTC_SRC (5u)
|
||||
#define WDT_CTRL_AUTO_RESTART (6u)
|
||||
#define WDT_CTRL_DBG_HALT_EN (7u)
|
||||
#define WDT_CTRL_WDT_EN_SRC (8u)
|
||||
#define WDT_CTRL_SELFTEST_TRIG (9u)
|
||||
#define WDT_CTRL_WDT_EN_STA (10u)
|
||||
#define WDT_CTRL_PRE_DIV_NUM_LSB (16u)
|
||||
#define WDT_CTRL_PRE_DIV_NUM_MASK (0xFFFFu)
|
||||
|
||||
#define WDT_WTC (0x04u)
|
||||
#define WDT_WTC_VAL_MASK (0xFFFFFFFFu)
|
||||
|
||||
#define WDT_WRC_CTRL (0x08u)
|
||||
#define WDT_WRC_CTRL_MODEM0 (0u)
|
||||
#define WDT_WRC_CTRL_MODEM1 (1u)
|
||||
#define WDT_WRC_CTRL_SEQ_REFR (2u)
|
||||
#define WDT_WRC_CTRL_REFR_TRIG (3u)
|
||||
|
||||
#define WDT_WRC_VAL (0x0Cu)
|
||||
#define WDT_WRC_VAL_MASK (0xFFFFFFFFu)
|
||||
|
||||
#define WDT_WRC_SEQ (0x10u)
|
||||
#define WDT_WRC_SEQ_MASK (0xFFFFFFFFu)
|
||||
|
||||
#define WDT_RST_CTRL (0x14u)
|
||||
#define WDT_RST_CTRL_RST_CNT_MASK (0xFFFFu)
|
||||
#define WDT_RST_CTRL_INT_RST_EN (16u)
|
||||
#define WDT_RST_CTRL_INT_RST_MODE (17u)
|
||||
#define WDT_RST_CTRL_WDT_RST_EN (18u)
|
||||
#define WDT_RST_CTRL_RST_WIN_LSB (20u)
|
||||
#define WDT_RST_CTRL_RST_WIN_MASK (0xFFu)
|
||||
|
||||
#define WDT_EXT_RST_CTRL (0x18u)
|
||||
#define WDT_EXT_RST_CTRL_RST_CNT_MASK (0xFFFFu)
|
||||
#define WDT_EXT_RST_CTRL_EXT_RST_EN (16u)
|
||||
#define WDT_EXT_RST_CTRL_EXT_RST_MODE (17u)
|
||||
#define WDT_EXT_RST_CTRL_RST_WIN_LSB (20u)
|
||||
#define WDT_EXT_RST_CTRL_RST_WIN_MASK (0xFFu)
|
||||
#define WDT_EXT_RST_CTRL_EXT_RST_REQ_POL (28u)
|
||||
|
||||
#define WDT_CNT (0x1Cu)
|
||||
#define WDT_TWS (0x20u)
|
||||
|
||||
#define WDT_INT (0x24u)
|
||||
#define WDT_INT_ILL_WIN_REFE_INT_EN (0u)
|
||||
#define WDT_INT_ILL_SEQ_REFE_INT_EN (1u)
|
||||
#define WDT_INT_OVERFLOW_INT_EN (2u)
|
||||
#define WDT_INT_ILL_WIN_REFE_INT_STA (3u)
|
||||
#define WDT_INT_ILL_SEQ_REFE_INT_STA (4u)
|
||||
#define WDT_INT_OVERFLOW_INT_STA (5u)
|
||||
#define WDT_INT_ILL_WIN_REFE_INT_CLR (6u)
|
||||
#define WDT_INT_ILL_SEQ_REFE_INT_CLR (7u)
|
||||
#define WDT_INT_OVERFLOW_INT_CLR (8u)
|
||||
|
||||
#define WDT_RST_REQ_MON (0x28u)
|
||||
#define WDT_RST_REQ_MON_INT_RST_REQ_MON (0u)
|
||||
#define WDT_RST_REQ_MON_INT_RST_REQ_REC (2u)
|
||||
|
||||
#define WDT_LOCK (0x40u)
|
||||
#define WDT_LOCK_CTL_LOCK (0u)
|
||||
#define WDT_LOCK_WTC_LOCK (1u)
|
||||
#define WDT_LOCK_WRC_LOCK (2u)
|
||||
#define WDT_LOCK_RST_LOCK (3u)
|
||||
#define WDT_LOCK_EXT_RST_LOCK (4u)
|
||||
#define WDT_LOCK_INT_LOCK (5u)
|
||||
#define WDT_LOCK_CLK_SRC_LOCK (6u)
|
||||
|
||||
|
||||
#endif /* SDRV_TAISHAN_WDT_REG_H_ */
|
||||
Reference in New Issue
Block a user