Files
E3_boot/drivers/source/btm/sdrv_btm_hw.c
2025-11-07 10:05:24 +08:00

446 lines
13 KiB
C

/**
* @file sdrv_btm_hw.c
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description: semidriver btm driver.
*
* Revision History:
* -----------------
*/
#include <types.h>
#include "reg.h"
#include "sdrv_btm.h"
/**
* @brief sdrv btm read reg.
*
* @param[in] base reg base
* @param[in] offset reg offset
* @param[in] return reg val
*/
static inline uint32_t sdrv_btm_hw_readl(uint32_t base, uint32_t offset)
{
return readl(base + offset);
}
/**
* @brief sdrv btm write reg.
*
* @param[in] base reg base
* @param[in] offset reg offset
* @param[in] val reg val
*/
static inline void sdrv_btm_hw_writel(uint32_t base, uint32_t offset, uint32_t val)
{
writel(val, (base + offset));
}
/**
* @brief sdrv btm set ovf cnt.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
* @param[in] ovf_cnt ovf cnt value
*/
void sdrv_btm_hw_set_ovf_cnt(uint32_t base, uint8_t tmr_id, uint32_t ovf_cnt)
{
sdrv_btm_hw_writel(base, BTM_CNT_OVF_OFF(tmr_id), ovf_cnt);
if (SDRV_BTM_G1 == tmr_id) {
sdrv_btm_hw_writel(base, BTM_CNT_G1_UPD_FLAG_OFF, BTM_BM_CNT_G1_UPD_FLAG_OVF_WR_UPD);
}
}
/**
* @brief sdrv btm set cmp val.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
* @param[in] cmp_val cnt cmp value
*/
void sdrv_btm_hw_set_cmp_val(uint32_t base, uint8_t tmr_id, uint32_t cmp_val)
{
sdrv_btm_hw_writel(base, BTM_CNT_CMP_OFF(tmr_id), cmp_val);
if (SDRV_BTM_G1 == tmr_id) {
sdrv_btm_hw_writel(base, BTM_CNT_G1_UPD_FLAG_OFF, BTM_BM_CNT_G1_UPD_FLAG_CMP_WR_UPD);
}
}
/**
* @brief sdrv btm cnt start.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
* @param[in] enable check if enable
*/
void sdrv_btm_hw_cnt_en(uint32_t base, uint8_t tmr_id, bool enable)
{
uint32_t cnt_en;
cnt_en = sdrv_btm_hw_readl(base, BTM_CNT_EN_OFF(tmr_id));
if (enable) {
cnt_en |= BTM_BM_CNT_EN_ENABLE;
}
else {
cnt_en &= ~BTM_BM_CNT_EN_ENABLE;
}
sdrv_btm_hw_writel(base, BTM_CNT_EN_OFF(tmr_id), cnt_en);
}
/**
* @brief sdrv btm cnt stop.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
* @param[in] stop check if stop
*/
void sdrv_btm_hw_cnt_stop(uint32_t base, uint8_t tmr_id, bool stop)
{
uint32_t cnt_en;
cnt_en = sdrv_btm_hw_readl(base, BTM_CNT_EN_OFF(tmr_id));
if (stop) {
cnt_en |= BTM_BM_CNT_EN_STOP;
}
else {
cnt_en &= ~BTM_BM_CNT_EN_STOP;
}
sdrv_btm_hw_writel(base, BTM_CNT_EN_OFF(tmr_id), cnt_en);
}
void sdrv_btm_hw_frc_rld(uint32_t base, uint8_t tmr_id)
{
/*force reload disable*/
uint32_t cnt_cfg_val;
cnt_cfg_val = sdrv_btm_hw_readl(base, BTM_CNT_CFG_OFF(tmr_id));
cnt_cfg_val |= BTM_BM_CNT_CFG_FRC_RLD_EN;
sdrv_btm_hw_writel(base, BTM_CNT_CFG_OFF(tmr_id), cnt_cfg_val);
}
void sdrv_btm_hw_sw_rst(uint32_t base, uint8_t tmr_id)
{
uint32_t cnt_cfg_val;
cnt_cfg_val = sdrv_btm_hw_readl(base, BTM_CNT_CFG_OFF(tmr_id));
cnt_cfg_val |= BTM_BM_CNT_CFG_SOFT_RST;
sdrv_btm_hw_writel(base, BTM_CNT_CFG_OFF(tmr_id), cnt_cfg_val);
}
/**
* @brief sdrv btm cnt cfg.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
* @param[in] cnt_cfg counter cfg
*/
void sdrv_btm_hw_cnt_cfg(uint32_t base, uint8_t tmr_id, const sdrv_btm_hw_cnt_cfg_t *cnt_cfg)
{
uint32_t cnt_cfg_val;
cnt_cfg_val = sdrv_btm_hw_readl(base, BTM_CNT_CFG_OFF(tmr_id));
cnt_cfg_val &= ~(BTM_BM_CNT_CFG_CNT_MODE | BTM_BM_CNT_CFG_CNT_DIR | BTM_BM_CNT_CFG_CMP_USE_MODE |
BTM_BM_CNT_CFG_CMP_USE_MODE |
BTM_BM_CNT_CFG_TERM_USE_MODE | BTM_BM_CNT_CFG_FRC_RLD_RST_CNT_EN | BTM_FM_CNT_CFG_INC_VAL |
BTM_FM_CNT_CFG_SI_VAL);
cnt_cfg_val |= ((cnt_cfg->cnt_mode << 0) | (cnt_cfg->cnt_dir << 1) | (cnt_cfg->cmp_use_mode << 2) |
(cnt_cfg->term_use_mode << 3));
if (cnt_cfg->frc_rld_rst_cnt_en) {
cnt_cfg_val |= BTM_BM_CNT_CFG_FRC_RLD_RST_CNT_EN;
}
else {
cnt_cfg_val &= ~BTM_BM_CNT_CFG_FRC_RLD_RST_CNT_EN;
}
cnt_cfg_val |= BTM_FV_CNT_CFG_INC_VAL(cnt_cfg->inc_val);
cnt_cfg_val |= BTM_FV_CNT_CFG_SI_VAL(cnt_cfg->si_val);
sdrv_btm_hw_writel(base, BTM_CNT_CFG_OFF(tmr_id), cnt_cfg_val);
if (SDRV_BTM_G1 == tmr_id) {
uint32_t g1_upd_flag = BTM_BM_CNT_G1_UPD_FLAG_INC_WR_UPD | BTM_BM_CNT_G1_UPD_FLAG_SI_WR_UPD;
sdrv_btm_hw_writel(base, BTM_CNT_G1_UPD_FLAG_OFF, g1_upd_flag);
}
}
/**
* @brief sdrv btm cnt hold mode.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
* @param[in] stop check if stop
*/
void sdrv_btm_hw_set_hold_mode(uint32_t base, uint8_t tmr_id, sdrv_btm_cnt_hold_mode_e hold_mode)
{
uint32_t com_ctrl;
com_ctrl = sdrv_btm_hw_readl(base, BTM_COM_CTRL_OFF);
if (SDRV_BTM_G0 == tmr_id) {
com_ctrl &= ~BTM_FM_COM_CTRL_HOLD_CAP_CFG_G0;
com_ctrl |= BTM_FV_COM_CTRL_HOLD_CAP_CFG_G0(hold_mode);
}
else if (SDRV_BTM_G1 == tmr_id) {
com_ctrl &= ~BTM_FM_COM_CTRL_HOLD_CAP_CFG_G1;
com_ctrl |= BTM_FV_COM_CTRL_HOLD_CAP_CFG_G1(hold_mode);
}
sdrv_btm_hw_writel(base, BTM_COM_CTRL_OFF, com_ctrl);
}
/**
* @brief sdrv btm cnt hold mode.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
* @param[in] stop check if stop
*/
void sdrv_btm_hw_set_g1_sync_mode(uint32_t base, const sdrv_btm_hw_g1_sync_t *sync_cfg)
{
uint32_t com_ctrl;
com_ctrl = sdrv_btm_hw_readl(base, BTM_COM_CTRL_OFF);
com_ctrl &= ~(BTM_BM_COM_CTRL_START_SYNC | BTM_BM_COM_CTRL_FRC_RLD_SYNC |
BTM_BM_COM_CTRL_STOP_SYNC);
if (sync_cfg->start_sync) {
com_ctrl |= BTM_BM_COM_CTRL_START_SYNC;
}
if (sync_cfg->frc_rld_sync) {
com_ctrl |= BTM_BM_COM_CTRL_FRC_RLD_SYNC;
}
if (sync_cfg->stop_sync) {
com_ctrl |= BTM_BM_COM_CTRL_STOP_SYNC;
}
sdrv_btm_hw_writel(base, BTM_COM_CTRL_OFF, com_ctrl);
}
/**
* @brief sdrv btm cnt int sta en.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
*/
void sdrv_btm_hw_set_sta_en(uint32_t base, uint8_t tmr_id)
{
uint32_t int_sta_en;
int_sta_en = sdrv_btm_hw_readl(base, BTM_INT_STAT_EN_OFF);
if (SDRV_BTM_G0 == tmr_id) {
int_sta_en |= BTM_BM_INT_STAT_EN_CE_G0 | BTM_BM_INT_STAT_EN_OE_G0;
}
else if (SDRV_BTM_G1 == tmr_id) {
int_sta_en |= BTM_BM_INT_STAT_EN_CE_G1 | BTM_BM_INT_STAT_EN_OE_G1;
}
sdrv_btm_hw_writel(base, BTM_INT_STAT_EN_OFF, int_sta_en);
}
/**
* @brief sdrv btm cnt int sig en.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
*/
void sdrv_btm_hw_set_sig_en(uint32_t base, uint8_t tmr_id)
{
uint32_t int_sig_en;
int_sig_en = sdrv_btm_hw_readl(base, BTM_INT_SIG_EN_OFF);
if (SDRV_BTM_G0 == tmr_id) {
int_sig_en |= BTM_BM_INT_SIG_EN_OE_G0 | BTM_BM_INT_SIG_EN_CE_G0;
}
else if (SDRV_BTM_G1 == tmr_id) {
int_sig_en |= BTM_BM_INT_SIG_EN_OE_G1 | BTM_BM_INT_SIG_EN_CE_G1;
}
sdrv_btm_hw_writel(base, BTM_INT_SIG_EN_OFF, int_sig_en);
}
/**
* @brief sdrv btm compare int control.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
* @param[in] enable true/false
*/
void sdrv_btm_hw_compare_int_en(uint32_t base, uint8_t tmr_id, bool enable)
{
uint32_t sig_en, stat_en;
sig_en = sdrv_btm_hw_readl(base, BTM_INT_SIG_EN_OFF);
stat_en = sdrv_btm_hw_readl(base, BTM_INT_STAT_EN_OFF);
if (SDRV_BTM_G0 == tmr_id) {
if (enable) {
sig_en |= BTM_BM_INT_SIG_EN_CE_G0;
stat_en |= BTM_BM_INT_STAT_EN_CE_G0;
}
else {
sig_en &= ~ BTM_BM_INT_SIG_EN_CE_G0;
stat_en &= ~ BTM_BM_INT_STAT_EN_CE_G0;
}
}
else if (SDRV_BTM_G1 == tmr_id) {
if (enable) {
sig_en |= BTM_BM_INT_SIG_EN_CE_G1;
stat_en |= BTM_BM_INT_STAT_EN_CE_G1;
}
else {
sig_en &= ~ BTM_BM_INT_SIG_EN_CE_G1;
stat_en &= ~ BTM_BM_INT_STAT_EN_CE_G1;
}
}
sdrv_btm_hw_writel(base, BTM_INT_SIG_EN_OFF, sig_en);
sdrv_btm_hw_writel(base, BTM_INT_STAT_EN_OFF, stat_en);
}
/**
* @brief sdrv btm set int sta.
*
* @param[in] tmr dev base
* @param[in] int_sta sta
*/
void sdrv_btm_hw_set_int_sta(uint32_t base, uint32_t int_sta)
{
sdrv_btm_hw_writel(base, BTM_INT_STAT_OFF, int_sta);
}
/**
* @brief sdrv btm get int sta.
*
* @param[in] tmr dev base
* @return int sta
*/
uint32_t sdrv_btm_hw_get_int_sta(uint32_t base)
{
return sdrv_btm_hw_readl(base, BTM_INT_STAT_OFF);
}
/**
* @brief sdrv btm get cnt val.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
* @return counter value
*/
uint32_t sdrv_btm_hw_get_cnt_val(uint32_t base, uint8_t tmr_id)
{
return sdrv_btm_hw_readl(base, BTM_CNT_OFF(tmr_id));
}
/**
* @brief sdrv btm get hold val.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
* @return hold value
*/
uint32_t sdrv_btm_hw_get_hold_val(uint32_t base, uint8_t tmr_id)
{
return sdrv_btm_hw_readl(base, BTM_HOLD_OFF(tmr_id));
}
/**
* @brief sdrv btm cnt init.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
* @param[in] cnt_cfg counter cfg
*/
void sdrv_btm_hw_init(uint32_t base, uint8_t tmr_id, const sdrv_btm_hw_cnt_cfg_t *cnt_cfg)
{
/* disable the cnt */
sdrv_btm_hw_cnt_en(base, tmr_id, false);
/* reset the cnt value */
sdrv_btm_hw_sw_rst(base, tmr_id);
uint32_t int_sta_en = sdrv_btm_hw_readl(base, BTM_INT_STAT_EN_OFF);
uint32_t int_sig_en = sdrv_btm_hw_readl(base, BTM_INT_SIG_EN_OFF);
if (SDRV_BTM_G0 == tmr_id) {
/* clear all interrupt value */
int_sta_en &= ~BTM_BM_INT_STAT_EN_OE_G0;
int_sta_en &= ~BTM_BM_INT_STAT_EN_CE_G0;
int_sig_en &= ~BTM_BM_INT_SIG_EN_CE_G0;
int_sig_en &= ~BTM_BM_INT_SIG_EN_OE_G0;
sdrv_btm_hw_writel(base, BTM_INT_STAT_EN_OFF, int_sta_en);
sdrv_btm_hw_writel(base, BTM_INT_SIG_EN_OFF, int_sig_en);
sdrv_btm_hw_writel(base, BTM_INT_STAT_OFF, (BTM_BM_INT_STAT_CE_G0 | BTM_BM_INT_STAT_OE_G0));
}
else {
/* clear all interrupt value */
int_sta_en &= ~BTM_BM_INT_STAT_EN_OE_G1;
int_sta_en &= ~BTM_BM_INT_STAT_EN_CE_G1;
int_sig_en &= ~BTM_BM_INT_SIG_EN_CE_G1;
int_sig_en &= ~BTM_BM_INT_SIG_EN_OE_G1;
sdrv_btm_hw_writel(base, BTM_INT_STAT_EN_OFF, int_sta_en);
sdrv_btm_hw_writel(base, BTM_INT_SIG_EN_OFF, int_sig_en);
sdrv_btm_hw_writel(base, BTM_INT_STAT_OFF, (BTM_BM_INT_STAT_CE_G1 | BTM_BM_INT_STAT_OE_G1));
}
/* set the cnt cfg */
sdrv_btm_hw_cnt_cfg(base, tmr_id, cnt_cfg);
}
/**
* @brief sdrv btm timer start.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
* @param[in] cnt_cfg counter value
*/
void sdrv_btm_hw_timer_start(uint32_t base, uint8_t tmr_id, uint32_t count)
{
/* set interrupt mask */
sdrv_btm_hw_set_sta_en(base, tmr_id);
sdrv_btm_hw_set_sig_en(base, tmr_id);
/* set ovf value */
sdrv_btm_hw_set_ovf_cnt(base, tmr_id, count);
/* enable the cnt */
sdrv_btm_hw_cnt_en(base, tmr_id, true);
}
/**
* @brief sdrv btm timer stop.
*
* @param[in] tmr dev base
* @param[in] tmr_id tmr id
* @param[in] cnt_cfg counter value
*/
void sdrv_btm_hw_timer_stop(uint32_t base, uint8_t tmr_id)
{
/* disable the cnt */
sdrv_btm_hw_cnt_en(base, tmr_id, false);
/* clear all interrupt value */
uint32_t int_sta_en = sdrv_btm_hw_readl(base, BTM_INT_STAT_EN_OFF);
uint32_t int_sig_en = sdrv_btm_hw_readl(base, BTM_INT_SIG_EN_OFF);
if (SDRV_BTM_G0 == tmr_id) {
/* clear all interrupt value */
int_sta_en &= ~BTM_BM_INT_STAT_EN_OE_G0;
int_sta_en &= ~BTM_BM_INT_STAT_EN_CE_G0;
int_sig_en &= ~BTM_BM_INT_SIG_EN_CE_G0;
int_sig_en &= ~BTM_BM_INT_SIG_EN_OE_G0;
sdrv_btm_hw_writel(base, BTM_INT_STAT_EN_OFF, int_sta_en);
sdrv_btm_hw_writel(base, BTM_INT_SIG_EN_OFF, int_sig_en);
sdrv_btm_hw_writel(base, BTM_INT_STAT_OFF, (BTM_BM_INT_STAT_CE_G0 | BTM_BM_INT_STAT_OE_G0));
}
else {
/* clear all interrupt value */
int_sta_en &= ~BTM_BM_INT_STAT_EN_OE_G1;
int_sta_en &= ~BTM_BM_INT_STAT_EN_CE_G1;
int_sig_en &= ~BTM_BM_INT_SIG_EN_CE_G1;
int_sig_en &= ~BTM_BM_INT_SIG_EN_OE_G1;
sdrv_btm_hw_writel(base, BTM_INT_STAT_EN_OFF, int_sta_en);
sdrv_btm_hw_writel(base, BTM_INT_SIG_EN_OFF, int_sig_en);
sdrv_btm_hw_writel(base, BTM_INT_STAT_OFF, (BTM_BM_INT_STAT_CE_G1 | BTM_BM_INT_STAT_OE_G1));
}
}