/** * @file sdrv_adc.c * @brief Semidrive ADC driver source file. * * @copyright Copyright (c) 2021 Semidrive Semiconductor. * All rights reserved. */ #include #include #include #include #include #include #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; } }