forked from RT-Thread/rt-thread
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c95ffcc
commit 5e89260
Showing
4 changed files
with
351 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
/* | ||
* Copyright (c) 2006-2024, RT-Thread Development Team | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* Change Logs: | ||
* Date Author Notes | ||
* 2024/03/02 ShichengChu first version | ||
*/ | ||
#include <rtthread.h> | ||
#include <rtdevice.h> | ||
#include "drv_wdt.h" | ||
|
||
#ifdef BSP_USING_WDT | ||
|
||
#define DBG_LEVEL DBG_LOG | ||
#include <rtdbg.h> | ||
#define LOG_TAG "DRV.WDT" | ||
|
||
#define WDT_FREQ_DEFAULT 25000000UL | ||
#define CVI_WDT_MAX_TOP 15 | ||
|
||
struct _cvi_wdt_dev | ||
{ | ||
struct rt_watchdog_device device; | ||
const char *name; | ||
rt_uint32_t base; | ||
}; | ||
|
||
static struct _cvi_wdt_dev _wdt_dev[] = | ||
{ | ||
#ifdef BSP_USING_WDT0 | ||
{ | ||
.name = "wdt0", | ||
.base = CVI_WDT0_BASE | ||
}, | ||
#endif /* BSP_USING_WDT0 */ | ||
#ifdef BSP_USING_WDT1 | ||
{ | ||
.name = "wdt1", | ||
.base = CVI_WDT1_BASE | ||
}, | ||
#endif /* BSP_USING_WDT1 */ | ||
#ifdef BSP_USING_WDT2 | ||
{ | ||
.name = "wdt2", | ||
.base = CVI_WDT2_BASE | ||
}, | ||
#endif /* BSP_USING_WDT2 */ | ||
}; | ||
struct rt_watchdog_device wdt_device; | ||
|
||
static rt_err_t _wdt_init(rt_watchdog_t *wdt_device) | ||
{ | ||
cvi_wdt_top_setting(); | ||
|
||
return RT_EOK; | ||
} | ||
|
||
rt_inline int wdt_top_in_ms(unsigned int top) | ||
{ | ||
/* | ||
* There are 16 possible timeout values in 0..15 where the number of | ||
* cycles is 2 ^ (16 + i) and the watchdog counts down. | ||
*/ | ||
// pr_debug("wdt top in seconds: %d/%d=%d\n", (1U << (16 + top)), chip->clk_hz, (1U << (16 + top)) / chip->clk_hz); | ||
return (1U << (16 + top)) / (WDT_FREQ_DEFAULT / 1000); | ||
} | ||
|
||
static rt_err_t csi_wdt_set_timeout(unsigned long reg_base, uint32_t ms) | ||
{ | ||
rt_err_t ret = RT_EOK; | ||
int i, top_val = CVI_WDT_MAX_TOP; | ||
|
||
/* | ||
* Iterate over the timeout values until we find the closest match. We | ||
* always look for >=. | ||
*/ | ||
for (i = 0; i <= CVI_WDT_MAX_TOP; ++i) | ||
if (wdt_top_in_ms(i) >= ms) { | ||
top_val = i; | ||
break; | ||
} | ||
|
||
if (i < CVI_WDT_MAX_TOP) | ||
{ | ||
/* | ||
* Set the new value in the watchdog. Some versions of wdt_chip | ||
* have TOPINIT in the TIMEOUT_RANGE register (as per | ||
* CP_WDT_DUAL_TOP in WDT_COMP_PARAMS_1). On those we | ||
* effectively get a pat of the watchdog right here. | ||
*/ | ||
cvi_wdt_set_timeout(reg_base, top_val); | ||
cvi_wdt_start_en(reg_base); | ||
} | ||
else | ||
{ | ||
ret = -RT_ERROR; | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
|
||
static rt_err_t _wdt_control(rt_watchdog_t *wdt_device, int cmd, void *arg) | ||
{ | ||
RT_ASSERT(wdt_device != RT_NULL); | ||
|
||
struct _cvi_wdt_dev *wdt = rt_container_of(wdt_device, struct _cvi_wdt_dev, device); | ||
rt_uint32_t reg_base = wdt->base; | ||
|
||
switch (cmd) | ||
{ | ||
case RT_DEVICE_CTRL_WDT_KEEPALIVE: | ||
cvi_wdt_feed_en(reg_base); | ||
break; | ||
case RT_DEVICE_CTRL_WDT_SET_TIMEOUT: | ||
csi_wdt_set_timeout(reg_base, *(rt_uint32_t *)arg); | ||
wdt_device->parent.user_data = (rt_uint32_t)(*(rt_uint32_t *)arg); | ||
break; | ||
case RT_DEVICE_CTRL_WDT_GET_TIMEOUT: | ||
*(rt_uint32_t *)arg = (rt_uint32_t)wdt_device->parent.user_data; | ||
break; | ||
case RT_DEVICE_CTRL_WDT_GET_TIMELEFT: | ||
*(rt_uint32_t *)arg = (cvi_wdt_get_counter_value(reg_base) / (WDT_FREQ_DEFAULT / 1000U)); | ||
break; | ||
case RT_DEVICE_CTRL_WDT_START: | ||
cvi_wdt_set_respond_system_reset(reg_base); | ||
cvi_wdt_start_en(reg_base); | ||
break; | ||
case RT_DEVICE_CTRL_WDT_STOP: | ||
cvi_wdt_start_dis(reg_base); | ||
break; | ||
default: | ||
LOG_W("This command is not supported."); | ||
return -RT_EINVAL; | ||
} | ||
|
||
return RT_EOK; | ||
} | ||
|
||
static const struct rt_watchdog_ops _wdt_ops = | ||
{ | ||
.init = _wdt_init, | ||
.control = _wdt_control | ||
}; | ||
|
||
int rt_hw_wdt_init(void) | ||
{ | ||
rt_uint8_t i; | ||
for (i = 0; i < sizeof(_wdt_dev) / sizeof(_wdt_dev[0]); i ++) | ||
{ | ||
_wdt_dev[i].device.ops = &_wdt_ops; | ||
if (rt_hw_watchdog_register(&_wdt_dev[i].device, _wdt_dev[i].name, RT_DEVICE_FLAG_RDWR, RT_NULL) != RT_EOK) | ||
{ | ||
LOG_E("%s register failed!", _wdt_dev[i].name); | ||
return -RT_ERROR; | ||
} | ||
} | ||
|
||
return RT_EOK; | ||
} | ||
INIT_BOARD_EXPORT(rt_hw_wdt_init); | ||
|
||
#endif /* BSP_USING_WDT */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
/* | ||
* Copyright (c) 2006-2024, RT-Thread Development Team | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* Change Logs: | ||
* Date Author Notes | ||
* 2024/03/02 ShichengChu first version | ||
*/ | ||
#ifndef __DRV_ADC_H__ | ||
#define __DRV_ADC_H__ | ||
|
||
#include "pinctrl.h" | ||
#include "mmio.h" | ||
|
||
struct cvi_wdt_regs_t { | ||
uint32_t CR; | ||
uint32_t TORR; | ||
uint32_t CCVR; | ||
uint32_t CRR; | ||
uint32_t STAT; | ||
uint32_t EOI; | ||
}; | ||
|
||
static struct cvi_wdt_regs_t cv182x_wdt_reg = { | ||
.CR = 0x0, | ||
.TORR = 0x4, | ||
.CCVR = 0x8, | ||
.CRR = 0xc, | ||
.STAT = 0x10, | ||
.EOI = 0x14, | ||
}; | ||
|
||
static struct cvi_wdt_regs_t *cvi_wdt_reg = &cv182x_wdt_reg; | ||
|
||
#define CVI_WDT0_BASE 0x03010000 | ||
#define CVI_WDT1_BASE 0x03011000 | ||
#define CVI_WDT2_BASE 0x03012000 | ||
|
||
#define WDT_CR(reg_base) *((volatile uint32_t *)(reg_base + cvi_wdt_reg->CR)) | ||
#define WDT_TORR(reg_base) *((volatile uint32_t *)(reg_base + cvi_wdt_reg->TORR)) | ||
#define WDT_CCVR(reg_base) *((volatile const uint32_t *)(reg_base + cvi_wdt_reg->CCVR)) | ||
#define WDT_CRR(reg_base) *((volatile uint32_t *)(reg_base + cvi_wdt_reg->CRR)) | ||
#define WDT_STAT(reg_base) *((volatile const uint32_t *)(reg_base + cvi_wdt_reg->STAT)) | ||
#define WDT_EOI(reg_base) *((volatile const uint32_t *)(reg_base + cvi_wdt_reg->EOI)) | ||
|
||
#define CVI_WDT_TORR_WDT_TORR_Pos (0U) | ||
#define CVI_WDT_TORR_WDT_TORR_Msk (0xf << CVI_WDT_TORR_WDT_TORR_Pos) | ||
#define CVI_WDT_TORR_WDT_ITORR_Pos (4U) | ||
#define CVI_WDT_TORR_WDT_ITORR_Msk (0xf << CVI_WDT_TORR_WDT_ITORR_Pos) | ||
|
||
#define CVI_WDT_CR_WDT_ENABLE_Pos (0U) | ||
#define CVI_WDT_CR_WDT_ENABLE_Msk (1U << CVI_WDT_CR_WDT_ENABLE_Pos) | ||
#define CVI_WDT_CR_WDT_ENABLE_En CVI_WDT_CR_WDT_ENABLE_Msk | ||
|
||
#define CVI_WDT_CR_WDT_RESPOND_Pos (1U) | ||
#define CVI_WDT_CR_WDT_RESPOND_Msk (1U << CVI_WDT_CR_WDT_RESPOND_Pos) | ||
#define CVI_WDT_CR_WDT_RESPOND_IRQ_THEN_RST CVI_WDT_CR_WDT_RESPOND_Msk | ||
|
||
#define CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_Pos (2U) | ||
#define CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_Msk (7U << CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_Pos) | ||
#define CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_2_PCLK (0U << CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_Pos) | ||
#define CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_4_PCLK (1U << CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_Pos) | ||
#define CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_8_PCLK (2U << CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_Pos) | ||
#define CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_16_PCLK (3U << CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_Pos) | ||
#define CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_32_PCLK (4U << CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_Pos) | ||
#define CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_64_PCLK (5U << CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_Pos) | ||
#define CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_128_PCLK (6U << CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_Pos) | ||
#define CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_256_PCLK CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_Msk | ||
|
||
#define CVI_WDT_CRR_FEED_Value 0x76 | ||
#define CVI_WDT_CRR_FEED_Pos (0U) | ||
#define CVI_WDT_CRR_FEED_Msk (0xff << CVI_WDT_CRR_FEED_Pos) | ||
#define CVI_WDT_CRR_FEED_En CVI_WDT_CRR_FEED_Value | ||
|
||
#define CVI_WDT_CCVR_COUNTER_Pos (0U) | ||
#define CVI_WDT_CCVR_COUNTER_Msk (0xffffffff << CVI_WDT_CCVR_COUNTER_Pos) | ||
|
||
#define CVI_WDT_STAT_IRQ_STAT_Pos (0U) | ||
#define CVI_WDT_STAT_IRQ_STAT_Msk (1U << CVI_WDT_STAT_IRQ_STAT_Pos) | ||
|
||
#define CVI_WDT_STAT_IRQ_CLR_Pos (0U) | ||
#define CVI_WDT_STAT_IRQ_CLR_Msk (1U << CVI_WDT_STAT_IRQ_STAT_Pos) | ||
#define CVI_WDT_STAT_IRQ_CLR_En CVI_WDT_STAT_IRQ_CLR_Msk | ||
|
||
#define CV_TOP 0x03000000 | ||
#define CV_TOP_WDT_OFFSET 0x8 | ||
#define CV_TOP_WDT_VAL 0x100 | ||
#define CV_RST_REG (CV_TOP + 0x3004) | ||
#define CV_RST_WDT (1U << 16) | ||
|
||
rt_inline void cvi_wdt_top_setting() | ||
{ | ||
uint32_t val; | ||
|
||
mmio_write_32(CV_TOP + CV_TOP_WDT_OFFSET, CV_TOP_WDT_VAL); | ||
|
||
val = mmio_read_32(CV_RST_REG); | ||
mmio_write_32(CV_RST_REG, val & ~CV_RST_WDT); | ||
rt_hw_us_delay(10); | ||
mmio_write_32(CV_RST_REG, val | CV_RST_WDT); | ||
} | ||
|
||
rt_inline void cvi_wdt_start_en(unsigned long reg_base) | ||
{ | ||
WDT_CR(reg_base) |= CVI_WDT_CR_WDT_ENABLE_En; | ||
} | ||
|
||
rt_inline void cvi_wdt_start_dis(unsigned long reg_base) | ||
{ | ||
WDT_CR(reg_base) &= ~CVI_WDT_CR_WDT_ENABLE_En; | ||
} | ||
|
||
rt_inline uint32_t cvi_wdt_get_start(unsigned long reg_base) | ||
{ | ||
return (WDT_CR(reg_base) & CVI_WDT_CR_WDT_ENABLE_Msk); | ||
} | ||
|
||
rt_inline void cvi_wdt_set_timeout(unsigned long reg_base, uint32_t value) | ||
{ | ||
WDT_TORR(reg_base) &= ~CVI_WDT_TORR_WDT_TORR_Pos; | ||
WDT_TORR(reg_base) = ((value << CVI_WDT_TORR_WDT_ITORR_Pos) | (value << CVI_WDT_TORR_WDT_TORR_Pos)); | ||
} | ||
|
||
rt_inline void cvi_wdt_set_respond_system_reset(unsigned long reg_base) | ||
{ | ||
WDT_CR(reg_base) &= ~CVI_WDT_CR_WDT_RESPOND_IRQ_THEN_RST; | ||
} | ||
|
||
rt_inline void cvi_wdt_set_respond_irq_then_reset(unsigned long reg_base) | ||
{ | ||
WDT_CR(reg_base) |= CVI_WDT_CR_WDT_RESPOND_IRQ_THEN_RST; | ||
} | ||
|
||
rt_inline void cvi_wdt_set_reset_pulse_width(unsigned long reg_base, uint32_t value) | ||
{ | ||
WDT_CR(reg_base) &= ~CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_Msk; | ||
WDT_CR(reg_base) |= (value << CVI_WDT_CR_WDT_RESET_PULSE_WIDTH_Pos); | ||
} | ||
|
||
rt_inline void cvi_wdt_feed_en(unsigned long reg_base) | ||
{ | ||
WDT_CRR(reg_base) = CVI_WDT_CRR_FEED_En; | ||
} | ||
|
||
rt_inline uint32_t cvi_wdt_get_counter_value(unsigned long reg_base) | ||
{ | ||
return (WDT_CCVR(reg_base) & CVI_WDT_CCVR_COUNTER_Msk); | ||
} | ||
|
||
rt_inline uint32_t cvi_wdt_get_irq_stat(unsigned long reg_base) | ||
{ | ||
return (WDT_STAT(reg_base) & CVI_WDT_STAT_IRQ_STAT_Msk); | ||
} | ||
|
||
rt_inline void cvi_wdt_clr_irq_en(unsigned long reg_base) | ||
{ | ||
WDT_EOI(reg_base); | ||
} | ||
|
||
|
||
int rt_hw_wdt_init(void); | ||
|
||
#endif /* __DRV_ADC_H__ */ |