Files
base/drivers/source/acmp/sdrv_acmp.c
2025-11-07 09:57:14 +08:00

758 lines
21 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @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;
}