1 /*
2  * Copyright (c) 2021-2024 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "hpm_adc16_drv.h"
9 #include "hpm_soc_feature.h"
10 
adc16_get_default_config(adc16_config_t * config)11 void adc16_get_default_config(adc16_config_t *config)
12 {
13     config->res                = adc16_res_16_bits;
14     config->conv_mode          = adc16_conv_mode_oneshot;
15     config->adc_clk_div        = adc16_clock_divider_1;
16     config->wait_dis           = true;
17     config->sel_sync_ahb       = true;
18     config->port3_realtime     = false;
19     config->adc_ahb_en         = false;
20 }
21 
adc16_get_channel_default_config(adc16_channel_config_t * config)22 void adc16_get_channel_default_config(adc16_channel_config_t *config)
23 {
24     config->ch                 = 0;
25     config->sample_cycle       = 10;
26     config->sample_cycle_shift = 0;
27     config->thshdh             = 0xffff;
28     config->thshdl             = 0x0000;
29     config->wdog_int_en        = false;
30 }
31 
adc16_do_calibration(ADC16_Type * ptr)32 static hpm_stat_t adc16_do_calibration(ADC16_Type *ptr)
33 {
34     uint32_t i, j;
35     uint32_t clk_div_temp;
36     uint32_t adc16_params[ADC16_SOC_PARAMS_LEN];
37     int32_t  param01;
38     uint32_t param02;
39     uint64_t param64;
40     uint32_t param32;
41     uint32_t temp;
42 
43     /* Get input clock divider */
44     clk_div_temp = ADC16_CONV_CFG1_CLOCK_DIVIDER_GET(ptr->CONV_CFG1);
45 
46     /* Set input clock divider temporarily */
47     ptr->CONV_CFG1 = (ptr->CONV_CFG1 & ~ADC16_CONV_CFG1_CLOCK_DIVIDER_MASK)
48                    | ADC16_CONV_CFG1_CLOCK_DIVIDER_SET(1);
49 
50     /* Enable ADC config clock */
51     ptr->ANA_CTRL0 |= ADC16_ANA_CTRL0_ADC_CLK_ON_MASK;
52 
53     for (i = 0; i < ADC16_SOC_PARAMS_LEN; i++) {
54         adc16_params[i] = 0;
55     }
56 
57     /* Enable reg_en */
58     /* Enable bandgap_en */
59     ptr->ADC16_CONFIG0 |= ADC16_ADC16_CONFIG0_REG_EN_MASK
60                        |  ADC16_ADC16_CONFIG0_BANDGAP_EN_MASK;
61 
62     /* Set cal_avg_cfg for 32 loops */
63     ptr->ADC16_CONFIG0 = (ptr->ADC16_CONFIG0 & ~ADC16_ADC16_CONFIG0_CAL_AVG_CFG_MASK)
64                        | ADC16_ADC16_CONFIG0_CAL_AVG_CFG_SET(5);
65 
66     /* Enable ahb_en */
67     ptr->ADC_CFG0 |= ADC16_ADC_CFG0_ADC_AHB_EN_MASK | (1 << 2);
68 
69     /* Disable ADC config clock */
70     ptr->ANA_CTRL0 &= ~ADC16_ANA_CTRL0_ADC_CLK_ON_MASK;
71 
72     /* Recover input clock divider */
73     ptr->CONV_CFG1 = (ptr->CONV_CFG1 & ~ADC16_CONV_CFG1_CLOCK_DIVIDER_MASK)
74                    | ADC16_CONV_CFG1_CLOCK_DIVIDER_SET(clk_div_temp);
75 
76     for (j = 0; j < 4; j++) {
77         /* Set startcal */
78         ptr->ANA_CTRL0 |= ADC16_ANA_CTRL0_STARTCAL_MASK;
79 
80         /* Clear startcal */
81         ptr->ANA_CTRL0 &= ~ADC16_ANA_CTRL0_STARTCAL_MASK;
82 
83         /* Polling calibration status */
84         while (ADC16_ANA_STATUS_CALON_GET(ptr->ANA_STATUS)) {
85         }
86 
87         /* Read parameters */
88         for (i = 0; i < ADC16_SOC_PARAMS_LEN; i++) {
89             adc16_params[i] += ADC16_ADC16_PARAMS_PARAM_VAL_GET(ptr->ADC16_PARAMS[i]);
90         }
91     }
92 
93     adc16_params[ADC16_ADC16_PARAMS_ADC16_PARA33] -= 0x800;
94     param01 = adc16_params[ADC16_ADC16_PARAMS_ADC16_PARA32] - adc16_params[ADC16_ADC16_PARAMS_ADC16_PARA33];
95     adc16_params[ADC16_ADC16_PARAMS_ADC16_PARA32] = adc16_params[ADC16_ADC16_PARAMS_ADC16_PARA00] -
96                                                     adc16_params[ADC16_ADC16_PARAMS_ADC16_PARA33];
97     adc16_params[ADC16_ADC16_PARAMS_ADC16_PARA00] = 0;
98 
99     for (i = 1; i < ADC16_SOC_PARAMS_LEN - 2; i++) {
100         adc16_params[i] = adc16_params[ADC16_ADC16_PARAMS_ADC16_PARA32] + adc16_params[i] -
101                           adc16_params[ADC16_ADC16_PARAMS_ADC16_PARA33] + adc16_params[i - 1];
102     }
103 
104     param02 = (param01 + adc16_params[ADC16_ADC16_PARAMS_ADC16_PARA31] + adc16_params[ADC16_ADC16_PARAMS_ADC16_PARA32]) >> 6;
105     param64 = 0x10000ll * param02;
106     param64 = param64 / (0x20000 - param02 / 2);
107     param32 = (uint32_t)param64;
108 
109     for (i = 0; i < ADC16_SOC_PARAMS_LEN; i++) {
110         adc16_params[i] >>= 6;
111     }
112 
113     /* Enable ADC config clock */
114     ptr->ANA_CTRL0 |= ADC16_ANA_CTRL0_ADC_CLK_ON_MASK;
115 
116     ptr->CONV_CFG1 = (ptr->CONV_CFG1 & ~ADC16_CONV_CFG1_CLOCK_DIVIDER_MASK)
117                    | ADC16_CONV_CFG1_CLOCK_DIVIDER_SET(1);
118 
119     /* Write parameters */
120     for (i = 0; i < ADC16_SOC_PARAMS_LEN ; i++) {
121         ptr->ADC16_PARAMS[i] = (uint16_t)(adc16_params[i]);
122     }
123 
124     /* Set ADC16 Config0 */
125     temp = ptr->ADC16_CONFIG0;
126 
127     temp &= ~(ADC16_ADC16_CONFIG0_CAL_AVG_CFG_MASK | ADC16_ADC16_CONFIG0_CONV_PARAM_MASK);
128 
129     temp |= ADC16_ADC16_CONFIG0_REG_EN_MASK
130          |  ADC16_ADC16_CONFIG0_BANDGAP_EN_MASK
131          |  ADC16_ADC16_CONFIG0_CAL_AVG_CFG_MASK
132          |  ADC16_ADC16_CONFIG0_CONV_PARAM_SET(param32);
133 
134     ptr->ADC16_CONFIG0 = temp;
135 
136     /* Recover input clock divider */
137     ptr->CONV_CFG1 = (ptr->CONV_CFG1 & ~ADC16_CONV_CFG1_CLOCK_DIVIDER_MASK)
138                    | ADC16_CONV_CFG1_CLOCK_DIVIDER_SET(clk_div_temp);
139 
140     /* Disable ADC config clock */
141     ptr->ANA_CTRL0 &= ~ADC16_ANA_CTRL0_ADC_CLK_ON_MASK;
142 
143     return status_success;
144 }
145 
adc16_deinit(ADC16_Type * ptr)146 hpm_stat_t adc16_deinit(ADC16_Type *ptr)
147 {
148     /* disable all interrupts */
149     ptr->INT_EN = 0;
150 
151     return status_success;
152 }
153 
adc16_init(ADC16_Type * ptr,adc16_config_t * config)154 hpm_stat_t adc16_init(ADC16_Type *ptr, adc16_config_t *config)
155 {
156     uint32_t clk_div_temp;
157 
158     /* Set convert clock number and clock period */
159     if (config->adc_clk_div - 1 > ADC16_CONV_CFG1_CLOCK_DIVIDER_MASK)  {
160         return status_invalid_argument;
161     }
162 
163     /* Set ADC minimum conversion cycle and ADC clock divider */
164     ptr->CONV_CFG1 = ADC16_CONV_CFG1_CONVERT_CLOCK_NUMBER_SET(config->res)
165                    | ADC16_CONV_CFG1_CLOCK_DIVIDER_SET(config->adc_clk_div - 1);
166 
167     /* Set ahb_en */
168     /* Set the duration of the conversion */
169     ptr->ADC_CFG0 = ADC16_ADC_CFG0_SEL_SYNC_AHB_SET(config->sel_sync_ahb)
170                   | ADC16_ADC_CFG0_ADC_AHB_EN_SET(config->adc_ahb_en)
171                   | ADC16_ADC_CFG0_PORT3_REALTIME_SET(config->port3_realtime);
172 
173     /* Set wait_dis */
174     ptr->BUF_CFG0 = ADC16_BUF_CFG0_WAIT_DIS_SET(config->wait_dis);
175 
176     /* Get input clock divider */
177     clk_div_temp = ADC16_CONV_CFG1_CLOCK_DIVIDER_GET(ptr->CONV_CFG1);
178 
179     /* Set input clock divider temporarily */
180     ptr->CONV_CFG1 = (ptr->CONV_CFG1 & ~ADC16_CONV_CFG1_CLOCK_DIVIDER_MASK)
181                    | ADC16_CONV_CFG1_CLOCK_DIVIDER_SET(1);
182 
183     /* Enable ADC config clock */
184     ptr->ANA_CTRL0 |= ADC16_ANA_CTRL0_ADC_CLK_ON_MASK;
185 
186     /* Set end count */
187     ptr->ADC16_CONFIG1 &= ~ADC16_ADC16_CONFIG1_COV_END_CNT_MASK;
188     ptr->ADC16_CONFIG1 |= ADC16_ADC16_CONFIG1_COV_END_CNT_SET(ADC16_SOC_MAX_CONV_CLK_NUM - config->res + 1);
189 
190     /* Disable ADC config clock */
191     ptr->ANA_CTRL0 &= ~ADC16_ANA_CTRL0_ADC_CLK_ON_MASK;
192 
193     /* Recover input clock divider */
194     ptr->CONV_CFG1 = (ptr->CONV_CFG1 & ~ADC16_CONV_CFG1_CLOCK_DIVIDER_MASK)
195                    | ADC16_CONV_CFG1_CLOCK_DIVIDER_SET(clk_div_temp);
196 
197     /* Do a calibration */
198     adc16_do_calibration(ptr);
199 
200     return status_success;
201 }
202 
adc16_init_channel(ADC16_Type * ptr,adc16_channel_config_t * config)203 hpm_stat_t adc16_init_channel(ADC16_Type *ptr, adc16_channel_config_t *config)
204 {
205     /* Check the specified channel number */
206     if (ADC16_IS_CHANNEL_INVALID(config->ch)) {
207         return status_invalid_argument;
208     }
209 
210     /* Check sample cycle */
211     if (ADC16_IS_CHANNEL_SAMPLE_CYCLE_INVALID(config->sample_cycle)) {
212         return status_invalid_argument;
213     }
214 
215     /* Set warning threshold */
216     ptr->PRD_CFG[config->ch].PRD_THSHD_CFG = ADC16_PRD_CFG_PRD_THSHD_CFG_THSHDH_SET(config->thshdh)
217                                            | ADC16_PRD_CFG_PRD_THSHD_CFG_THSHDL_SET(config->thshdl);
218 
219     /* Set ADC sample cycles multiple */
220     /* Set ADC sample cycles */
221     ptr->SAMPLE_CFG[config->ch] = ADC16_SAMPLE_CFG_SAMPLE_CLOCK_NUMBER_SHIFT_SET(config->sample_cycle_shift)
222                                 | ADC16_SAMPLE_CFG_SAMPLE_CLOCK_NUMBER_SET(config->sample_cycle);
223 
224     /* Enable watchdog interrupt */
225     if (config->wdog_int_en) {
226         ptr->INT_EN |= 1 << config->ch;
227     }
228 
229     return status_success;
230 }
231 
adc16_get_channel_threshold(ADC16_Type * ptr,uint8_t ch,adc16_channel_threshold_t * config)232 hpm_stat_t adc16_get_channel_threshold(ADC16_Type *ptr, uint8_t ch, adc16_channel_threshold_t *config)
233 {
234     /* Check the specified channel number */
235     if (ADC16_IS_CHANNEL_INVALID(ch)) {
236         return status_invalid_argument;
237     }
238 
239     config->ch     = ch;
240     config->thshdh = ADC16_PRD_CFG_PRD_THSHD_CFG_THSHDH_GET(ptr->PRD_CFG[ch].PRD_THSHD_CFG);
241     config->thshdl = ADC16_PRD_CFG_PRD_THSHD_CFG_THSHDL_GET(ptr->PRD_CFG[ch].PRD_THSHD_CFG);
242 
243     return status_success;
244 }
245 
246 #if defined(ADC_SOC_BUSMODE_ENABLE_CTRL_SUPPORT) && ADC_SOC_BUSMODE_ENABLE_CTRL_SUPPORT
adc16_enable_oneshot_mode(ADC16_Type * ptr)247 void adc16_enable_oneshot_mode(ADC16_Type *ptr)
248 {
249     ptr->BUF_CFG0 |= ADC16_BUF_CFG0_BUS_MODE_EN_MASK;
250 }
251 
adc16_disable_oneshot_mode(ADC16_Type * ptr)252 void adc16_disable_oneshot_mode(ADC16_Type *ptr)
253 {
254     ptr->BUF_CFG0 &= ~ADC16_BUF_CFG0_BUS_MODE_EN_MASK;
255 }
256 #endif
257 
adc16_init_seq_dma(ADC16_Type * ptr,adc16_dma_config_t * dma_config)258 hpm_stat_t adc16_init_seq_dma(ADC16_Type *ptr, adc16_dma_config_t *dma_config)
259 {
260      /* Check the DMA buffer length  */
261     if (ADC16_IS_SEQ_DMA_BUFF_LEN_INVLAID(dma_config->buff_len_in_4bytes)) {
262         return status_invalid_argument;
263     }
264 
265     /* Reset ADC DMA  */
266     ptr->SEQ_DMA_CFG |= ADC16_SEQ_DMA_CFG_DMA_RST_MASK;
267 
268     /* Reset memory to clear all of cycle bits */
269     memset(dma_config->start_addr, 0x00, dma_config->buff_len_in_4bytes * sizeof(uint32_t));
270 
271     /* De-reset ADC DMA */
272     ptr->SEQ_DMA_CFG &= ~ADC16_SEQ_DMA_CFG_DMA_RST_MASK;
273 
274     /* Set ADC DMA target address which should be 4-byte aligned */
275     ptr->SEQ_DMA_ADDR = (uint32_t)dma_config->start_addr & ADC16_SEQ_DMA_ADDR_TAR_ADDR_MASK;
276 
277     /* Set ADC DMA memory dword length */
278     ptr->SEQ_DMA_CFG = (ptr->SEQ_DMA_CFG & ~ADC16_SEQ_DMA_CFG_BUF_LEN_MASK)
279                      | ADC16_SEQ_DMA_CFG_BUF_LEN_SET(dma_config->buff_len_in_4bytes - 1);
280 
281     #if defined(ADC_SOC_SEQ_HCFG_EN) && ADC_SOC_SEQ_HCFG_EN
282     /* Set high-half buffer length */
283     ptr->SEQ_HIGH_CFG = (ptr->SEQ_HIGH_CFG & ~ADC16_SEQ_HIGH_CFG_BUF_LEN_HIGH_MASK)
284                       | ADC16_SEQ_HIGH_CFG_BUF_LEN_HIGH_SET(((dma_config->buff_len_in_4bytes - 1) >> 12));
285     #endif
286 
287     /* Set stop_en and stop_pos */
288     if (dma_config->stop_en) {
289         ptr->SEQ_DMA_CFG = (ptr->SEQ_DMA_CFG & ~ADC16_SEQ_DMA_CFG_STOP_POS_MASK)
290                          | ADC16_SEQ_DMA_CFG_STOP_EN_MASK
291                          | ADC16_SEQ_DMA_CFG_STOP_POS_SET(dma_config->stop_pos);
292 
293         #if defined(ADC_SOC_SEQ_HCFG_EN) && ADC_SOC_SEQ_HCFG_EN
294         ptr->SEQ_HIGH_CFG = (ptr->SEQ_HIGH_CFG & ~ADC16_SEQ_HIGH_CFG_STOP_POS_HIGH_MASK)
295                           | ADC16_SEQ_HIGH_CFG_STOP_POS_HIGH_SET(((dma_config->stop_pos) >> 12));
296         #endif
297     }
298 
299     return status_success;
300 }
301 
adc16_set_prd_config(ADC16_Type * ptr,adc16_prd_config_t * config)302 hpm_stat_t adc16_set_prd_config(ADC16_Type *ptr, adc16_prd_config_t *config)
303 {
304     /* Check the specified channel number */
305     if (ADC16_IS_CHANNEL_INVALID(config->ch)) {
306         return status_invalid_argument;
307     }
308 
309     /* Check the prescale */
310     if (config->prescale > (ADC16_PRD_CFG_PRD_CFG_PRESCALE_MASK >> ADC16_PRD_CFG_PRD_CFG_PRESCALE_SHIFT)) {
311         return status_invalid_argument;
312     }
313 
314     /* Set periodic prescale */
315     ptr->PRD_CFG[config->ch].PRD_CFG = (ptr->PRD_CFG[config->ch].PRD_CFG & ~ADC16_PRD_CFG_PRD_CFG_PRESCALE_MASK)
316                                      | ADC16_PRD_CFG_PRD_CFG_PRESCALE_SET(config->prescale);
317 
318     /* Set period count */
319     ptr->PRD_CFG[config->ch].PRD_CFG = (ptr->PRD_CFG[config->ch].PRD_CFG & ~ADC16_PRD_CFG_PRD_CFG_PRD_MASK)
320                                      | ADC16_PRD_CFG_PRD_CFG_PRD_SET(config->period_count);
321 
322     return status_success;
323 }
324 
adc16_trigger_seq_by_sw(ADC16_Type * ptr)325 hpm_stat_t adc16_trigger_seq_by_sw(ADC16_Type *ptr)
326 {
327     if (ADC16_INT_STS_SEQ_SW_CFLCT_GET(ptr->INT_STS)) {
328         return status_fail;
329     }
330     ptr->SEQ_CFG0 |= ADC16_SEQ_CFG0_SW_TRIG_MASK;
331 
332     return status_success;
333 }
334 
335 /* Note: the sequence length can not be larger or equal than 2 in HPM6750EVK Revision A0 */
adc16_set_seq_config(ADC16_Type * ptr,adc16_seq_config_t * config)336 hpm_stat_t adc16_set_seq_config(ADC16_Type *ptr, adc16_seq_config_t *config)
337 {
338     /* Check sequence length */
339     if (ADC16_IS_SEQ_LEN_INVLAID(config->seq_len)) {
340         return status_invalid_argument;
341     }
342 
343     ptr->SEQ_CFG0 = ADC16_SEQ_CFG0_SEQ_LEN_SET(config->seq_len - 1)
344                   | ADC16_SEQ_CFG0_RESTART_EN_SET(config->restart_en)
345                   | ADC16_SEQ_CFG0_CONT_EN_SET(config->cont_en)
346                   | ADC16_SEQ_CFG0_SW_TRIG_EN_SET(config->sw_trig_en)
347                   | ADC16_SEQ_CFG0_HW_TRIG_EN_SET(config->hw_trig_en);
348 
349     /* Set sequence queue */
350     for (int i = 0; i < config->seq_len; i++) {
351         /* Check the specified channel number */
352         if (ADC16_IS_CHANNEL_INVALID(config->queue[i].ch)) {
353             return status_invalid_argument;
354         }
355 
356         ptr->SEQ_QUE[i] = ADC16_SEQ_QUE_SEQ_INT_EN_SET(config->queue[i].seq_int_en)
357                         | ADC16_SEQ_QUE_CHAN_NUM_4_0_SET(config->queue[i].ch);
358     }
359 
360     return status_success;
361 }
362 
adc16_trigger_pmt_by_sw(ADC16_Type * ptr,uint8_t trig_ch)363 hpm_stat_t adc16_trigger_pmt_by_sw(ADC16_Type *ptr, uint8_t trig_ch)
364 {
365     ptr->TRG_SW_STA = ADC16_TRG_SW_STA_TRG_SW_STA_MASK | ADC16_TRG_SW_STA_TRIG_SW_INDEX_SET(trig_ch);
366 
367     return status_success;
368 }
369 
adc16_set_pmt_config(ADC16_Type * ptr,adc16_pmt_config_t * config)370 hpm_stat_t adc16_set_pmt_config(ADC16_Type *ptr, adc16_pmt_config_t *config)
371 {
372     uint32_t temp = 0;
373 
374     /* Check the specified trigger length */
375     if (ADC16_IS_TRIG_LEN_INVLAID(config->trig_len)) {
376         return status_invalid_argument;
377     }
378 
379     /* Check the triggier channel */
380     if (ADC16_IS_TRIG_CH_INVLAID(config->trig_ch)) {
381         return status_invalid_argument;
382     }
383 
384     temp |= ADC16_CONFIG_TRIG_LEN_SET(config->trig_len - 1);
385 
386     for (int i = 0; i < config->trig_len; i++) {
387         if (ADC16_IS_CHANNEL_INVALID(config->adc_ch[i])) {
388             return status_invalid_argument;
389         }
390 
391         temp |= config->inten[i] << (ADC16_CONFIG_INTEN0_SHIFT + i * ADC_SOC_CONFIG_INTEN_CHAN_BIT_SIZE)
392              |  config->adc_ch[i] << (ADC16_CONFIG_CHAN0_SHIFT + i * ADC_SOC_CONFIG_INTEN_CHAN_BIT_SIZE);
393     }
394 
395     ptr->CONFIG[config->trig_ch] = temp;
396 
397     return status_success;
398 }
399 
adc16_set_pmt_queue_enable(ADC16_Type * ptr,uint8_t trig_ch,bool enable)400 hpm_stat_t adc16_set_pmt_queue_enable(ADC16_Type *ptr, uint8_t trig_ch, bool enable)
401 {
402     (void) ptr;
403     /* Check the specified trigger channel */
404     if (ADC16_IS_TRIG_CH_INVLAID(trig_ch)) {
405         return status_invalid_argument;
406     }
407 
408 #if defined(ADC_SOC_PREEMPT_ENABLE_CTRL_SUPPORT) && ADC_SOC_PREEMPT_ENABLE_CTRL_SUPPORT
409     /* Set queue enable control */
410     ptr->CONFIG[trig_ch] &= ~ADC16_CONFIG_QUEUE_EN_MASK;
411     ptr->CONFIG[trig_ch] |= ADC16_CONFIG_QUEUE_EN_SET(enable);
412     return status_success;
413 #else
414     (void) enable;
415     return status_success;
416 #endif
417 }
418 
419 /* one shot mode */
adc16_get_oneshot_result(ADC16_Type * ptr,uint8_t ch,uint16_t * result)420 hpm_stat_t adc16_get_oneshot_result(ADC16_Type *ptr, uint8_t ch, uint16_t *result)
421 {
422     uint32_t bus_res;
423 
424     /* Check the specified channel number */
425     if (ADC16_IS_CHANNEL_INVALID(ch)) {
426         return status_invalid_argument;
427     }
428 
429     bus_res = ptr->BUS_RESULT[ch];
430     *result = ADC16_BUS_RESULT_CHAN_RESULT_GET(bus_res);
431 
432     if (ADC16_BUF_CFG0_WAIT_DIS_GET(ptr->BUF_CFG0)) {
433         if (!ADC16_BUS_RESULT_VALID_GET(bus_res)) {
434             return status_fail;
435         }
436     }
437 
438     return status_success;
439 }
440 
441 /* period mode */
adc16_get_prd_result(ADC16_Type * ptr,uint8_t ch,uint16_t * result)442 hpm_stat_t adc16_get_prd_result(ADC16_Type *ptr, uint8_t ch, uint16_t *result)
443 {
444     /* Check the specified channel number */
445     if (ADC16_IS_CHANNEL_INVALID(ch)) {
446         return status_invalid_argument;
447     }
448 
449     *result = ADC16_PRD_CFG_PRD_RESULT_CHAN_RESULT_GET(ptr->PRD_CFG[ch].PRD_RESULT);
450 
451     return status_success;
452 }
453 
454 #if defined(ADC16_SOC_TEMP_CH_EN) && ADC16_SOC_TEMP_CH_EN
adc16_enable_temp_sensor(ADC16_Type * ptr)455 void adc16_enable_temp_sensor(ADC16_Type *ptr)
456 {
457     uint32_t clk_div_temp;
458 
459     /* Get input clock divider */
460     clk_div_temp = ADC16_CONV_CFG1_CLOCK_DIVIDER_GET(ptr->CONV_CFG1);
461 
462     /* Set input clock divider temporarily */
463     ptr->CONV_CFG1 = (ptr->CONV_CFG1 & ~ADC16_CONV_CFG1_CLOCK_DIVIDER_MASK) | ADC16_CONV_CFG1_CLOCK_DIVIDER_SET(1);
464 
465     /* Enable ADC config clock */
466     ptr->ANA_CTRL0 |= ADC16_ANA_CTRL0_ADC_CLK_ON_MASK;
467 
468     /* Enable the temperature sensor */
469     ptr->ADC16_CONFIG0 |= ADC16_ADC16_CONFIG0_TEMPSNS_EN_MASK | ADC16_ADC16_CONFIG0_REG_EN_MASK
470                         | ADC16_ADC16_CONFIG0_BANDGAP_EN_MASK | ADC16_ADC16_CONFIG0_CAL_AVG_CFG_SET(5);
471 
472     /* Disable ADC config clock */
473     ptr->ANA_CTRL0 &= ~ADC16_ANA_CTRL0_ADC_CLK_ON_MASK;
474 
475     /* Recover input clock divider */
476     ptr->CONV_CFG1 = (ptr->CONV_CFG1 & ~ADC16_CONV_CFG1_CLOCK_DIVIDER_MASK) | ADC16_CONV_CFG1_CLOCK_DIVIDER_SET(clk_div_temp);
477 }
478 
adc16_disable_temp_sensor(ADC16_Type * ptr)479 void adc16_disable_temp_sensor(ADC16_Type *ptr)
480 {
481     uint32_t clk_div_temp;
482 
483     /* Get input clock divider */
484     clk_div_temp = ADC16_CONV_CFG1_CLOCK_DIVIDER_GET(ptr->CONV_CFG1);
485 
486     /* Set input clock divider temporarily */
487     ptr->CONV_CFG1 = (ptr->CONV_CFG1 & ~ADC16_CONV_CFG1_CLOCK_DIVIDER_MASK)
488                    | ADC16_CONV_CFG1_CLOCK_DIVIDER_SET(1);
489 
490     /* Enable ADC config clock */
491     ptr->ANA_CTRL0 |= ADC16_ANA_CTRL0_ADC_CLK_ON_MASK;
492 
493     /* Disable the temp sensor */
494     ptr->ADC16_CONFIG0 &= ~ADC16_ADC16_CONFIG0_TEMPSNS_EN_MASK;
495 
496     /* Disable ADC config clock */
497     ptr->ANA_CTRL0 &= ~ADC16_ANA_CTRL0_ADC_CLK_ON_MASK;
498 
499     /* Recover input clock divider */
500     ptr->CONV_CFG1 = (ptr->CONV_CFG1 & ~ADC16_CONV_CFG1_CLOCK_DIVIDER_MASK)
501                    | ADC16_CONV_CFG1_CLOCK_DIVIDER_SET(clk_div_temp);
502 }
503 #endif
504