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 
21 #include <stdio.h>
22 #include "mxc_device.h"
23 #include "mxc_errors.h"
24 #include "mxc_assert.h"
25 #include "mxc_sys.h"
26 #include "adc.h"
27 #include "adc_regs.h"
28 #include "adc_revb.h"
29 #include "gcr_regs.h"
30 #include "mcr_regs.h"
31 #include "mxc_lock.h"
32 #include "mxc_pins.h"
33 #include "pwrseq_regs.h"
34 
35 /*TODO-
36  * This is work in progress file and has not finalized yet. Expected to change some parameters as well as some function prototypes.
37  */
38 
39 #define MXC_F_MCR_ADCCFG2_CH 0x3
40 #define TEMP_FACTOR 530.582f / 4096.0f
41 #define TEMP_FACTOR1V25 1.25f * TEMP_FACTOR
42 #define TEMP_FACTOR2V048 2.048f * TEMP_FACTOR
43 
initGPIOForChannel(mxc_adc_chsel_t channel)44 static void initGPIOForChannel(mxc_adc_chsel_t channel)
45 {
46     switch (channel) {
47     case MXC_ADC_CH_0:
48         MXC_GPIO_Config(&gpio_cfg_adc_ain0);
49         break;
50 
51     case MXC_ADC_CH_1:
52         MXC_GPIO_Config(&gpio_cfg_adc_ain1);
53         break;
54 
55     case MXC_ADC_CH_2:
56         MXC_GPIO_Config(&gpio_cfg_adc_ain2);
57         break;
58 
59     case MXC_ADC_CH_3:
60         MXC_GPIO_Config(&gpio_cfg_adc_ain3);
61         break;
62 
63     case MXC_ADC_CH_4:
64         MXC_GPIO_Config(&gpio_cfg_adc_ain4);
65         break;
66 
67     case MXC_ADC_CH_5:
68         MXC_GPIO_Config(&gpio_cfg_adc_ain5);
69         break;
70 
71     case MXC_ADC_CH_6:
72         MXC_GPIO_Config(&gpio_cfg_adc_ain6);
73         break;
74 
75     case MXC_ADC_CH_7:
76         MXC_GPIO_Config(&gpio_cfg_adc_ain7);
77         break;
78 
79     default:
80         break;
81     }
82 }
83 
initGPIOforHWTrig(mxc_adc_trig_sel_t hwTrig)84 static void initGPIOforHWTrig(mxc_adc_trig_sel_t hwTrig)
85 {
86     mxc_gpio_cfg_t gpioCfg;
87     switch (hwTrig) {
88     case MXC_ADC_TRIG_SEL_TMR0:
89     case MXC_ADC_TRIG_SEL_TMR1:
90     case MXC_ADC_TRIG_SEL_TMR2:
91     case MXC_ADC_TRIG_SEL_TMR3:
92     case MXC_ADC_TRIG_SEL_TEMP_SENS:
93         break;
94     case MXC_ADC_TRIG_SEL_P1_12:
95         gpioCfg.port = MXC_GPIO1;
96         gpioCfg.mask = MXC_GPIO_PIN_12;
97         gpioCfg.func = MXC_GPIO_FUNC_ALT2;
98         gpioCfg.pad = MXC_GPIO_PAD_NONE;
99         gpioCfg.vssel = MXC_GPIO_VSSEL_VDDIOH;
100         gpioCfg.drvstr = MXC_GPIO_DRVSTR_0;
101         MXC_GPIO_Config(&gpioCfg);
102         break;
103     case MXC_ADC_TRIG_SEL_P1_13:
104         gpioCfg.port = MXC_GPIO1;
105         gpioCfg.mask = MXC_GPIO_PIN_13;
106         gpioCfg.func = MXC_GPIO_FUNC_ALT2;
107         gpioCfg.pad = MXC_GPIO_PAD_NONE;
108         gpioCfg.vssel = MXC_GPIO_VSSEL_VDDIOH;
109         gpioCfg.drvstr = MXC_GPIO_DRVSTR_0;
110         MXC_GPIO_Config(&gpioCfg);
111         break;
112     case MXC_ADC_TRIG_SEL_P1_14:
113         gpioCfg.port = MXC_GPIO1;
114         gpioCfg.mask = MXC_GPIO_PIN_14;
115         gpioCfg.func = MXC_GPIO_FUNC_ALT2;
116         gpioCfg.pad = MXC_GPIO_PAD_NONE;
117         gpioCfg.vssel = MXC_GPIO_VSSEL_VDDIOH;
118         gpioCfg.drvstr = MXC_GPIO_DRVSTR_0;
119         MXC_GPIO_Config(&gpioCfg);
120         break;
121     }
122 }
123 
MXC_ADC_Init(mxc_adc_req_t * req)124 int MXC_ADC_Init(mxc_adc_req_t *req)
125 {
126     switch (req->clock) {
127     case MXC_ADC_CLK_HCLK:
128         break;
129     case MXC_ADC_CLK_EXT:
130         MXC_GPIO_Config(&gpio_cfg_extclk);
131         MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_EXTCLK);
132         break;
133     case MXC_ADC_CLK_IBRO:
134         MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IBRO);
135         break;
136     default:
137         return E_BAD_PARAM;
138     }
139 
140     MXC_SYS_Reset_Periph(MXC_SYS_RESET0_ADC);
141     MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_ADC);
142 
143     /* This is required for temperature sensor only */
144     MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IBRO);
145 
146     MXC_ADC_ReferenceSelect(req->ref);
147 
148     return MXC_ADC_RevB_Init((mxc_adc_revb_regs_t *)MXC_ADC, req);
149 }
150 
MXC_ADC_Shutdown(void)151 int MXC_ADC_Shutdown(void)
152 {
153     MXC_ADC_RevB_Shutdown((mxc_adc_revb_regs_t *)MXC_ADC);
154 
155     MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_ADC);
156 
157     return E_NO_ERROR;
158 }
159 
MXC_ADC_EnableInt(uint32_t flags)160 void MXC_ADC_EnableInt(uint32_t flags)
161 {
162     MXC_ADC_RevB_EnableInt((mxc_adc_revb_regs_t *)MXC_ADC, flags);
163 }
164 
MXC_ADC_DisableInt(uint32_t flags)165 void MXC_ADC_DisableInt(uint32_t flags)
166 {
167     MXC_ADC_RevB_DisableInt((mxc_adc_revb_regs_t *)MXC_ADC, flags);
168 }
169 
MXC_ADC_GetFlags(void)170 int MXC_ADC_GetFlags(void)
171 {
172     return MXC_ADC_RevB_GetFlags((mxc_adc_revb_regs_t *)MXC_ADC);
173 }
174 
MXC_ADC_ClearFlags(uint32_t flags)175 void MXC_ADC_ClearFlags(uint32_t flags)
176 {
177     MXC_ADC_RevB_ClearFlags((mxc_adc_revb_regs_t *)MXC_ADC, flags);
178 }
179 
MXC_ADC_ClockSelect(mxc_adc_clock_t clock)180 void MXC_ADC_ClockSelect(mxc_adc_clock_t clock)
181 {
182     MXC_ADC_RevB_ClockSelect((mxc_adc_revb_regs_t *)MXC_ADC, clock);
183 }
184 
MXC_ADC_StartConversion(void)185 int MXC_ADC_StartConversion(void)
186 {
187     return MXC_ADC_RevB_StartConversion((mxc_adc_revb_regs_t *)MXC_ADC);
188 }
189 
MXC_ADC_StartConversionAsync(mxc_adc_complete_cb_t callback)190 int MXC_ADC_StartConversionAsync(mxc_adc_complete_cb_t callback)
191 {
192     return MXC_ADC_RevB_StartConversionAsync((mxc_adc_revb_regs_t *)MXC_ADC, callback);
193 }
194 
MXC_ADC_StartConversionDMA(mxc_adc_conversion_req_t * req,int * data,void (* callback)(int,int))195 int MXC_ADC_StartConversionDMA(mxc_adc_conversion_req_t *req, int *data, void (*callback)(int, int))
196 {
197     return MXC_ADC_RevB_StartConversionDMA((mxc_adc_revb_regs_t *)MXC_ADC, req, data, callback);
198 }
199 
MXC_ADC_Handler(void)200 int MXC_ADC_Handler(void)
201 {
202     return MXC_ADC_RevB_Handler((mxc_adc_revb_regs_t *)MXC_ADC);
203 }
204 
MXC_ADC_GetData(int * outdata)205 int MXC_ADC_GetData(int *outdata)
206 {
207     return MXC_ADC_RevB_GetData((mxc_adc_revb_regs_t *)MXC_ADC, outdata);
208 }
209 
MXC_ADC_InputDividerSelect(mxc_adc_chsel_t ch,mxc_adc_divsel_t div,mxc_adc_dynamic_pullup_t lpEn)210 int MXC_ADC_InputDividerSelect(mxc_adc_chsel_t ch, mxc_adc_divsel_t div,
211                                mxc_adc_dynamic_pullup_t lpEn)
212 {
213     uint32_t bitOffset;
214 
215     if (ch > MXC_ADC_CH_7 || div > MXC_ADC_DIV2_50K) {
216         return E_BAD_PARAM;
217     }
218 
219     bitOffset = ch << 1;
220     MXC_MCR->adccfg2 &= ~(MXC_F_MCR_ADCCFG2_CH << bitOffset);
221     MXC_MCR->adccfg2 |= (div << bitOffset);
222 
223     if (lpEn == MXC_ADC_PY_DN_DISABLE) {
224         MXC_ADC_DynamicModeDis(ch);
225     } else {
226         MXC_ADC_DynamicModeEn(ch);
227     }
228 
229     return E_NO_ERROR;
230 }
231 
MXC_ADC_ReferenceSelect(mxc_adc_refsel_t ref)232 int MXC_ADC_ReferenceSelect(mxc_adc_refsel_t ref)
233 {
234     switch (ref) {
235     case MXC_ADC_REF_EXT:
236         MXC_MCR->adccfg0 |= MXC_F_MCR_ADCCFG0_EXT_REF;
237         break;
238     case MXC_ADC_REF_INT_1V25:
239         MXC_MCR->adccfg0 &= ~(MXC_F_MCR_ADCCFG0_EXT_REF | MXC_F_MCR_ADCCFG0_REF_SEL);
240         break;
241     case MXC_ADC_REF_INT_2V048:
242         MXC_MCR->adccfg0 &= ~MXC_F_MCR_ADCCFG0_EXT_REF;
243         MXC_MCR->adccfg0 |= MXC_F_MCR_ADCCFG0_REF_SEL;
244         break;
245     default:
246         return E_BAD_PARAM;
247     }
248 
249     return E_NO_ERROR;
250 }
251 
MXC_ADC_LowPowerModeDividerSelect(mxc_adc_div_lpmode_t div_lpmode)252 int MXC_ADC_LowPowerModeDividerSelect(mxc_adc_div_lpmode_t div_lpmode)
253 {
254     MXC_MCR->adccfg0 &= ~(MXC_F_MCR_ADCCFG0_LP_5K_DIS | MXC_F_MCR_ADCCFG0_LP_50K_DIS);
255     MXC_MCR->adccfg0 |= div_lpmode;
256 
257     return E_NO_ERROR;
258 }
259 
MXC_ADC_EnableConversion(void)260 void MXC_ADC_EnableConversion(void)
261 {
262     MXC_ADC_RevB_EnableConversion((mxc_adc_revb_regs_t *)MXC_ADC);
263 }
264 
MXC_ADC_DisableConversion(void)265 void MXC_ADC_DisableConversion(void)
266 {
267     MXC_ADC_RevB_DisableConversion((mxc_adc_revb_regs_t *)MXC_ADC);
268 }
269 
MXC_ADC_TS_SelectEnable(void)270 void MXC_ADC_TS_SelectEnable(void)
271 {
272     MXC_ADC_RevB_TS_SelectEnable((mxc_adc_revb_regs_t *)MXC_ADC);
273 }
274 
MXC_ADC_TS_SelectDisable(void)275 void MXC_ADC_TS_SelectDisable(void)
276 {
277     MXC_ADC_RevB_TS_SelectDisable((mxc_adc_revb_regs_t *)MXC_ADC);
278 }
279 
MXC_ADC_FIFO_Level(void)280 uint16_t MXC_ADC_FIFO_Level(void)
281 {
282     return MXC_ADC_RevB_FIFO_Level((mxc_adc_revb_regs_t *)MXC_ADC);
283 }
284 
MXC_ADC_FIFO_Threshold_Config(uint32_t fifo_threshold)285 int MXC_ADC_FIFO_Threshold_Config(uint32_t fifo_threshold)
286 {
287     return MXC_ADC_RevB_FIFO_Threshold_Config((mxc_adc_revb_regs_t *)MXC_ADC, fifo_threshold);
288 }
289 
MXC_ADC_AverageConfig(mxc_adc_avg_t avg_number)290 int MXC_ADC_AverageConfig(mxc_adc_avg_t avg_number)
291 {
292     return MXC_ADC_RevB_AverageConfig((mxc_adc_revb_regs_t *)MXC_ADC, avg_number);
293 }
294 
MXC_ADC_Clear_ChannelSelect(void)295 void MXC_ADC_Clear_ChannelSelect(void)
296 {
297     MXC_ADC_RevB_Clear_ChannelSelect((mxc_adc_revb_regs_t *)MXC_ADC);
298 }
299 
MXC_ADC_TriggerConfig(mxc_adc_conversion_req_t * req)300 void MXC_ADC_TriggerConfig(mxc_adc_conversion_req_t *req)
301 {
302     initGPIOforHWTrig(req->hwTrig);
303     MXC_ADC_RevB_TriggerConfig((mxc_adc_revb_regs_t *)MXC_ADC, req);
304 }
305 
MXC_ADC_ConversionModeConfig(mxc_adc_conversion_req_t * req)306 void MXC_ADC_ConversionModeConfig(mxc_adc_conversion_req_t *req)
307 {
308     MXC_ADC_RevB_ConversionModeConfig((mxc_adc_revb_regs_t *)MXC_ADC, req);
309 }
310 
MXC_ADC_SetConversionDelay(int delay)311 void MXC_ADC_SetConversionDelay(int delay)
312 {
313     MXC_ADC_RevB_SetConversionDelay((mxc_adc_revb_regs_t *)MXC_ADC, delay);
314 }
315 
MXC_ADC_SlotsConfig(mxc_adc_conversion_req_t * req)316 int MXC_ADC_SlotsConfig(mxc_adc_conversion_req_t *req)
317 {
318     return MXC_ADC_RevB_SlotsConfig((mxc_adc_revb_regs_t *)MXC_ADC, req);
319 }
320 
MXC_ADC_ChSelectConfig(mxc_adc_chsel_t ch,uint32_t slot_num)321 int MXC_ADC_ChSelectConfig(mxc_adc_chsel_t ch, uint32_t slot_num)
322 {
323     return MXC_ADC_RevB_ChSelectConfig((mxc_adc_revb_regs_t *)MXC_ADC, ch, slot_num);
324 }
325 
MXC_ADC_Configuration(mxc_adc_conversion_req_t * req)326 int MXC_ADC_Configuration(mxc_adc_conversion_req_t *req)
327 {
328     MXC_ADC_ConversionModeConfig(req);
329 
330     MXC_ADC_TriggerConfig(req);
331 
332     MXC_ADC_FIFO_Threshold_Config(req->fifo_threshold);
333 
334     MXC_ADC_SlotsConfig(req);
335 
336     MXC_ADC_Clear_ChannelSelect();
337 
338     //number of samples to average
339     MXC_ADC_AverageConfig(req->avg_number);
340 
341     MXC_ADC_LowPowerModeDividerSelect(req->lpmode_divder);
342 
343     return E_NO_ERROR;
344 }
345 
MXC_ADC_SlotConfiguration(mxc_adc_slot_req_t * req,uint32_t slot_length)346 int MXC_ADC_SlotConfiguration(mxc_adc_slot_req_t *req, uint32_t slot_length)
347 {
348     uint32_t loop_counter = 0;
349 
350     for (loop_counter = 0; loop_counter <= slot_length; loop_counter++) {
351         initGPIOForChannel(req->channel);
352 
353         if (req->channel <= MAX_ADC_RES_DIV_CH) {
354             MXC_ADC_InputDividerSelect(req->channel, req->div, req->pullup_dyn);
355         }
356 
357         MXC_ADC_ChSelectConfig(req->channel, loop_counter);
358         req++;
359     }
360     return E_NO_ERROR;
361 }
362 
MXC_ConvertTemperature_ToK(uint16_t tempSensor_Readout,mxc_adc_refsel_t ref,float ext_ref,float * temp_k)363 int MXC_ConvertTemperature_ToK(uint16_t tempSensor_Readout, mxc_adc_refsel_t ref, float ext_ref,
364                                float *temp_k)
365 {
366     switch (ref) {
367     case MXC_ADC_REF_EXT:
368         *temp_k = tempSensor_Readout * TEMP_FACTOR * ext_ref;
369         break;
370 
371     case MXC_ADC_REF_INT_1V25:
372         *temp_k = tempSensor_Readout * TEMP_FACTOR1V25;
373         break;
374 
375     case MXC_ADC_REF_INT_2V048:
376         *temp_k = tempSensor_Readout * TEMP_FACTOR2V048;
377         break;
378 
379     default:
380         return E_BAD_PARAM;
381     }
382     return E_NO_ERROR;
383 }
384 
MXC_ConvertTemperature_ToC(uint16_t tempSensor_Readout,mxc_adc_refsel_t ref,float ext_ref,float * temp)385 int MXC_ConvertTemperature_ToC(uint16_t tempSensor_Readout, mxc_adc_refsel_t ref, float ext_ref,
386                                float *temp)
387 {
388     if (MXC_ConvertTemperature_ToK(tempSensor_Readout, ref, ext_ref, temp) == E_NO_ERROR) {
389         *temp = *temp - 273.15f;
390         return E_NO_ERROR;
391     } else {
392         return E_BAD_PARAM;
393     }
394 }
395 
MXC_ConvertTemperature_ToF(uint16_t tempSensor_Readout,mxc_adc_refsel_t ref,float ext_ref,float * temp)396 int MXC_ConvertTemperature_ToF(uint16_t tempSensor_Readout, mxc_adc_refsel_t ref, float ext_ref,
397                                float *temp)
398 {
399     if (MXC_ConvertTemperature_ToK(tempSensor_Readout, ref, ext_ref, temp) == E_NO_ERROR) {
400         *temp = (*temp * 1.8f) - 459.67f;
401         return E_NO_ERROR;
402     } else {
403         return E_BAD_PARAM;
404     }
405 }
406 
MXC_ADC_DynamicModeEn(mxc_adc_chsel_t ch)407 int MXC_ADC_DynamicModeEn(mxc_adc_chsel_t ch)
408 {
409     if (ch > MXC_ADC_CH_7) {
410         return E_BAD_PARAM;
411     }
412 
413     MXC_MCR->adccfg1 |= (1 << ch);
414 
415     return E_NO_ERROR;
416 }
417 
MXC_ADC_DynamicModeDis(mxc_adc_chsel_t ch)418 int MXC_ADC_DynamicModeDis(mxc_adc_chsel_t ch)
419 {
420     if (ch > MXC_ADC_CH_7) {
421         return E_BAD_PARAM;
422     }
423 
424     MXC_MCR->adccfg1 &= ~(1 << ch);
425 
426     return E_NO_ERROR;
427 }
428