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