/** * @file sdrv_btm_hw.c * * Copyright (c) 2021 Semidrive Semiconductor. * All rights reserved. * * Description: semidriver btm driver. * * Revision History: * ----------------- */ #include #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)); } }