新增所有文件

This commit is contained in:
2025-10-25 21:11:06 +08:00
parent 8cc4755d15
commit 3134504178
8414 changed files with 2995287 additions and 5 deletions

View File

@@ -0,0 +1,757 @@
/**
* @file sdrv_acmp.c
* @brief semidrive acmp driver
*
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#include <types.h>
#include <bits.h>
#include <debug.h>
#include <string.h>
#include <reg.h>
#include <irq.h>
#include <udelay/udelay.h>
#include "sdrv_acmp.h"
/* Define the register offsets of acmp component */
#define ACMP_MAX_CSEL_NUM 4
#define ACMP_MAX_INDEX_NUM 32
#define ACMP_INIT_POLLs 200000
#define ACMP_SOFT (0x00)
#define ACMP_SOFT_RST (0)
#define ACMP_SOFT_RC_TMR_RST (1)
#define ACMP_MODE (0x04)
#define ACMP_IT_MODE_CFG (0x08)
#define ACMP_IT_MODE_CFG_TG_START (0)
#define ACMP_IT_MODE_CFG_QSTART (8)
#define ACMP_IT_MODE_CFG_QEND (16)
#define ACMP_IT_MODE_CFG_CUR_ENTRY_PT (24)
#define ACMP_TIMER (0x0C)
#define ACMP_TIMER_COMPARE_VAL (0)
#define ACMP_TIMER_TERMINAL_VAL (16)
#define ACMP_CFG_INDEX(n) (0x10 + n * 4)
#define ACMP_CFG_INDEX_AMSEL (0)
#define ACMP_CFG_INDEX_CSEL (12)
#define ACMP_CFG_INDEX_IE (16)
#define ACMP_CFG_INDEX_UIE (17)
#define ACMP_ANA_CFG(n) (0x90 + n * 4)
#define ACMP_ANA_CFG_REFSEL (0)
#define ACMP_ANA_CFG_SDSEL (1)
#define ACMP_ANA_CFG_HCFG (4)
#define ACMP_ANA_CFG_DAIN (8)
#define ACMP_CTRL_CFG(n) (0xA0 + n * 4)
#define ACMP_CTRL_CFG_AMUX_SETUP (0)
#define ACMP_CTRL_CFG_PROP_DLY (8)
#define ACMP_CTRL_CFG_RBW (16)
#define ACMP_CTRL_CFG_FBW (20)
#define ACMP_CTRL_CFG_SAMPLE_EN (24)
#define ACMP_CTRL_CFG_MASK_EN (25)
#define ACMP_CTRL_CFG_POL_ADJ (26)
#define ACMP_CTRL_CFG_SYNC_EN (27)
#define ACMP_IRQ (0xB0)
#define ACMP_IRQ_UNCOR (0xB4)
#define ANA_EXT_MUX_ERR (0xB8)
#define ANA_EXT_MUX_ERR_STATUS (0)
#define ANA_EXT_MUX_ERR_SIG_EN (16)
#define ACMP_PD_CTRL (0xBC)
#define ACMP_PD_CTRL_CMP (0)
#define ACMP_PD_CTRL_DAC (1)
#define ACMP_PD_CTRL_Q_CH_CMP (8)
#define ACMP_PD_CTRL_Q_CH_DAC (9)
#define ACMP_INIT (0xC0)
#define ACMP_INIT_CNT_THRD (0)
#define ACMP_INIT_DONE (16)
#define ACMP_LOW_POWER (0xC4)
#define ACMP_SCH (0xC8)
#define ACMP_SCH_ACMP_EN (0)
#define ACMP_SCH_ANA_INSEL_ON (1)
#define REG_PARITY_ERR_INT_STAT (0xD0)
#define REG_PARITY_ERR_INT_STAT_EN (0xD4)
#define REG_PARITY_ERR_INT_SIG_EN (0xD8)
#define FUSA_COR_ERR_INT_STAT (0xE0)
#define FUSA_COR_ERR_INT_STAT_EN (0xE4)
#define FUSA_COR_ERR_INT_SIG_EN (0xE8)
#define FUSA_UNCOR_ERR_INT_STAT (0xF0)
#define FUSA_UNCOR_ERR_INT_STAT_PWDATA_UNCOR_ERR (0)
#define FUSA_UNCOR_ERR_INT_STAT_PWDATA_DATAL_ERR (1)
#define FUSA_UNCOR_ERR_INT_STAT_PADDR_UNCOR_ERR (2)
#define FUSA_UNCOR_ERR_INT_STAT_PCTL_UNCOR_ERR (3)
#define FUSA_UNCOR_ERR_INT_STAT_INPUT_ERR (4)
#define FUSA_UNCOR_ERR_INT_STAT_EN (0xF4)
#define FUSA_UNCOR_ERR_INT_STAT_EN_PWDATA_UNCOR_ERR (0)
#define FUSA_UNCOR_ERR_INT_STAT_EN_PWDATA_DATAL_ERR (1)
#define FUSA_UNCOR_ERR_INT_STAT_EN_PADDR_UNCOR_ERR (2)
#define FUSA_UNCOR_ERR_INT_STAT_EN_PCTL_UNCOR_ERR (3)
#define FUSA_UNCOR_ERR_INT_STAT_EN_INPUT_ERR (4)
#define FUSA_UNCOR_ERR_INT_SIG_EN (0xF8)
#define FUSA_UNCOR_ERR_INT_SIG_EN_PWDATA_UNCOR_ERR (0)
#define FUSA_UNCOR_ERR_INT_SIG_EN_PWDATA_DATAL_ERR (1)
#define FUSA_UNCOR_ERR_INT_SIG_EN_PADDR_UNCOR_ERR (2)
#define FUSA_UNCOR_ERR_INT_SIG_EN_PCTL_UNCOR_ERR (3)
#define FUSA_UNCOR_ERR_INT_SIG_EN_INPUT_ERR (4)
#define PWDATA_INJ (0x100)
#define PWECC_INJ (0x104)
#define SELFTEST_MODE (0x108)
#define PRDATAINJ (0x10C)
#define INT_ERR_INJ (0x110)
#define INT_ERR_INJ_IE_ERR (0)
#define INT_ERR_INJ_COR_ERR (1)
#define INT_ERR_INJ_UNC_ERR (2)
/**
* @brief sdrv acmp soft reset
*
* @param[in] base sdrv acmp address
*/
static void sdrv_acmp_soft_reset(paddr_t base)
{
RMWREG32(base + ACMP_SOFT, ACMP_SOFT_RST, 1, 1);
RMWREG32(base + ACMP_SOFT, ACMP_SOFT_RST, 1, 0);
}
/**
* @brief sdrv acmp config mode.
*
* @param[in] base sdrv acmp address
* @param[in] mode sdrv acmp mode
*/
static void sdrv_acmp_config_mode(paddr_t base, sdrv_acmp_mode_t mode)
{
writel(mode, base + ACMP_MODE);
}
/**
* @brief sdrv acmp get mode.
*
* @param[in] base sdrv acmp address
* @param[in] mode sdrv acmp mode
*/
static sdrv_acmp_mode_t sdrv_acmp_get_mode(paddr_t base)
{
return (sdrv_acmp_mode_t)(readl(base + ACMP_MODE) & 0x1U);
}
/**
* @brief sdrv acmp config it mode.
*
* @param[in] base sdrv acmp address
* @param[in] qstart sdrv acmp trigger start id number for loop
* @param[in] qend sdrv acmp trigger end id number for loop
* @param[in] cur_entry_pt sdrv acmp trigger first access id number
* @return SDRV_STATUS_OK represents success or other error code
*/
static status_t sdrv_acmp_config_it_mode(paddr_t base, uint8_t qstart,
uint8_t qend, uint8_t cur_entry_pt)
{
if ((qstart <= cur_entry_pt) && (cur_entry_pt <= qend)) {
RMWREG32(base + ACMP_IT_MODE_CFG, ACMP_IT_MODE_CFG_QSTART, 5, qstart & 0x1F);
RMWREG32(base + ACMP_IT_MODE_CFG, ACMP_IT_MODE_CFG_QEND, 5, qend & 0x1F);
RMWREG32(base + ACMP_IT_MODE_CFG, ACMP_IT_MODE_CFG_CUR_ENTRY_PT, 5,
cur_entry_pt & 0x1F);
return SDRV_STATUS_OK;
}
else {
return SDRV_ACMP_STATUS_INVALID_PARAM;
}
}
/**
* @brief sdrv acmp get it mode config.
*
* @param[in] base sdrv acmp address
* @param[in] qstart sdrv acmp trigger start id number for loop
* @param[in] qend sdrv acmp trigger end id number for loop
* @param[in] cur_entry_pt sdrv acmp trigger first access id number
*/
static void sdrv_acmp_get_it_mode_config(paddr_t base, uint8_t *qstart,
uint8_t *qend, uint8_t *cur_entry_pt)
{
uint32_t it_cfg = readl(base + ACMP_IT_MODE_CFG);
*qstart = (it_cfg >> ACMP_IT_MODE_CFG_QSTART) & 0x1F;
*qend = (it_cfg >> ACMP_IT_MODE_CFG_QEND) & 0x1F;
*cur_entry_pt = (it_cfg >> ACMP_IT_MODE_CFG_CUR_ENTRY_PT) & 0x1F;
}
/**
* @brief sdrv acmp config timer.
*
* @param[in] base sdrv acmp address
* @param[in] compare_val acmp timer compare value
* @param[in] terminal_val acmp timer terminal value
* @return SDRV_STATUS_OK represents success or other error code
*/
static status_t sdrv_acmp_config_timer(paddr_t base, uint16_t compare_val,
uint16_t terminal_val)
{
RMWREG32(base + ACMP_TIMER, ACMP_TIMER_COMPARE_VAL, 16, compare_val & 0xFFFF);
if (terminal_val > compare_val) {
RMWREG32(base + ACMP_TIMER, ACMP_TIMER_TERMINAL_VAL, 16, terminal_val & 0xFFFF);
}
else {
return SDRV_ACMP_STATUS_INVALID_PARAM;
}
return SDRV_STATUS_OK;
}
/**
* @brief sdrv acmp start it generate.
*
* @param[in] base sdrv acmp address
* @param[in] trigger_start acmp it generate start
*/
static void sdrv_acmp_it_gen_start(paddr_t base, bool trigger_start)
{
RMWREG32(base + ACMP_IT_MODE_CFG, ACMP_IT_MODE_CFG_TG_START, 1, trigger_start);
}
/**
* @brief sdrv acmp config csel
*
* @param[in] base sdrv acmp address
* @param[in] csel_cfg sdrv acmp csel cfg
*/
static void sdrv_acmp_config_csel(paddr_t base, sdrv_acmp_csel_cfg_t *csel_cfg)
{
uint32_t val = 0;
/* acmp ctrl cfg*/
val = (csel_cfg->sync_en << ACMP_CTRL_CFG_SYNC_EN) |
(csel_cfg->pol_adj << ACMP_CTRL_CFG_POL_ADJ) |
(csel_cfg->mask_en << ACMP_CTRL_CFG_MASK_EN) |
(csel_cfg->sample_en << ACMP_CTRL_CFG_SAMPLE_EN) |
(csel_cfg->fbw << ACMP_CTRL_CFG_FBW) |
(csel_cfg->rbw << ACMP_CTRL_CFG_RBW) |
(csel_cfg->prop_delay << ACMP_CTRL_CFG_PROP_DLY) |
(csel_cfg->amux_setup << ACMP_CTRL_CFG_AMUX_SETUP);
writel(val, base + ACMP_CTRL_CFG(csel_cfg->csel_idx));
/* acmp ana cfg*/
val = (csel_cfg->dain << ACMP_ANA_CFG_DAIN) |
(csel_cfg->hcfg << ACMP_ANA_CFG_HCFG) |
(csel_cfg->sdsel << ACMP_ANA_CFG_SDSEL) |
(csel_cfg->refsel << ACMP_ANA_CFG_REFSEL);
writel(val, base + ACMP_ANA_CFG(csel_cfg->csel_idx));
}
/**
* @brief sdrv acmp config index
*
* @param[in] base sdrv acmp address
* @param[in] index_cfg sdrv acmp index cfg
*/
static void sdrv_acmp_config_index(paddr_t base,
sdrv_acmp_index_cfg_t *index_cfg)
{
uint32_t val = 0;
val = (index_cfg->uie << ACMP_CFG_INDEX_UIE) |
(index_cfg->ie << ACMP_CFG_INDEX_IE) |
(index_cfg->csel << ACMP_CFG_INDEX_CSEL) |
(index_cfg->amsel << ACMP_CFG_INDEX_AMSEL);
writel(val, base + ACMP_CFG_INDEX(index_cfg->idx));
}
/**
* @brief sdrv acmp get irq state.
*
* @param[in] base sdrv acmp address
* @return irq status
*/
static uint32_t sdrv_acmp_get_irq_state(paddr_t base)
{
return readl(base + ACMP_IRQ);
}
/**
* @brief sdrv acmp clear irq.
*
* @param[in] base sdrv acmp address
* @param[in] state irq state
*/
static void sdrv_acmp_clear_irq(paddr_t base, uint32_t state)
{
writel(state, base + ACMP_IRQ);
}
/**
* @brief sdrv acmp get irq status.
*
* @param[in] base sdrv acmp address
* @return init done
*/
static bool sdrv_acmp_lld_get_init_done(paddr_t base)
{
return ((readl(base + ACMP_INIT) >> ACMP_INIT_DONE) & 0x1);
}
/**
* @brief sdrv acmp set low power req_n delay num.
*
* @param[in] base sdrv acmp address
* @param[in] req_n_dly req_n delay number
*/
static void sdrv_acmp_set_low_power(paddr_t base, uint8_t req_n_dly)
{
writel(req_n_dly & 0xFFFF, base + ACMP_LOW_POWER);
}
/**
* @brief sdrv acmp dac recieve q channel low power requset.
*
* @param[in] base sdrv acmp address
* @param[in] enable cmp recieve q channel low power requset
*/
static void sdrv_acmp_rcv_qch_cmp(paddr_t base, bool enable)
{
RMWREG32(base + ACMP_PD_CTRL, ACMP_PD_CTRL_CMP, 1, enable);
}
/**
* @brief sdrv acmp comperitor recieve q channel low power requset.
*
* @param[in] base sdrv acmp address
* @param[in] enable dac recieve q channel low power requset
*/
static void sdrv_acmp_rcv_qch_dac(paddr_t base, bool enable)
{
RMWREG32(base + ACMP_PD_CTRL, ACMP_PD_CTRL_DAC, 1, enable);
}
/**
* @brief sdrv acmp irq handler
*
* @param[in] irq irq number
* @param[in] arg irq arg
* return irq handler result
*/
static int sdrv_acmp_irq_handler(uint32_t irq, void *arg)
{
sdrv_acmp_t *dev = arg;
uint32_t irq_state;
int ret = 0;
ASSERT(dev);
irq_state = sdrv_acmp_get_irq_state(dev->base);
if (irq_state) {
if (dev->callback) {
ret = dev->callback(dev, irq_state);
}
sdrv_acmp_clear_irq(dev->base, irq_state);
}
return ret;
}
/**
* @brief sdrv acmp init
*
* This function initializes acmp device and attach callback function.
*
* @param[in] dev sdrv acmp device
* @param[in] cfg sdrv acmp configuration parameters
* @param[in] callback sdrv acmp callback function
* @return SDRV_STATUS_OK represents success or other error code
*/
status_t sdrv_acmp_init(sdrv_acmp_t *dev, sdrv_acmp_config_t *cfg,
sdrv_acmp_callback callback)
{
status_t ret;
uint32_t i = 0;
uint32_t tms = 0;
if (cfg->base == 0) {
return SDRV_ACMP_STATUS_INVALID_PARAM;
}
dev->base = cfg->base;
dev->irq = cfg->irq;
dev->callback = callback;
#if (CONFIG_E3 || CONFIG_D3)
if (IS_P0) {
/* close ADC self-test to avoid disturbing the ACMP reference voltage */
#if APB_ADC1_BASE
writel(0xFFFF, APB_ADC1_BASE + 0x244);
#endif
#if APB_ADC2_BASE
writel(0xFFFF, APB_ADC2_BASE + 0x244);
#endif
#if APB_ADC3_BASE
writel(0xFFFF, APB_ADC3_BASE + 0x244);
#endif
}
#endif
/* soft reset */
sdrv_acmp_soft_reset(dev->base);
/* wait init done */
while (!sdrv_acmp_lld_get_init_done(dev->base)) {
if (tms++ > ACMP_INIT_POLLs) {
return SDRV_STATUS_TIMEOUT;
}
}
/* config mode */
sdrv_acmp_config_mode(dev->base, cfg->mode);
if (cfg->mode == ACMP_IT_MODE) {
ret = sdrv_acmp_config_it_mode(dev->base, cfg->qstart, cfg->qend,
cfg->cur_entry_pt);
if (ret != SDRV_STATUS_OK) {
return ret;
}
ret = sdrv_acmp_config_timer(dev->base, cfg->timer_compare_val,
cfg->timer_terminal_val);
if (ret != SDRV_STATUS_OK) {
return ret;
}
}
/* config csel */
if ((cfg->csel_num > 0) && (cfg->csel_num <= ACMP_MAX_CSEL_NUM)) {
for (i = 0; i < cfg->csel_num; i++) {
sdrv_acmp_config_csel(dev->base, &cfg->csel_cfg[i]);
}
}
else {
return SDRV_ACMP_STATUS_INVALID_PARAM;
}
/* config index */
if ((cfg->index_num > 0) && (cfg->index_num <= ACMP_MAX_INDEX_NUM)) {
for (i = 0; i < cfg->index_num; i++) {
sdrv_acmp_config_index(dev->base, &cfg->index_cfg[i]);
}
}
else {
return SDRV_ACMP_STATUS_INVALID_PARAM;
}
/* set low power req_n delay */
if (cfg->req_n_dly > 0) {
sdrv_acmp_set_low_power(dev->base, cfg->req_n_dly);
}
/* competitor recv q channel low power request */
sdrv_acmp_rcv_qch_cmp(dev->base, cfg->qch_cmp_en);
/* dac recv q channel low power request */
sdrv_acmp_rcv_qch_dac(dev->base, cfg->qch_dac_en);
/* start it generate */
if (cfg->mode == ACMP_IT_MODE) {
sdrv_acmp_it_gen_start(dev->base, true);
}
else {
sdrv_acmp_it_gen_start(dev->base, false);
}
if (dev->irq > 0) {
irq_attach(dev->irq, sdrv_acmp_irq_handler, dev);
irq_enable(dev->irq);
}
else {
return SDRV_ACMP_STATUS_INVALID_PARAM;
}
return SDRV_STATUS_OK;
}
/**
* @brief sdrv acmp start
*
* This function is used to start or stop acmp comparation.
* All the parameters are remained when acmp stop, and the previous comparation will restart when acmp start.
*
* @param[in] dev sdrv acmp dev
* @param[in] start sdrv acmp start
* @return SDRV_STATUS_OK represents success
*/
status_t sdrv_acmp_start(sdrv_acmp_t *dev, bool start)
{
if (dev->base == 0) {
return SDRV_ACMP_STATUS_INVALID_PARAM;
}
RMWREG32(dev->base + ACMP_SCH, ACMP_SCH_ANA_INSEL_ON, 1, 0);
RMWREG32(dev->base + ACMP_SCH, ACMP_SCH_ACMP_EN, 1, start);
return SDRV_STATUS_OK;
}
/**
* @brief sdrv acmp IT mode trigger start
*
* This function is used to stop or restart trigger with differnet id numbers in IT mode.
* The new comparation will use the same comparation parameters with the former comparation.
* If the parameters need to be modified, acmp should be stopped and reinitialized.
*
* @param[in] dev sdrv acmp device
* @param[in] qstart sdrv acmp trigger start id number for loop
* @param[in] qend sdrv acmp trigger end id number for loop
* @param[in] cur_entry_pt sdrv acmp trigger first access id number
* @param[in] trigger_start acmp IT mode trigger start
* @return SDRV_STATUS_OK represents success
*/
status_t sdrv_acmp_it_trigger_start(sdrv_acmp_t *dev, uint8_t qstart, uint8_t qend, uint8_t cur_entry_pt,
bool trigger_start)
{
if (dev->base == 0) {
return SDRV_ACMP_STATUS_INVALID_PARAM;
}
/* check ACMP_IT_MODE */
if (sdrv_acmp_get_mode(dev->base) == ACMP_HT_MODE) {
return SDRV_ACMP_STATUS_WRONG_MODE;
}
/* trigger stop */
sdrv_acmp_it_gen_start(dev->base, false);
/* trigger restart */
if (trigger_start) {
sdrv_acmp_config_it_mode(dev->base, qstart, qend, cur_entry_pt);
sdrv_acmp_it_gen_start(dev->base, trigger_start);
}
return SDRV_STATUS_OK;
}
/**
* @brief sdrv acmp IT mode update valid irq state
*
* This function is used to workaround for multiple trigger if interrupt is required in IT mode.
* Occurrence scenario:
* Only appers in multiple triggers of IT mode using interrupt, but this is not a problem
* if not changing the configuration(index and analog config) at next trigger.
* At the end of each trigger, if acmp voltage comparision result is pulled up one clock cycle
* before next trigger, the interrupt generated by this trigger will update to the register ID
* of the next trigger. Other functions of ACMP are not affected.
*
* How to use this function:
* Call the function at beginning of acmp callback function.
*
* @param[in] dev sdrv acmp device
* @param[in] state sdrv acmp irq state
* @param[in] wait_time check irq valid wait time (unit: μs)
* the period should be a little longer than terminal time.
* @return SDRV_STATUS_OK represents success
*/
status_t sdrv_acmp_it_update_valid_irq(sdrv_acmp_t *dev, uint32_t *state, uint32_t wait_time)
{
uint8_t save_qstart = 0;
uint8_t save_qend = 0;
uint8_t save_cur_entry_pt = 0;
uint8_t irq_bit = 0;
if (dev->base == 0) {
return SDRV_ACMP_STATUS_INVALID_PARAM;
}
/* check ACMP_IT_MODE */
if (sdrv_acmp_get_mode(dev->base) == ACMP_HT_MODE) {
return SDRV_ACMP_STATUS_WRONG_MODE;
}
/* save IT mode qstart/qend/cur_entry_pt */
sdrv_acmp_get_it_mode_config(dev->base, &save_qstart, &save_qend, &save_cur_entry_pt);
/* check state, and clear invalid bits */
while (*state >> irq_bit) {
/* check irq_bit */
if (BIT(*state, irq_bit)) {
/* clear irq_bit */
sdrv_acmp_clear_irq(dev->base, 1 << irq_bit);
/* stop tg_start */
sdrv_acmp_it_gen_start(dev->base, false);
/* only trigger irq_bit */
sdrv_acmp_config_it_mode(dev->base, irq_bit, irq_bit, irq_bit);
/* restart tg_start */
sdrv_acmp_it_gen_start(dev->base, true);//
/* wait more than terminal time */
udelay(wait_time);
}
/* check next bit */
irq_bit ++;
if (irq_bit > 31) {
break;
}
}
/* update irq state */
*state = sdrv_acmp_get_irq_state(dev->base);
/* restore IT mode qstart/qend/cur_entry_pt */
if (save_cur_entry_pt >= save_qend) {
save_cur_entry_pt = save_qstart;
}
else {
save_cur_entry_pt = save_cur_entry_pt + 1;
}
return sdrv_acmp_config_it_mode(dev->base, save_qstart, save_qend, save_cur_entry_pt);
}
/**
* @brief sdrv acmp power ctrl
*
* This function sets the sdrv acmp power mode.
* The status is default power on after acmp initilization.
* If the acmp comparation is finished, the power mode can be set to power down to reduce power consumption.
*
* @param[in] dev sdrv acmp device
* @param[in] down 0 power on (default), 1 power down
* @return SDRV_STATUS_OK represents success
*/
status_t sdrv_acmp_power_ctrl(sdrv_acmp_t *dev, bool down)
{
if (dev->base == 0) {
return SDRV_ACMP_STATUS_INVALID_PARAM;
}
/* power down analog competitor */
RMWREG32(dev->base + ACMP_PD_CTRL, ACMP_PD_CTRL_CMP, 1, down);
/* power down analog dac */
RMWREG32(dev->base + ACMP_PD_CTRL, ACMP_PD_CTRL_DAC, 1, down);
return SDRV_STATUS_OK;
}
/**
* @brief sdrv acmp allows analog competitor and dac enter lowpower mode
*
* This function allows competitor and dac recv q channel low power request.
* And than if the lowpower request is received, the competitor and dac will enter
* low power mode after req_n_dly clock cycle.
*
* @param[in] dev sdrv acmp device
* @param[in] cmp_en competitor enable or disable
* @param[in] dac_en dac enable or disable
* @param[in] req_n_dly enter lowpower mode delay number
* @return SDRV_STATUS_OK represents success
*/
status_t sdrv_acmp_enable_low_power(sdrv_acmp_t *dev, bool cmp_en, bool dac_en,
uint8_t req_n_dly)
{
if (dev->base == 0) {
return SDRV_ACMP_STATUS_INVALID_PARAM;
}
/* set low power req_n delay */
sdrv_acmp_set_low_power(dev->base, req_n_dly);
/* competitor recv q channel low power request */
sdrv_acmp_rcv_qch_cmp(dev->base, cmp_en);
/* dac recv q channel low power request */
sdrv_acmp_rcv_qch_dac(dev->base, dac_en);
return SDRV_STATUS_OK;
}
/**
* @brief sdrv acmp set callback
*
* This function is used to set the sdrv acmp callback function separately, after acmp initilization.
*
* @param[in] dev sdrv acmp device
* @param[in] callback acmp callback function
* @return SDRV_STATUS_OK represents success
*/
status_t sdrv_acmp_set_callback(sdrv_acmp_t *dev, sdrv_acmp_callback callback)
{
dev->callback = callback;
return SDRV_STATUS_OK;
}
/**
* @brief sdrv acmp deinit
*
* This function stops acmp and deletes acmp initilization.
* Acmp must be de-initiated before entering lowpower mode.
*
* @param[in] dev sdrv acmp device
* @return SDRV_STATUS_OK represents success
*/
status_t sdrv_acmp_deinit(sdrv_acmp_t *dev)
{
status_t ret;
if (dev->irq > 0) {
irq_disable(dev->irq);
irq_detach(dev->irq);
}
/* stop acmp */
ret = sdrv_acmp_start(dev, false);
/* clear ACMP IT mode */
sdrv_acmp_config_mode(dev->base, ACMP_HT_MODE);
/* soft reset */
sdrv_acmp_soft_reset(dev->base);
/* clear the acmp controller. */
(void)memset(dev, 0, sizeof(sdrv_acmp_t));
return ret;
}