Files
1CAR/drivers/source/adc/sdrv_adc.c
2025-10-25 21:11:06 +08:00

777 lines
21 KiB
C

/**
* @file sdrv_adc.c
* @brief Semidrive ADC driver source file.
*
* @copyright Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*/
#include <common.h>
#include <debug.h>
#include <sdrv_adc.h>
#include <sdrv_adc_dev_data.h>
#include <clock_ip.h>
#include <udelay/udelay.h>
#if CONFIG_E3 || CONFIG_D3
static uint8_t adc_fifo_read_rcd[3];
#endif
__WEAK const sdrv_adc_dev_data_t sdrv_adc_dev_data_table[] = {
{APB_ADC1_BASE, CLK_NODE(g_ckgen_ip_adc1), HOST_ADC1_DFLT_OFFSET},
{APB_ADC2_BASE, CLK_NODE(g_ckgen_ip_adc2), HOST_ADC2_DFLT_OFFSET},
#ifdef APB_ADC3_BASE
{APB_ADC3_BASE, CLK_NODE(g_ckgen_ip_adc3), HOST_ADC3_DFLT_OFFSET},
#endif
{NULL, NULL}
};
void sdrv_adc_init(sdrv_adc_t *sdrv_adcX, unsigned int clk_div)
{
uint32_t temp;
uint32_t tmo;
uint32_t clk_freq;
unsigned int clk_div_min;
const sdrv_adc_dev_data_t *p_adc_data;
int i;
ASSERT(sdrv_adcX);
p_adc_data = NULL;
for (i = 0; sdrv_adc_dev_data_table[i].adc_base; i++) {
if (sdrv_adc_dev_data_table[i].adc_base == (uintptr_t)sdrv_adcX) {
p_adc_data = &sdrv_adc_dev_data_table[i];
break;
}
}
if (!p_adc_data) {
ssdk_printf(SSDK_WARNING, "Make sure ADC %p clock div%d <= 32MHz.\n", sdrv_adcX, clk_div);
clk_div_min = 1;
} else {
/* If p_adc_data->adc_ckgen is NULL, consider clk_div parameter as valid. */
clk_freq = sdrv_ckgen_get_rate(p_adc_data->adc_ckgen);
clk_div_min = clk_freq / CLK_MHZ(32);
if (clk_div_min) {
if (clk_freq / clk_div_min > CLK_MHZ(32))
clk_div_min++;
} else {
clk_div_min = 1;
}
}
#if CONFIG_E3 || CONFIG_D3
sdrv_adcX->ana_ref_cfg2 = 0xFFFFu;
sdrv_adc2->ana_ref_cfg2 = 0xFFFFu;
#endif
sdrv_adcX->soft_rst |= SADC_SOFT_RST_DIG | SADC_SOFT_RST_RC0TMR |
SADC_SOFT_RST_RC1TMR | SADC_SOFT_RST_RC2TMR |
SADC_SOFT_RST_RC3TMR;
udelay(50);
sdrv_adcX->htc = 0;
for (i = 0; i < SDRV_ADC_RC_CNT; i++) {
sdrv_adcX->rc[i] = 0;
}
for (i = 0; i < SDRV_ADC_MNT_SINGLE_CNT; i++) {
sdrv_adcX->mnt_thrd_single[i] = SADC_MNT_THRES_MODE_CLOSE;
}
sdrv_adcX->mnt_thrd_cont = SADC_MNT_THRES_MODE_CLOSE;
sdrv_adcX->sch_cfg = SADC_SCH_CFG_MODE_MASTER | SADC_SCH_CFG_ASYNC_STALL | 0xF;
temp = clk_div;
if (clk_div < clk_div_min)
clk_div = clk_div_min;
if (clk_div > SDRV_ADC_CLK_DIV_MAX)
clk_div = SDRV_ADC_CLK_DIV_MAX;
else if (clk_div == 3)
clk_div++;
if (clk_div != temp)
ssdk_printf(SSDK_WARNING, "Round ADC %p clock div %d to %d.\n", sdrv_adcX, temp, clk_div);
if (clk_div == 1) {
sdrv_adcX->clk_ctrl = SADC_CLK_CTRL_DIV_BYPASS;
} else {
temp = clk_div / 2;
/* duty cycle in [40%, 50%] */
sdrv_adcX->clk_ctrl = ((clk_div - temp - 1) << SADC_CLK_CTRL_REFL_POS) |
((temp - 1) << SADC_CLK_CTRL_REFH_POS);
}
sdrv_adcX->soft_rst = SADC_SOFT_RST_ANA;
tmo = SDRV_ADC_POLL_TMO;
sdrv_adcX->init |= SADC_INIT_START;
while (!(sdrv_adcX->init & SADC_INIT_DONE) && tmo--);
if (p_adc_data) {
sdrv_adc_set_dc_offset(sdrv_adcX, p_adc_data->dc_offset);
} else {
sdrv_adc_set_dc_offset(sdrv_adcX, 0);
}
for (i = 0; i < SDRV_ADC_SUB_FIFO_CNT; i++) {
sdrv_adcX->sub_fifo[i] &= ~(SADC_SUB_FIFO_SADDR_MSK | SADC_SUB_FIFO_RC_EN_MSK);
}
sdrv_adcX->sub_fifo[3] |= SADC_SUB_FIFO_RC_EN_MSK;
sdrv_adcX->fifo_cfg = SADC_FIFO_CFG_PACK_M_32 << SADC_FIFO_CFG_PACK_M_POS;
#if CONFIG_E3 || CONFIG_D3
if (IS_P1 || !tmo) {
return;
}
switch ((uintptr_t)sdrv_adcX) {
case APB_ADC1_BASE:
i = 0;
break;
case APB_ADC2_BASE:
i = 1;
break;
#ifdef APB_ADC3_BASE
case APB_ADC3_BASE:
i = 2;
break;
#endif
default:
/* Ignore ADC in slave chip. */
return;
}
if (!adc_fifo_read_rcd[i]) {
sdrv_adcX->rc[3] = SADC_RC_TRG_EN | SADC_RC_TRG_MODE_SW;
sdrv_adcX->sch_cfg &= ~SADC_SCH_CFG_ASYNC_STALL;
sdrv_adcX->rc_entry[3][0] = 0;
sdrv_adcX->ana_para[0] = 0;
sdrv_adcX->rc[3] |= SADC_RC_SOFT_TRG;
tmo = SDRV_ADC_POLL_TMO;
while ((sdrv_adcX->sub_fifo[3] & SADC_SUB_FIFO_EMPTY) && tmo--);
sdrv_adcX->fusa_cor_err_int_stat_en = 0;
sdrv_adcX->fusa_unc_err_int_stat_en = 0;
sdrv_adcX->fifo[3][0];
sdrv_adcX->fusa_cor_err_int_stat_en = 0xFFFFFFFFu;
sdrv_adcX->fusa_unc_err_int_stat_en = 0xFFFFFFFFu;
sdrv_adcX->rc[3] = 0;
sdrv_adcX->sch_cfg |= SADC_SCH_CFG_ASYNC_STALL;
adc_fifo_read_rcd[i] = 1;
}
#endif
return;
}
void sdrv_adc_set_dc_offset(sdrv_adc_t *sdrv_adcX, int16_t offset)
{
uint32_t temp;
ASSERT(sdrv_adcX);
if (offset) {
temp = sdrv_adcX->dcoc;
temp &= ~(SADC_DCOC_EN | SADC_DCOC_VALUE_MSK | SADC_DCOC_VALUE_SIGN);
if (offset > 0) {
temp |= ((uint32_t)offset << SADC_DCOC_VALUE_POS) & SADC_DCOC_VALUE_MSK;
} else {
temp |= ((uint32_t)(-offset) << SADC_DCOC_VALUE_POS) & SADC_DCOC_VALUE_MSK;
temp |= SADC_DCOC_VALUE_SIGN;
}
temp |= SADC_DCOC_OVWR;
sdrv_adcX->dcoc = temp;
sdrv_adcX->dcoc |= SADC_DCOC_EN;
} else {
sdrv_adcX->dcoc &= ~SADC_DCOC_EN;
}
return;
}
int16_t sdrv_adc_get_dc_offset(sdrv_adc_t *sdrv_adcX)
{
uint32_t temp;
bool sign;
ASSERT(sdrv_adcX);
temp = sdrv_adcX->dcoc;
if (temp & SADC_DCOC_EN) {
sign = !!(temp & SADC_DCOC_VALUE_SIGN);
temp = (temp & SADC_DCOC_VALUE_MSK) >> SADC_DCOC_VALUE_POS;
if (sign) {
return -temp;
} else {
return temp;
}
} else {
return 0;
}
}
void sdrv_adc_set_slave_mode(sdrv_adc_t *sdrv_adcX)
{
ASSERT(sdrv_adcX);
ASSERT(sdrv_adcX != sdrv_adc1);
sdrv_adcX->sch_cfg &= ~SADC_SCH_CFG_MODE_MASTER;
return;
}
void sdrv_adc_clr_slave_mode(sdrv_adc_t *sdrv_adcX)
{
ASSERT(sdrv_adcX);
sdrv_adcX->sch_cfg |= SADC_SCH_CFG_MODE_MASTER;
return;
}
uint32_t sdrv_adc_read_int_status(sdrv_adc_t *sdrv_adcX)
{
ASSERT(sdrv_adcX);
return sdrv_adcX->int_stat;
}
void sdrv_adc_clear_int_status(sdrv_adc_t *sdrv_adcX, uint32_t int_bits)
{
ASSERT(sdrv_adcX);
sdrv_adcX->int_stat = int_bits;
return;
}
void sdrv_adc_int_status_en_cfg(sdrv_adc_t *sdrv_adcX, uint32_t int_bits, bool enable)
{
ASSERT(sdrv_adcX);
if (enable) {
sdrv_adcX->int_stat_en |= int_bits;
} else {
sdrv_adcX->int_stat_en &= ~int_bits;
}
return;
}
void sdrv_adc_int_status_sig_en_cfg(sdrv_adc_t *sdrv_adcX, uint32_t int_bits, bool enable)
{
ASSERT(sdrv_adcX);
if (enable) {
sdrv_adcX->int_sig_en |= int_bits;
} else {
sdrv_adcX->int_sig_en &= ~int_bits;
}
return;
}
void sdrv_adc_rc_cfg(sdrv_adc_t *sdrv_adcX, unsigned int rc_nbr, sdrv_adc_rc_cfg_t *rc_cfg)
{
uint32_t temp;
uint32_t terminal;
uint32_t compare;
ASSERT(sdrv_adcX);
ASSERT(rc_nbr < SDRV_ADC_RC_CNT);
ASSERT(rc_cfg);
ASSERT(rc_nbr || (rc_cfg->tmr_mode != SDRV_ADC_RC_TMR_MODE_SLAVE));
/* Avoid reg parity issue. */
terminal = (rc_cfg->terminal < SADC_RC_TIMER_TERMINAL_MIN) ?
SADC_RC_TIMER_TERMINAL_MIN : rc_cfg->terminal;
compare = rc_cfg->compare ? rc_cfg->compare : SADC_RC_TIMER_COMPARE_MIN;
sdrv_adcX->rc_timer[rc_nbr] = (terminal << SADC_RC_TIMER_TERMINAL_POS) |
(compare << SADC_RC_TIMER_COMPARE_POS);
temp = rc_cfg->q_cur << SADC_RC_Q_CUR_POS | SADC_RC_OVWR_CUR_EN;
temp |= rc_cfg->q_start << SADC_RC_Q_START_POS;
temp |= rc_cfg->q_end << SADC_RC_Q_END_POS;
if (rc_cfg->tmr_mode == SDRV_ADC_RC_TMR_MODE_SLAVE) {
temp |= SADC_RC_TMR_SLAVE;
}
if (rc_cfg->trg_mode == SDRV_ADC_RC_TRG_MODE_SW) {
temp |= SADC_RC_TRG_MODE_SW;
}
if (rc_cfg->trg_en) {
temp |= SADC_RC_TRG_EN;
}
sdrv_adcX->rc[rc_nbr] = temp;
return;
}
void sdrv_adc_rc_start_tmr(sdrv_adc_t *sdrv_adcX, unsigned int rc_nbr)
{
ASSERT(sdrv_adcX);
ASSERT(rc_nbr < SDRV_ADC_RC_CNT);
sdrv_adcX->rc[rc_nbr] |= SADC_RC_TRG_START;
return;
}
void sdrv_adc_rc_start_timers(sdrv_adc_t *sdrv_adcX, sdrv_adc_rc_start_flag_t rc_flags)
{
int i;
uint32_t reset_rc_tmr;
ASSERT(sdrv_adcX);
reset_rc_tmr = (rc_flags & SDRV_ADC_START_ALL) << SADC_SOFT_RST_RC_POS;
sdrv_adcX->soft_rst |= reset_rc_tmr;
for (i = 0; i < SDRV_ADC_RC_CNT; i++) {
if (rc_flags & (1u << i)) {
sdrv_adcX->rc[i] |= SADC_RC_TRG_START;
}
}
sdrv_adcX->soft_rst &= ~reset_rc_tmr;
return;
}
void sdrv_adc_rc_stop_tmr(sdrv_adc_t *sdrv_adcX, unsigned int rc_nbr)
{
uint32_t reset_rc_tmr;
ASSERT(sdrv_adcX);
ASSERT(rc_nbr < SDRV_ADC_RC_CNT);
switch (rc_nbr) {
case 0:
reset_rc_tmr = SADC_SOFT_RST_RC0TMR;
break;
case 1:
reset_rc_tmr = SADC_SOFT_RST_RC1TMR;
break;
case 2:
reset_rc_tmr = SADC_SOFT_RST_RC2TMR;
break;
case 3:
reset_rc_tmr = SADC_SOFT_RST_RC3TMR;
break;
default:
return;
}
sdrv_adcX->soft_rst |= reset_rc_tmr;
sdrv_adcX->rc[rc_nbr] &= ~SADC_RC_TRG_START;
sdrv_adcX->soft_rst &= ~reset_rc_tmr;
return;
}
void sdrv_adc_rc_soft_trg(sdrv_adc_t *sdrv_adcX, unsigned int rc_nbr)
{
uint32_t tmo;
ASSERT(sdrv_adcX);
ASSERT(rc_nbr < SDRV_ADC_RC_CNT);
tmo = SDRV_ADC_POLL_TMO;
while ((sdrv_adcX->rc[rc_nbr] & SADC_RC_SOFT_TRG) && tmo--);
sdrv_adcX->rc[rc_nbr] |= SADC_RC_SOFT_TRG;
return;
}
void sdrv_adc_rcht_ready(sdrv_adc_t *sdrv_adcX, uint8_t ready_len)
{
ASSERT(sdrv_adcX);
sdrv_adcX->htc = (ready_len << SADC_HTC_READY_LEN_POS) |
SADC_HTC_READY;
return;
}
void sdrv_adc_rcht_clr_ready(sdrv_adc_t *sdrv_adcX)
{
ASSERT(sdrv_adcX);
sdrv_adcX->htc &= ~SADC_HTC_READY;
return;
}
void sdrv_adc_rcht_entry_cfg(sdrv_adc_t *sdrv_adcX,
unsigned int entry_nbr,
sdrv_adc_rcht_entry_cfg_t entry_cfg)
{
uint32_t temp;
ASSERT(sdrv_adcX);
ASSERT(entry_nbr < SDRV_ADC_RCHT_ENTRY_CNT);
temp = entry_cfg.channel |
(entry_cfg.cfg_sel << SADC_RCHT_ENTRY_CSEL_POS) |
(entry_cfg.repeat_cnt << SADC_RCHT_ENTRY_RPT_CNT_POS);
temp |= SADC_RCHT_ENTRY_RPT_MODE;
sdrv_adcX->rcht_entry[entry_nbr] = temp;
return;
}
void sdrv_adc_rc_entry_cfg( sdrv_adc_t *sdrv_adcX,
unsigned int rc_nbr,
unsigned int entry_nbr,
sdrv_adc_rc_entry_cfg_t entry_cfg)
{
uint32_t temp;
ASSERT(sdrv_adcX);
ASSERT(rc_nbr < SDRV_ADC_RC_CNT);
ASSERT(entry_nbr < SDRV_ADC_RC_ENTRY_CNT);
if (entry_cfg.repeat_cnt > 16) {
entry_cfg.repeat_cnt = 16;
} else if (entry_cfg.repeat_cnt == 0) {
entry_cfg.repeat_cnt = 1;
}
temp = entry_cfg.channel |
(entry_cfg.cfg_sel << SADC_RC_ENTRY_CSEL_POS) |
((entry_cfg.repeat_cnt - 1) << SADC_RC_ENTRY_RPT_CNT_POS);
if (entry_cfg.repeat_mode != SDRV_ADC_RC_REPM_HW_TRG) {
temp |= SADC_RC_ENTRY_RPT_MODE;
}
sdrv_adcX->rc_entry[rc_nbr][entry_nbr] = temp;
return;
}
void sdrv_adc_ana_param_cfg(sdrv_adc_t *sdrv_adcX,
unsigned int param_nbr,
sdrv_adc_ana_param_cfg_t aparam_cfg)
{
uint32_t temp;
ASSERT(sdrv_adcX);
ASSERT(param_nbr < SDRV_ADC_ANA_PARAM_CNT);
temp = sdrv_adcX->ana_para[param_nbr] &
~(SADC_ANA_PARAM_SAMCTRL_MSK | SADC_ANA_PARAM_REF_SEL | SADC_ANA_PARAM_DIFF_SEL);
temp |= aparam_cfg.sample_time << SADC_ANA_PARAM_SAMCTRL_POS;
if (aparam_cfg.ref_sel) {
temp |= SADC_ANA_PARAM_REF_SEL;
}
if (aparam_cfg.input_mode) {
temp |= SADC_ANA_PARAM_DIFF_SEL;
}
sdrv_adcX->ana_para[param_nbr] = temp;
return;
}
void sdrv_adc_fifo_cfg(sdrv_adc_t *sdrv_adcX, sdrv_adc_fifo_cfg_t *fifo_cfg)
{
uint32_t temp;
ASSERT(sdrv_adcX);
ASSERT(fifo_cfg);
if (fifo_cfg->bypass) {
sdrv_adcX->fifo_cfg |= SADC_FIFO_CFG_BYPASS;
return;
}
temp = fifo_cfg->pack_mode << SADC_FIFO_CFG_PACK_M_POS;
if (fifo_cfg->pack16_chnl) {
temp |= SADC_FIFO_CFG_PACK16_AMSEL;
}
sdrv_adcX->fifo_cfg = temp;
temp = sdrv_adcX->sub_fifo[3];
temp &= ~SADC_SUB_FIFO_THRES_MSK;
temp |= fifo_cfg->threshold << SADC_SUB_FIFO_THRES_POS;
sdrv_adcX->sub_fifo[3] = temp;
return;
}
void sdrv_adc_fifo_rc_cfg(sdrv_adc_t *sdrv_adcX, sdrv_adc_fifo_rc_cfg_t rc_cfg)
{
uint32_t temp;
ASSERT(sdrv_adcX);
temp = sdrv_adcX->sub_fifo[3];
temp &= ~SADC_SUB_FIFO_RC_EN_MSK;
temp |= rc_cfg << SADC_SUB_FIFO_RC_EN_POS;
sdrv_adcX->sub_fifo[3] = temp;
return;
}
uint32_t sdrv_adc_fifo_status(sdrv_adc_t *sdrv_adcX)
{
ASSERT(sdrv_adcX);
return (sdrv_adcX->sub_fifo[3] & (SADC_SUB_FIFO_EMPTY | SADC_SUB_FIFO_FULL));
}
uint32_t sdrv_adc_read_fifo(sdrv_adc_t *sdrv_adcX)
{
ASSERT(sdrv_adcX);
return sdrv_adcX->fifo[3][0];
}
uintptr_t sdrv_adc_fifo_addr(sdrv_adc_t *sdrv_adcX)
{
ASSERT(sdrv_adcX);
return (uintptr_t)&sdrv_adcX->fifo[3][0];
}
void sdrv_adc_dma_enable(sdrv_adc_t *sdrv_adcX, sdrv_adc_dma_src_cfg_t req_src)
{
ASSERT(sdrv_adcX);
ASSERT((unsigned int)req_src <= SDRV_ADC_DMA_SRC_RCHT);
switch (req_src) {
case SDRV_ADC_DMA_SRC_FIFO:
sdrv_adcX->dma_cfg = SADC_DMA_CH0EN_F3RC3 | SADC_DMA_MODE_FIFO3;
break;
case SDRV_ADC_DMA_SRC_RC0:
sdrv_adcX->dma_cfg = SADC_DMA_CH0EN_F0RC0;
break;
case SDRV_ADC_DMA_SRC_RC1:
sdrv_adcX->dma_cfg = SADC_DMA_CH0EN_F1RC1;
break;
case SDRV_ADC_DMA_SRC_RC2:
sdrv_adcX->dma_cfg = SADC_DMA_CH0EN_F2RC2;
break;
case SDRV_ADC_DMA_SRC_RC3:
sdrv_adcX->dma_cfg = SADC_DMA_CH0EN_F3RC3;
break;
case SDRV_ADC_DMA_SRC_RCHT:
sdrv_adcX->dma_cfg = SADC_DMA_CH0EN_RCHT;
break;
default:
break;
}
return;
}
void sdrv_adc_dma_disable(sdrv_adc_t *sdrv_adcX)
{
ASSERT(sdrv_adcX);
sdrv_adcX->dma_cfg = 0;
return;
}
void sdrv_adc_sync_cfg( sdrv_adc_t *sdrv_adcX,
sdrv_adc_sync_cfg_t sync_cfg,
uint8_t *slot_cid,
unsigned int len)
{
uint8_t cid_buf[SADC_SCH_CID_CNT];
unsigned int cid_fill_cnt;
uint32_t temp, temp_ctrl;
uint32_t interval;
uint32_t clk_div;
int i, j;
ASSERT(sdrv_adcX);
ASSERT(slot_cid && len);
/* slot0 should not be 4, 5, 7. */
ASSERT((slot_cid[0] & SADC_SCH_CID_MSK) != SDRV_ADC_SYNC_CID_MERGE);
ASSERT(((slot_cid[0] & SADC_SCH_CID_MSK) != SDRV_ADC_SYNC_CID_RCHT) ||
/* slot_cid[0] won't be copied to slot0 under the following situation. */
(!sync_cfg.itvl_const && (len < SADC_SCH_CID_CNT)));
sdrv_adcX->sch_cfg &= ~SADC_SCH_CFG_ROT_EN;
sdrv_adcX->sch_cfg |= SADC_SCH_CFG_MODE_SYNC;
if (len > SADC_SCH_CID_CNT) {
len = SADC_SCH_CID_CNT;
}
for (i = 0; i < len; i++) {
cid_buf[i] = slot_cid[i] & SADC_SCH_CID_MSK;
}
if (len == SADC_SCH_CID_CNT) {
/* User set all slots manually. Nothing more to do. */
} else if (sync_cfg.itvl_const) {
cid_fill_cnt = SADC_SCH_CID_CNT % len;
if (cid_fill_cnt) {
/* check whether the input CID sequence consists of the same CID. */
for (i = 1; i < len; i++) {
if (cid_buf[i] != cid_buf[0])
break;
}
/* If so, copy the same CID to all 64 CID slots. */
if (i == len) {
len = 1;
cid_fill_cnt = 0;
}
}
/* Copy the input CID sequence to CID slots circularly.
The last cid_fill_cnt slots could be filled with CID 7.*/
for (i = len; i < SADC_SCH_CID_CNT - cid_fill_cnt; i++) {
cid_buf[i] = cid_buf[i - len];
}
if (cid_fill_cnt) {
/* Find the place where CID 7 could be inserted. */
cid_buf[SADC_SCH_CID_CNT - cid_fill_cnt] = cid_buf[0];
for (j = len - 1; j >= 0; j--) {
/* 7 is not allowed to be before 4 or 5. */
if ((cid_buf[j + 1] != SDRV_ADC_SYNC_CID_RCHT) &&
(cid_buf[j + 1] != SDRV_ADC_SYNC_CID_MERGE)) {
break;
}
}
/* Fill the last cid_fill_cnt slots with CID 7. */
for (i = SADC_SCH_CID_CNT - cid_fill_cnt; i < SADC_SCH_CID_CNT; i++) {
cid_buf[i] = SADC_SCH_CID_MV_NEXT;
}
if (j < 0) {
/* If the place for CID 7 isnot found, change the last slot to CID 6. */
cid_buf[SADC_SCH_CID_CNT - 1] = SDRV_ADC_SYNC_CID_IDLE;
} else {
/* Move the CIDs after the place to the end of the 64 slots. */
for (i = len - 1; i > j; i--) {
cid_buf[SADC_SCH_CID_CNT - (len - i)] = cid_buf[i];
cid_buf[SADC_SCH_CID_CNT - cid_fill_cnt - (len - i)] = SADC_SCH_CID_MV_NEXT;
}
}
}
} else {
/* slot0 must be 6 in non-const mode. */
cid_buf[0] = SDRV_ADC_SYNC_CID_IDLE;
cid_fill_cnt = (SADC_SCH_CID_CNT - 1) % len;
/* Copy the input CID sequence to CID slots circularly. */
for (i = 1; i < SADC_SCH_CID_CNT - cid_fill_cnt; i++) {
cid_buf[i] = slot_cid[(i - 1) % len];
}
/* Fill the last cid_fill_cnt slots with CID 7. */
for (; i < SADC_SCH_CID_CNT; i++) {
cid_buf[i] = SADC_SCH_CID_MV_NEXT;
}
}
/* Convert the slot sequence from 8-bit buffer to 8*4-bit register. */
for (i = 0; i < SDRV_ADC_CID_PART_CNT; i++) {
temp = 0;
for (j = SADC_SCH_CID_CNT_PER_REG - 1; j >= 0; j--) {
temp = (temp << SADC_SCH_CID_WIDTH_BIT) | cid_buf[i * SADC_SCH_CID_CNT_PER_REG + j];
}
sdrv_adcX->sch_cid_part[i] = temp;
}
interval = sync_cfg.slot_itvl ? sync_cfg.slot_itvl : 256;
temp = sdrv_adcX->sch_cfg;
temp &= ~SADC_SCH_CFG_SLOT_ITVL_MSK;
if (sync_cfg.itvl_const) {
temp |= SADC_SCH_CFG_SLOT_CONST;
temp |= (interval - 1) << SADC_SCH_CFG_SLOT_ITVL_POS;
} else {
temp &= ~SADC_SCH_CFG_SLOT_CONST;
temp |= 1u << SADC_SCH_CFG_SLOT_ITVL_POS; /* Let slot0 consume the least time. */
temp_ctrl = sdrv_adcX->clk_ctrl;
clk_div = 2;
clk_div += (temp_ctrl & SADC_CLK_CTRL_REFH_MSK) >> SADC_CLK_CTRL_REFH_POS;
clk_div += (temp_ctrl & SADC_CLK_CTRL_REFL_MSK) >> SADC_CLK_CTRL_REFL_POS;
sdrv_adcX->sch_tmo = interval * clk_div;
}
sdrv_adcX->sch_cfg = temp;
return;
}
void sdrv_adc_sync_start(sdrv_adc_t *sdrv_adcX)
{
ASSERT(sdrv_adcX);
sdrv_adcX->sch_cfg |= SADC_SCH_CFG_ROT_EN;
return;
}
void sdrv_adc_Async_start(sdrv_adc_t *sdrv_adcX)
{
ASSERT(sdrv_adcX);
sdrv_adcX->sch_cfg &= ~SADC_SCH_CFG_ASYNC_STALL;
return;
}
void sdrv_adc_sync_slot_reset(sdrv_adc_t *sdrv_adcX)
{
uint32_t tmo;
ASSERT(sdrv_adcX);
tmo = SDRV_ADC_POLL_TMO;
sdrv_adcX->sch_cfg |= SADC_SCH_CFG_SLOT_RST;
while (!(sdrv_adcX->sch_cfg & SADC_SCH_CFG_RST_DONE) && tmo--);
sdrv_adcX->sch_cfg &= ~SADC_SCH_CFG_SLOT_RST;
return;
}
void sdrv_adc_stop(sdrv_adc_t *sdrv_adcX, bool rc_tmr_stop)
{
uint32_t temp;
int i;
ASSERT(sdrv_adcX);
if (rc_tmr_stop) {
sdrv_adcX->soft_rst |= SADC_SOFT_RST_RC0TMR | SADC_SOFT_RST_RC1TMR |
SADC_SOFT_RST_RC2TMR | SADC_SOFT_RST_RC3TMR;
for (i = 0; i < SDRV_ADC_RC_CNT; i++) {
sdrv_adcX->rc[i] &= ~SADC_RC_TRG_START;
}
sdrv_adcX->soft_rst &= ~(SADC_SOFT_RST_RC0TMR | SADC_SOFT_RST_RC1TMR |
SADC_SOFT_RST_RC2TMR | SADC_SOFT_RST_RC3TMR);
}
temp = sdrv_adcX->sch_cfg;
if (temp & SADC_SCH_CFG_MODE_SYNC) {
temp &= ~SADC_SCH_CFG_ROT_EN;
} else {
temp |= SADC_SCH_CFG_ASYNC_STALL;
}
sdrv_adcX->sch_cfg = temp;
return;
}
void sdrv_adc_power_ctrl(sdrv_adc_t *sdrv_adcX, bool down)
{
ASSERT(sdrv_adcX);
if (down) {
sdrv_adcX->ana_ref_cfg1 |= (SADC_ANA_REF_PART1_PD | SADC_ANA_REF_PART1_PDBISA);
}
else {
sdrv_adcX->ana_ref_cfg1 &= ~SADC_ANA_REF_PART1_PD;
sdrv_adcX->ana_ref_cfg1 &= ~SADC_ANA_REF_PART1_PDBISA;
}
}