1 /******************************************************************************
2  *
3  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4  * Analog Devices, Inc.),
5  * Copyright (C) 2023-2024 Analog Devices, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************************/
20 #include <stdio.h>
21 #include "adc.h"
22 #include "adc_regs.h"
23 #include "adc_revb.h"
24 #include "gcr_regs.h"
25 #include "mxc_device.h"
26 #include "mxc_errors.h"
27 #include "mxc_assert.h"
28 #include "mxc_sys.h"
29 #include "mcr_regs.h"
30 #include "mxc_lock.h"
31 #include "mxc_pins.h"
32 #include "pwrseq_regs.h"
33 
34 #define MXC_F_MCR_ADC_CFG2_CH 0x3
35 
36 #define TEMP_FACTOR (double)530.582f / (double)4096.0f
37 #define TEMP_FACTOR1V25 (double)1.25f * TEMP_FACTOR
38 #define TEMP_FACTOR2V048 (double)2.048f * TEMP_FACTOR
39 
initGPIOForChannel(mxc_adc_chsel_t channel)40 static void initGPIOForChannel(mxc_adc_chsel_t channel)
41 {
42     switch (channel) {
43     case MXC_ADC_CH_0:
44         MXC_GPIO_Config(&gpio_cfg_adc_ain0);
45         break;
46 
47     case MXC_ADC_CH_1:
48         MXC_GPIO_Config(&gpio_cfg_adc_ain1);
49         break;
50 
51     case MXC_ADC_CH_2:
52         MXC_GPIO_Config(&gpio_cfg_adc_ain2);
53         break;
54 
55     case MXC_ADC_CH_3:
56         MXC_GPIO_Config(&gpio_cfg_adc_ain3);
57         break;
58 
59     case MXC_ADC_CH_4:
60         MXC_GPIO_Config(&gpio_cfg_adc_ain4);
61         break;
62 
63     case MXC_ADC_CH_5:
64         MXC_GPIO_Config(&gpio_cfg_adc_ain5);
65         break;
66 
67     case MXC_ADC_CH_6:
68         MXC_GPIO_Config(&gpio_cfg_adc_ain6);
69         break;
70 
71     case MXC_ADC_CH_7:
72         MXC_GPIO_Config(&gpio_cfg_adc_ain7);
73         break;
74 
75     case MXC_ADC_CH_8:
76         MXC_GPIO_Config(&gpio_cfg_adc_ain8);
77         break;
78 
79     case MXC_ADC_CH_9:
80         MXC_GPIO_Config(&gpio_cfg_adc_ain9);
81         break;
82 
83     case MXC_ADC_CH_10:
84         MXC_GPIO_Config(&gpio_cfg_adc_ain10);
85         break;
86 
87     case MXC_ADC_CH_11:
88         MXC_GPIO_Config(&gpio_cfg_adc_ain11);
89         break;
90 
91     default:
92         break;
93     }
94 }
95 
initGPIOforHWTrig(mxc_adc_trig_sel_t hwTrig)96 static void initGPIOforHWTrig(mxc_adc_trig_sel_t hwTrig)
97 {
98     mxc_gpio_cfg_t gpioCfg;
99     switch (hwTrig) {
100     case MXC_ADC_TRIG_SEL_TMR0:
101     case MXC_ADC_TRIG_SEL_TMR1:
102     case MXC_ADC_TRIG_SEL_TMR2:
103     case MXC_ADC_TRIG_SEL_TMR3:
104     case MXC_ADC_TRIG_SEL_TEMP_SENS:
105         break;
106     case MXC_ADC_TRIG_SEL_P0_29:
107         gpioCfg.port = MXC_GPIO0;
108         gpioCfg.mask = MXC_GPIO_PIN_29;
109         gpioCfg.func = MXC_GPIO_FUNC_ALT4;
110         gpioCfg.pad = MXC_GPIO_PAD_NONE;
111         gpioCfg.vssel = MXC_GPIO_VSSEL_VDDIO;
112         gpioCfg.drvstr = MXC_GPIO_DRVSTR_0;
113         MXC_GPIO_Config(&gpioCfg);
114         break;
115     case MXC_ADC_TRIG_SEL_P0_22:
116         gpioCfg.port = MXC_GPIO0;
117         gpioCfg.mask = MXC_GPIO_PIN_22;
118         gpioCfg.func = MXC_GPIO_FUNC_ALT2;
119         gpioCfg.pad = MXC_GPIO_PAD_NONE;
120         gpioCfg.vssel = MXC_GPIO_VSSEL_VDDIO;
121         gpioCfg.drvstr = MXC_GPIO_DRVSTR_0;
122         MXC_GPIO_Config(&gpioCfg);
123         break;
124     case MXC_ADC_TRIG_SEL_P1_4:
125         gpioCfg.port = MXC_GPIO1;
126         gpioCfg.mask = MXC_GPIO_PIN_4;
127         gpioCfg.func = MXC_GPIO_FUNC_ALT4;
128         gpioCfg.pad = MXC_GPIO_PAD_NONE;
129         gpioCfg.vssel = MXC_GPIO_VSSEL_VDDIO;
130         gpioCfg.drvstr = MXC_GPIO_DRVSTR_0;
131         MXC_GPIO_Config(&gpioCfg);
132         break;
133     }
134 }
135 
MXC_ADC_Init(mxc_adc_req_t * req)136 int MXC_ADC_Init(mxc_adc_req_t *req)
137 {
138 #ifndef MSDK_NO_GPIO_CLK_INIT
139     /* ADC in reset state */
140     switch (req->clock) {
141     case MXC_ADC_CLK_HCLK:
142         break;
143     case MXC_ADC_CLK_EXT:
144         MXC_GPIO_Config(&gpio_cfg_hfextclk);
145         MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_EXTCLK);
146         break;
147     case MXC_ADC_CLK_IBRO:
148         MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IBRO);
149         break;
150     case MXC_ADC_CLK_ERFO:
151         MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_ERFO);
152         break;
153     default:
154         return E_BAD_PARAM;
155     }
156 
157     MXC_SYS_Reset_Periph(MXC_SYS_RESET0_ADC);
158     MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_ADC);
159 
160     /* This is required for temperature sensor only */
161     MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IBRO);
162 #endif
163 
164     MXC_ADC_ReferenceSelect(req->ref);
165 
166     return MXC_ADC_RevB_Init((mxc_adc_revb_regs_t *)MXC_ADC, req);
167 }
168 
MXC_ADC_Shutdown(void)169 int MXC_ADC_Shutdown(void)
170 {
171     MXC_ADC_RevB_Shutdown((mxc_adc_revb_regs_t *)MXC_ADC);
172 
173     MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_ADC);
174 
175     return E_NO_ERROR;
176 }
177 
MXC_ADC_EnableInt(uint32_t flags)178 void MXC_ADC_EnableInt(uint32_t flags)
179 {
180     MXC_ADC_RevB_EnableInt((mxc_adc_revb_regs_t *)MXC_ADC, flags);
181 }
182 
MXC_ADC_DisableInt(uint32_t flags)183 void MXC_ADC_DisableInt(uint32_t flags)
184 {
185     MXC_ADC_RevB_DisableInt((mxc_adc_revb_regs_t *)MXC_ADC, flags);
186 }
187 
MXC_ADC_GetFlags(void)188 int MXC_ADC_GetFlags(void)
189 {
190     return MXC_ADC_RevB_GetFlags((mxc_adc_revb_regs_t *)MXC_ADC);
191 }
192 
MXC_ADC_ClearFlags(uint32_t flags)193 void MXC_ADC_ClearFlags(uint32_t flags)
194 {
195     MXC_ADC_RevB_ClearFlags((mxc_adc_revb_regs_t *)MXC_ADC, flags);
196 }
197 
MXC_ADC_ClockSelect(mxc_adc_clock_t clock)198 void MXC_ADC_ClockSelect(mxc_adc_clock_t clock)
199 {
200     MXC_ADC_RevB_ClockSelect((mxc_adc_revb_regs_t *)MXC_ADC, clock);
201 }
202 
MXC_ADC_StartConversion(void)203 int MXC_ADC_StartConversion(void)
204 {
205     return MXC_ADC_RevB_StartConversion((mxc_adc_revb_regs_t *)MXC_ADC);
206 }
207 
MXC_ADC_StartConversionAsync(mxc_adc_complete_cb_t callback)208 int MXC_ADC_StartConversionAsync(mxc_adc_complete_cb_t callback)
209 {
210     return MXC_ADC_RevB_StartConversionAsync((mxc_adc_revb_regs_t *)MXC_ADC, callback);
211 }
212 
MXC_ADC_StartConversionDMA(mxc_adc_conversion_req_t * req,int * data,void (* callback)(int,int))213 int MXC_ADC_StartConversionDMA(mxc_adc_conversion_req_t *req, int *data, void (*callback)(int, int))
214 {
215     return MXC_ADC_RevB_StartConversionDMA((mxc_adc_revb_regs_t *)MXC_ADC, req, data, callback);
216 }
217 
MXC_ADC_Handler(void)218 int MXC_ADC_Handler(void)
219 {
220     return MXC_ADC_RevB_Handler((mxc_adc_revb_regs_t *)MXC_ADC);
221 }
222 
MXC_ADC_GetData(int * outdata)223 int MXC_ADC_GetData(int *outdata)
224 {
225     return MXC_ADC_RevB_GetData((mxc_adc_revb_regs_t *)MXC_ADC, outdata);
226 }
227 
MXC_ADC_ReferenceSelect(mxc_adc_refsel_t ref)228 int MXC_ADC_ReferenceSelect(mxc_adc_refsel_t ref)
229 {
230     switch (ref) {
231     case MXC_ADC_REF_EXT:
232         MXC_MCR->adc_cfg0 |= MXC_F_MCR_ADC_CFG0_EXT_REF;
233         break;
234     case MXC_ADC_REF_INT_1V25:
235         MXC_MCR->adc_cfg0 &= ~(MXC_F_MCR_ADC_CFG0_EXT_REF | MXC_F_MCR_ADC_CFG0_REF_SEL);
236         break;
237     case MXC_ADC_REF_INT_2V048:
238         MXC_MCR->adc_cfg0 &= ~MXC_F_MCR_ADC_CFG0_EXT_REF;
239         MXC_MCR->adc_cfg0 |= MXC_F_MCR_ADC_CFG0_REF_SEL;
240         break;
241     default:
242         return E_BAD_PARAM;
243     }
244 
245     return E_NO_ERROR;
246 }
247 
MXC_ADC_DynamicModeEn(mxc_adc_chsel_t ch)248 int MXC_ADC_DynamicModeEn(mxc_adc_chsel_t ch)
249 {
250     if (ch > MAX_ADC_RES_DIV_CH) {
251         return E_BAD_PARAM;
252     }
253 
254     MXC_MCR->adc_cfg1 |= (1 << ch);
255 
256     return E_NO_ERROR;
257 }
258 
MXC_ADC_DynamicModeDis(mxc_adc_chsel_t ch)259 int MXC_ADC_DynamicModeDis(mxc_adc_chsel_t ch)
260 {
261     if (ch > MAX_ADC_RES_DIV_CH) {
262         return E_BAD_PARAM;
263     }
264 
265     MXC_MCR->adc_cfg1 &= ~(1 << ch);
266 
267     return E_NO_ERROR;
268 }
269 
MXC_ADC_InputDividerSelect(mxc_adc_chsel_t ch,mxc_adc_divsel_t div,mxc_adc_dynamic_pullup_t lpEn)270 int MXC_ADC_InputDividerSelect(mxc_adc_chsel_t ch, mxc_adc_divsel_t div,
271                                mxc_adc_dynamic_pullup_t lpEn)
272 {
273     uint32_t bitOffset;
274 
275     if (ch > MXC_ADC_CH_12 || div > MXC_ADC_DIV2_50K) {
276         return E_BAD_PARAM;
277     }
278 
279     bitOffset = ch << 1;
280     MXC_MCR->adc_cfg2 &= ~(MXC_F_MCR_ADC_CFG2_CH << bitOffset);
281     MXC_MCR->adc_cfg2 |= (div << bitOffset);
282 
283     if (lpEn == MXC_ADC_PY_DN_DISABLE) {
284         MXC_ADC_DynamicModeDis(ch);
285     } else {
286         MXC_ADC_DynamicModeEn(ch);
287     }
288 
289     return E_NO_ERROR;
290 }
291 
MXC_ADC_LowPowerModeDividerSelect(mxc_adc_div_lpmode_t div_lpmode)292 int MXC_ADC_LowPowerModeDividerSelect(mxc_adc_div_lpmode_t div_lpmode)
293 {
294     MXC_MCR->adc_cfg0 &= ~(MXC_F_MCR_ADC_CFG0_LP_5K_DIS | MXC_F_MCR_ADC_CFG0_LP_50K_DIS);
295     MXC_MCR->adc_cfg0 |= div_lpmode;
296 
297     return E_NO_ERROR;
298 }
299 
MXC_ADC_EnableConversion(void)300 void MXC_ADC_EnableConversion(void)
301 {
302     MXC_ADC_RevB_EnableConversion((mxc_adc_revb_regs_t *)MXC_ADC);
303 }
304 
MXC_ADC_DisableConversion(void)305 void MXC_ADC_DisableConversion(void)
306 {
307     MXC_ADC_RevB_DisableConversion((mxc_adc_revb_regs_t *)MXC_ADC);
308 }
309 
MXC_ADC_TS_SelectEnable(void)310 void MXC_ADC_TS_SelectEnable(void)
311 {
312     MXC_ADC_RevB_TS_SelectEnable((mxc_adc_revb_regs_t *)MXC_ADC);
313 }
314 
MXC_ADC_TS_SelectDisable(void)315 void MXC_ADC_TS_SelectDisable(void)
316 {
317     MXC_ADC_RevB_TS_SelectDisable((mxc_adc_revb_regs_t *)MXC_ADC);
318 }
319 
MXC_ADC_FIFO_Level(void)320 uint16_t MXC_ADC_FIFO_Level(void)
321 {
322     return MXC_ADC_RevB_FIFO_Level((mxc_adc_revb_regs_t *)MXC_ADC);
323 }
324 
MXC_ADC_FIFO_Threshold_Config(uint32_t fifo_threshold)325 int MXC_ADC_FIFO_Threshold_Config(uint32_t fifo_threshold)
326 {
327     return MXC_ADC_RevB_FIFO_Threshold_Config((mxc_adc_revb_regs_t *)MXC_ADC, fifo_threshold);
328 }
329 
MXC_ADC_AverageConfig(mxc_adc_avg_t avg_number)330 int MXC_ADC_AverageConfig(mxc_adc_avg_t avg_number)
331 {
332     return MXC_ADC_RevB_AverageConfig((mxc_adc_revb_regs_t *)MXC_ADC, avg_number);
333 }
334 
MXC_ADC_Clear_ChannelSelect(void)335 void MXC_ADC_Clear_ChannelSelect(void)
336 {
337     MXC_ADC_RevB_Clear_ChannelSelect((mxc_adc_revb_regs_t *)MXC_ADC);
338 }
339 
MXC_ADC_TriggerConfig(mxc_adc_conversion_req_t * req)340 void MXC_ADC_TriggerConfig(mxc_adc_conversion_req_t *req)
341 {
342     initGPIOforHWTrig(req->hwTrig);
343     MXC_ADC_RevB_TriggerConfig((mxc_adc_revb_regs_t *)MXC_ADC, req);
344 }
345 
MXC_ADC_ConversionModeConfig(mxc_adc_conversion_req_t * req)346 void MXC_ADC_ConversionModeConfig(mxc_adc_conversion_req_t *req)
347 {
348     MXC_ADC_RevB_ConversionModeConfig((mxc_adc_revb_regs_t *)MXC_ADC, req);
349 }
350 
MXC_ADC_SetConversionDelay(int delay)351 void MXC_ADC_SetConversionDelay(int delay)
352 {
353     MXC_ADC_RevB_SetConversionDelay((mxc_adc_revb_regs_t *)MXC_ADC, delay);
354 }
355 
MXC_ADC_SlotsConfig(mxc_adc_conversion_req_t * req)356 int MXC_ADC_SlotsConfig(mxc_adc_conversion_req_t *req)
357 {
358     return MXC_ADC_RevB_SlotsConfig((mxc_adc_revb_regs_t *)MXC_ADC, req);
359 }
360 
MXC_ADC_ChSelectConfig(mxc_adc_chsel_t ch,uint32_t slot_num)361 int MXC_ADC_ChSelectConfig(mxc_adc_chsel_t ch, uint32_t slot_num)
362 {
363     return MXC_ADC_RevB_ChSelectConfig((mxc_adc_revb_regs_t *)MXC_ADC, ch, slot_num);
364 }
365 
MXC_ADC_Configuration(mxc_adc_conversion_req_t * req)366 int MXC_ADC_Configuration(mxc_adc_conversion_req_t *req)
367 {
368     MXC_ADC_ConversionModeConfig(req);
369 
370     MXC_ADC_TriggerConfig(req);
371 
372     MXC_ADC_FIFO_Threshold_Config(req->fifo_threshold);
373 
374     MXC_ADC_SlotsConfig(req);
375 
376     MXC_ADC_Clear_ChannelSelect();
377 
378     //number of samples to average
379     MXC_ADC_AverageConfig(req->avg_number);
380 
381     MXC_ADC_LowPowerModeDividerSelect(req->lpmode_divder);
382 
383     return E_NO_ERROR;
384 }
385 
MXC_ADC_SlotConfiguration(mxc_adc_slot_req_t * req,uint32_t slot_length)386 int MXC_ADC_SlotConfiguration(mxc_adc_slot_req_t *req, uint32_t slot_length)
387 {
388     uint32_t loop_counter = 0;
389 
390     for (loop_counter = 0; loop_counter <= slot_length; loop_counter++) {
391         initGPIOForChannel(req->channel);
392 
393         if (req->channel <= MAX_ADC_RES_DIV_CH) {
394             MXC_ADC_InputDividerSelect(req->channel, req->div, req->pullup_dyn);
395         }
396 
397         MXC_ADC_ChSelectConfig(req->channel, loop_counter);
398         req++;
399     }
400     return E_NO_ERROR;
401 }
402 
MXC_ConvertTemperature_ToK(uint16_t tempSensor_Readout,mxc_adc_refsel_t ref,float ext_ref,float * temp_k)403 int MXC_ConvertTemperature_ToK(uint16_t tempSensor_Readout, mxc_adc_refsel_t ref, float ext_ref,
404                                float *temp_k)
405 {
406     switch (ref) {
407     case MXC_ADC_REF_EXT:
408         *temp_k = (double)tempSensor_Readout * (double)TEMP_FACTOR * (double)ext_ref;
409         break;
410 
411     case MXC_ADC_REF_INT_1V25:
412         *temp_k = tempSensor_Readout * TEMP_FACTOR1V25;
413         break;
414 
415     case MXC_ADC_REF_INT_2V048:
416         *temp_k = tempSensor_Readout * TEMP_FACTOR2V048;
417         break;
418 
419     default:
420         return E_BAD_PARAM;
421     }
422     return E_NO_ERROR;
423 }
424 
MXC_ConvertTemperature_ToC(uint16_t tempSensor_Readout,mxc_adc_refsel_t ref,float ext_ref,float * temp)425 int MXC_ConvertTemperature_ToC(uint16_t tempSensor_Readout, mxc_adc_refsel_t ref, float ext_ref,
426                                float *temp)
427 {
428     if (MXC_ConvertTemperature_ToK(tempSensor_Readout, ref, ext_ref, temp) == E_NO_ERROR) {
429         *temp = *temp - 273.15f;
430         return E_NO_ERROR;
431     } else {
432         return E_BAD_PARAM;
433     }
434 }
435 
MXC_ConvertTemperature_ToF(uint16_t tempSensor_Readout,mxc_adc_refsel_t ref,float ext_ref,float * temp)436 int MXC_ConvertTemperature_ToF(uint16_t tempSensor_Readout, mxc_adc_refsel_t ref, float ext_ref,
437                                float *temp)
438 {
439     if (MXC_ConvertTemperature_ToK(tempSensor_Readout, ref, ext_ref, temp) == E_NO_ERROR) {
440         *temp = (*temp * 1.8f) - 459.67f;
441         return E_NO_ERROR;
442     } else {
443         return E_BAD_PARAM;
444     }
445 }
446 
MXC_ADC_EnableComparator(mxc_adc_comp_t comp,mxc_adc_chsel_t negCh,mxc_adc_chsel_t posCh)447 int MXC_ADC_EnableComparator(mxc_adc_comp_t comp, mxc_adc_chsel_t negCh, mxc_adc_chsel_t posCh)
448 {
449     if (negCh > MXC_ADC_CH_3) {
450         return E_BAD_PARAM;
451     }
452 
453     if (posCh < MXC_ADC_CH_4 || posCh > MXC_ADC_CH_7) {
454         return E_BAD_PARAM;
455     }
456 
457     initGPIOForChannel(negCh);
458     initGPIOForChannel(posCh);
459 
460     switch (comp) {
461     case MXC_ADC_COMP_0:
462         MXC_SETFIELD(MXC_MCR->aincomp, MXC_F_MCR_AINCOMP_NSEL_COMP0,
463                      (1 << negCh) << MXC_F_MCR_AINCOMP_NSEL_COMP0_POS);
464         MXC_SETFIELD(MXC_MCR->aincomp, MXC_F_MCR_AINCOMP_PSEL_COMP0,
465                      (1 << posCh % 4) << MXC_F_MCR_AINCOMP_PSEL_COMP0_POS);
466         break;
467     case MXC_ADC_COMP_1:
468         MXC_SETFIELD(MXC_MCR->aincomp, MXC_F_MCR_AINCOMP_NSEL_COMP1,
469                      (1 << negCh) << MXC_F_MCR_AINCOMP_NSEL_COMP1_POS);
470         MXC_SETFIELD(MXC_MCR->aincomp, MXC_F_MCR_AINCOMP_PSEL_COMP1,
471                      (1 << posCh % 4) << MXC_F_MCR_AINCOMP_PSEL_COMP1_POS);
472         break;
473     default:
474         return E_BAD_PARAM;
475     }
476 
477     MXC_MCR->aincomp &= ~(comp << MXC_F_MCR_AINCOMP_PD_POS);
478 
479     return E_NO_ERROR;
480 }
481 
MXC_ADC_DisableComparator(mxc_adc_comp_t comp)482 int MXC_ADC_DisableComparator(mxc_adc_comp_t comp)
483 {
484     switch (comp) {
485     case MXC_ADC_COMP_0:
486         MXC_MCR->aincomp &= ~(MXC_F_MCR_AINCOMP_NSEL_COMP0 | MXC_F_MCR_AINCOMP_PSEL_COMP0);
487         break;
488     case MXC_ADC_COMP_1:
489         MXC_MCR->aincomp &= ~(MXC_F_MCR_AINCOMP_NSEL_COMP1 | MXC_F_MCR_AINCOMP_PSEL_COMP1);
490         break;
491     default:
492         return E_BAD_PARAM;
493     }
494 
495     MXC_MCR->aincomp |= (comp << MXC_F_MCR_AINCOMP_PD_POS);
496 
497     return E_NO_ERROR;
498 }
499 
500 //End
501