1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date         Author      Notes
8  * 2011-02-21   onelife     Initial creation for EFM32
9  * 2011-07-14   onelife     Add multiple channels support for scan mode
10  */
11 
12 /***************************************************************************//**
13  * @addtogroup efm32
14  * @{
15  ******************************************************************************/
16 
17 /* Includes ------------------------------------------------------------------*/
18 #include "board.h"
19 #include "drv_adc.h"
20 
21 #if defined(RT_USING_ADC0)
22 /* Private typedef -----------------------------------------------------------*/
23 /* Private define ------------------------------------------------------------*/
24 /* Private macro -------------------------------------------------------------*/
25 #ifdef RT_ADC_DEBUG
26 #define adc_debug(format,args...)           rt_kprintf(format, ##args)
27 #else
28 #define adc_debug(format,args...)
29 #endif
30 
31 /* Private variables ---------------------------------------------------------*/
32 #ifdef RT_USING_ADC0
33 static struct rt_device adc0_device;
34 #endif
35 static rt_uint32_t adcErrataShift = 0;
36 
37 /* Private function prototypes -----------------------------------------------*/
38 /* Private functions ---------------------------------------------------------*/
39 /***************************************************************************//**
40  * @brief
41  *   Calibrate offset and gain for the specified reference.
42  *   Supports currently only single ended gain calibration.
43  *   Could easily be expanded to support differential gain calibration.
44  *
45  * @details
46  *   The offset calibration routine measures 0 V with the ADC, and adjust
47  *   the calibration register until the converted value equals 0.
48  *   The gain calibration routine needs an external reference voltage equal
49  *   to the top value for the selected reference. For example if the 2.5 V
50  *   reference is to be calibrated, the external supply must also equal 2.5V.
51  *
52  * @param[in] adc
53  *   Pointer to ADC peripheral register block.
54  *
55  * @param[in] ref
56  *   Reference used during calibration. Can be both external and internal
57  *   references.
58  *
59  * @param[in] input
60  *   Input channel used during calibration.
61  *
62  * @return
63  *   The final value of the calibration register, note that the calibration
64  *   register gets updated with this value during the calibration.
65  *   No need to load the calibration values after the function returns.
66  ******************************************************************************/
efm32_adc_calibration(ADC_TypeDef * adc,ADC_Ref_TypeDef ref,ADC_SingleInput_TypeDef input)67 rt_uint32_t efm32_adc_calibration(
68     ADC_TypeDef             *adc,
69     ADC_Ref_TypeDef         ref,
70     ADC_SingleInput_TypeDef input)
71 {
72     rt_uint32_t     cal;
73     rt_int32_t      sample;
74     rt_int8_t       high, mid, low, tmp;
75     ADC_InitSingle_TypeDef singleInit   = ADC_INITSINGLE_DEFAULT;
76 
77     /* Init for single conversion use, measure diff 0 with selected reference. */
78     singleInit.reference    = ref;
79     singleInit.input        = adcSingleInpDiff0;
80     singleInit.acqTime      = adcAcqTime32;
81     singleInit.diff         = true;
82     /* Enable oversampling rate */
83     singleInit.resolution   = adcResOVS;
84     ADC_InitSingle(adc, &singleInit);
85 
86     /* ADC is now set up for offset calibration */
87     /* Offset calibration register is a 7 bit signed 2's complement value. */
88     /* Use unsigned indexes for binary search, and convert when calibration */
89     /* register is written to. */
90     high = 63;
91     low = -64;
92 
93     /* Do binary search for offset calibration*/
94     while (low < high)
95     {
96         /* Calculate midpoint */
97         mid = low + (high - low) / 2;
98 
99         /* Midpoint is converted to 2's complement and written to both scan and */
100         /* single calibration registers */
101         cal = adc->CAL & ~(_ADC_CAL_SINGLEOFFSET_MASK | _ADC_CAL_SCANOFFSET_MASK);
102         tmp = mid < 0 ? (((mid & 0x3F) ^ 0x3F) | 0x40) + 1 : mid;
103         cal |= tmp << _ADC_CAL_SINGLEOFFSET_SHIFT;
104         cal |= tmp << _ADC_CAL_SCANOFFSET_SHIFT;
105         adc_debug("adc->CAL = %x, cal = %x, tmp = %x\n", adc->CAL, cal, tmp);
106         adc->CAL = cal;
107 
108         /* Do a conversion */
109         ADC_Start(adc, adcStartSingle);
110 
111         /* Wait while conversion is active */
112         while (adc->STATUS & ADC_STATUS_SINGLEACT) ;
113 
114         /* Get ADC result */
115         sample = ADC_DataSingleGet(adc);
116 
117         /* Check result and decide in which part of to repeat search */
118         /* Calibration register has negative effect on result */
119         if (sample < 0)
120         {
121             /* Repeat search in bottom half. */
122             high = mid;
123         }
124         else if (sample > 0)
125         {
126             /* Repeat search in top half. */
127             low = mid + 1;
128         }
129         else
130         {
131             /* Found it, exit while loop */
132             break;
133         }
134     }
135     adc_debug("adc->CAL = %x\n", adc->CAL);
136 
137     /* Now do gain calibration, only input and diff settings needs to be changed */
138     adc->SINGLECTRL &= ~(_ADC_SINGLECTRL_INPUTSEL_MASK | _ADC_SINGLECTRL_DIFF_MASK);
139     adc->SINGLECTRL |= (input << _ADC_SINGLECTRL_INPUTSEL_SHIFT);
140     adc->SINGLECTRL |= (false << _ADC_SINGLECTRL_DIFF_SHIFT);
141 
142     /* ADC is now set up for gain calibration */
143     /* Gain calibration register is a 7 bit unsigned value. */
144     high = 127;
145     low = 0;
146 
147     /* Do binary search for gain calibration */
148     while (low < high)
149     {
150         /* Calculate midpoint and write to calibration register */
151         mid = low + (high - low) / 2;
152 
153         /* Midpoint is converted to 2's complement */
154         cal      = adc->CAL & ~(_ADC_CAL_SINGLEGAIN_MASK | _ADC_CAL_SCANGAIN_MASK);
155         cal     |= mid << _ADC_CAL_SINGLEGAIN_SHIFT;
156         cal     |= mid << _ADC_CAL_SCANGAIN_SHIFT;
157         adc_debug("adc->CAL = %x, cal = %x, mid = %x\n", adc->CAL, cal, mid);
158         adc->CAL = cal;
159 
160         /* Do a conversion */
161         ADC_Start(adc, adcStartSingle);
162 
163         /* Wait while conversion is active */
164         while (adc->STATUS & ADC_STATUS_SINGLEACT) ;
165 
166         /* Get ADC result */
167         sample = ADC_DataSingleGet(adc);
168 
169         /* Check result and decide in which part to repeat search */
170         /* Compare with a value atleast one LSB's less than top to avoid overshooting */
171         /* Since oversampling is used, the result is 16 bits, but a couple of lsb's */
172         /* applies to the 12 bit result value, if 0xffe is the top value in 12 bit, this */
173         /* is in turn 0xffe0 in the 16 bit result. */
174         /* Calibration register has positive effect on result */
175         if (sample > 0xffd0)
176         {
177           /* Repeat search in bottom half. */
178           high = mid;
179         }
180         else if (sample < 0xffd0)
181         {
182           /* Repeat search in top half. */
183           low = mid + 1;
184         }
185         else
186         {
187           /* Found it, exit while loop */
188           break;
189         }
190     }
191     adc_debug("adc->CAL = %x\n", adc->CAL);
192 
193     return adc->CAL;
194 }
195 
196 /***************************************************************************//**
197  * @brief
198  *   Configure DMA for ADC
199  *
200  * @details
201  *
202  * @note
203  *
204  * @param[in] adc_device
205  *   Pointer to ADC registers base address
206  *
207  * @param[in] mode
208  *   ADC mode
209  *
210  * @param[in] channel
211  *   DMA channel
212  ******************************************************************************/
efm32_adc_cfg_dma(ADC_TypeDef * adc_device,rt_uint8_t mode,rt_uint8_t channel)213 void efm32_adc_cfg_dma(
214         ADC_TypeDef             *adc_device,
215         rt_uint8_t              mode,
216         rt_uint8_t              channel)
217 {
218     DMA_CfgChannel_TypeDef  chnlCfg;
219     DMA_CfgDescr_TypeDef    descrCfg;
220 
221     if (channel == (rt_uint8_t)EFM32_NO_DMA)
222     {
223         return;
224     }
225 
226     /* Set up DMA channel */
227     chnlCfg.highPri     = false;
228     chnlCfg.enableInt   = false;
229     if (adc_device == ADC0)
230     {
231         switch (mode & ADC_MASK_MODE)
232         {
233         case ADC_MODE_SINGLE:
234             chnlCfg.select = DMAREQ_ADC0_SINGLE;
235             break;
236 
237         case ADC_MODE_SCAN:
238             chnlCfg.select = DMAREQ_ADC0_SCAN;
239             break;
240 
241         default:
242             return;
243         }
244     }
245     else
246     {
247         // TODO: Any other channel?
248         return;
249     }
250     chnlCfg.cb          = RT_NULL;
251     DMA_CfgChannel((rt_uint32_t)channel, &chnlCfg);
252 
253     /* Setting up DMA channel descriptor */
254     descrCfg.dstInc     = dmaDataInc4;
255     descrCfg.srcInc     = dmaDataIncNone;
256     descrCfg.size       = dmaDataSize4;
257     descrCfg.arbRate    = dmaArbitrate1;
258     descrCfg.hprot      = 0;
259     DMA_CfgDescr((rt_uint32_t)channel, true, &descrCfg);
260 }
261 
262 /***************************************************************************//**
263  * @brief
264  *   Activate DMA for ADC
265  *
266  * @details
267  *
268  * @note
269  *
270  * @param[in] adc_device
271  *   Pointer to ADC registers base address
272  *
273  * @param[in] mode
274  *   ADC mode
275  *
276  * @param[in] count
277  *   ADC channel count
278  *
279  * @param[in] channel
280  *   DMA channel
281  *
282  * @param[out] buffer
283  *   Pointer to ADC results buffer
284  ******************************************************************************/
efm32_adc_on_dma(ADC_TypeDef * adc_device,rt_uint8_t mode,rt_uint8_t count,rt_uint8_t channel,void * buffer)285 void efm32_adc_on_dma(
286         ADC_TypeDef             *adc_device,
287         rt_uint8_t              mode,
288         rt_uint8_t              count,
289         rt_uint8_t              channel,
290         void                    *buffer)
291 {
292     switch (mode & ADC_MASK_MODE)
293     {
294     case ADC_MODE_SINGLE:
295         /* Activate DMA */
296         DMA_ActivateBasic(
297             (rt_uint32_t)channel,
298             true,
299             false,
300             buffer,
301             (void *)&(adc_device->SINGLEDATA),
302             count - 1);
303         break;
304 
305     case ADC_MODE_SCAN:
306         DMA_ActivateBasic(
307             (rt_uint32_t)channel,
308             true,
309             false,
310             buffer,
311             (void *)&(adc_device->SCANDATA),
312             count - 1);
313         break;
314 
315     default:
316         return;
317     }
318 }
319 
320 /***************************************************************************//**
321  * @brief
322  *   Initialize ADC device
323  *
324  * @details
325  *
326  * @note
327  *
328  * @param[in] dev
329  *   Pointer to device descriptor
330  *
331  * @return
332  *   Error code
333  ******************************************************************************/
rt_adc_init(rt_device_t dev)334  static rt_err_t rt_adc_init(rt_device_t dev)
335 {
336     RT_ASSERT(dev != RT_NULL);
337 
338     rt_uint32_t temp;
339 
340     struct efm32_adc_device_t *adc;
341 
342     adc = (struct efm32_adc_device_t *)(dev->user_data);
343 
344     temp = efm32_adc_calibration(adc->adc_device, ADC_CALI_REF, ADC_CALI_CH);
345 
346     adc_debug("adc->CAL = %x\n", temp);
347     return RT_EOK;
348 }
349 
350 /***************************************************************************//**
351  * @brief
352  *  Configure ADC device
353  *
354  * @details
355  *
356  * @note
357  *
358  * @param[in] dev
359  *  Pointer to device descriptor
360  *
361  * @param[in] cmd
362  *  ADC control command
363  *
364  * @param[in] args
365  *  Arguments
366  *
367  * @return
368  *  Error code
369  ******************************************************************************/
rt_adc_control(rt_device_t dev,rt_uint8_t cmd,void * args)370 static rt_err_t rt_adc_control(
371     rt_device_t     dev,
372     rt_uint8_t      cmd,
373     void            *args)
374 {
375     RT_ASSERT(dev != RT_NULL);
376 
377     struct efm32_adc_device_t *adc;
378 
379     adc = (struct efm32_adc_device_t *)(dev->user_data);
380 
381     switch (cmd)
382     {
383     case RT_DEVICE_CTRL_SUSPEND:
384         /* Suspend device */
385         dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
386         adc->adc_device->CMD = ADC_CMD_SINGLESTOP | ADC_CMD_SCANSTOP;
387         break;
388 
389     case RT_DEVICE_CTRL_RESUME:
390         {
391             /* Resume device */
392             struct efm32_adc_result_t *control = \
393                 (struct efm32_adc_result_t *)args;
394 
395             dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
396 
397             switch (control->mode)
398             {
399             case ADC_MODE_SINGLE:
400                 if (adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
401                 {
402                     efm32_adc_on_dma(
403                         adc->adc_device,
404                         control->mode,
405                         adc->singleCount,
406                         adc->singleDmaChannel,
407                         control->buffer);
408                 }
409                 ADC_Start(adc->adc_device, adcStartSingle);
410                 break;
411 
412             case ADC_MODE_SCAN:
413                 if (adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
414                 {
415                     efm32_adc_on_dma(
416                         adc->adc_device,
417                         control->mode,
418                         adc->scanCount,
419                         adc->scanDmaChannel,
420                         control->buffer);
421                 }
422                 ADC_Start(adc->adc_device, adcStartScan);
423                 break;
424 
425             case ADC_MODE_TAILGATE:
426                 {
427                     void *index = control->buffer;
428 
429                     if (adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
430                     {
431                         efm32_adc_on_dma(
432                             adc->adc_device,
433                             control->mode,
434                             adc->scanCount,
435                             adc->scanDmaChannel,
436                             index);
437                         index += adc->scanCount;
438                     }
439                     if (adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
440                     {
441                         efm32_adc_on_dma(
442                             adc->adc_device,
443                             control->mode,
444                             adc->singleCount,
445                             adc->singleDmaChannel,
446                             index);
447                         index += adc->singleCount;
448                     }
449                     ADC_Start(adc->adc_device, adcStartScanAndSingle);
450                 }
451 
452                 break;
453 
454             default:
455                 return -RT_ERROR;
456             }
457         }
458         break;
459 
460     case RT_DEVICE_CTRL_ADC_MODE:
461         {
462             /* change device setting */
463             struct efm32_adc_control_t *control = \
464                 (struct efm32_adc_control_t *)args;
465 
466             switch (control->mode)
467             {
468             case ADC_MODE_SINGLE:
469                 ADC_InitSingle(adc->adc_device, control->single.init);
470                 break;
471 
472             case ADC_MODE_SCAN:
473                 ADC_InitScan(adc->adc_device, control->scan.init);
474                 break;
475 
476             case ADC_MODE_TAILGATE:
477                 ADC_InitSingle(adc->adc_device, control->single.init);
478                 ADC_InitScan(adc->adc_device, control->scan.init);
479                 break;
480 
481             default:
482                 return -RT_ERROR;
483             }
484 
485             if (control->mode == ADC_MODE_TAILGATE)
486             {
487                 adc->mode = ADC_MODE_TAILGATE;
488             }
489             else
490             {
491                 adc->mode &= ~(rt_uint8_t)ADC_MODE_TAILGATE;
492                 adc->mode |= control->mode;
493             }
494             if ((control->mode == ADC_MODE_TAILGATE) || \
495                 (control->mode == ADC_MODE_SINGLE))
496             {
497                 if (control->single.init->rep)
498                 {
499                     adc->mode |= ADC_OP_SINGLE_REPEAT;
500                 }
501                 adc->singleCount = control->single.count;
502                 adc->singleDmaChannel = control->single.dmaChannel;
503                 efm32_adc_cfg_dma(adc->adc_device, control->mode, adc->singleDmaChannel);
504             }
505             if ((control->mode == ADC_MODE_TAILGATE) || \
506                 (control->mode == ADC_MODE_SCAN))
507             {
508                 if (control->scan.init->rep)
509                 {
510                     adc->mode |= ADC_OP_SCAN_REPEAT;
511                 }
512                 adc->scanCount = control->scan.count;
513                 adc->scanDmaChannel = control->scan.dmaChannel;
514                 efm32_adc_cfg_dma(adc->adc_device, control->mode, adc->scanDmaChannel);
515             }
516         }
517         break;
518 
519     case RT_DEVICE_CTRL_ADC_RESULT:
520         {
521             struct efm32_adc_result_t *control = \
522                 (struct efm32_adc_result_t *)args;
523 
524             switch (control->mode)
525             {
526             case ADC_MODE_SINGLE:
527                 if (adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
528                 {
529                     if (adc->mode & ADC_OP_SINGLE_REPEAT)
530                     {
531                         if (!(DMA->IF & (1 << adc->singleDmaChannel)))
532                         {
533                             efm32_adc_on_dma(
534                                 adc->adc_device,
535                                 control->mode,
536                                 adc->singleCount,
537                                 adc->singleDmaChannel,
538                                 control->buffer);
539                         }
540                         while (!(DMA->IF & (1 << adc->singleDmaChannel)));
541                     }
542                     else
543                     {
544                         while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT);
545                     }
546                 }
547                 else
548                 {
549                     while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT);
550                     *((rt_uint32_t *)control->buffer) = \
551                         ADC_DataSingleGet(adc->adc_device) << adcErrataShift;
552                 }
553                 break;
554 
555             case ADC_MODE_SCAN:
556                 if (adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
557                 {
558                     if (adc->mode & ADC_OP_SCAN_REPEAT)
559                     {
560                         if (!(DMA->IF & (1 << adc->scanDmaChannel)))
561                         {
562                             efm32_adc_on_dma(
563                                 adc->adc_device,
564                                 control->mode,
565                                 adc->scanCount,
566                                 adc->scanDmaChannel,
567                                 control->buffer);
568                         }
569                         while (!(DMA->IF & (1 << adc->scanDmaChannel)));
570                     }
571                     else
572                     {
573                         while (adc->adc_device->STATUS & ADC_STATUS_SCANACT);
574                     }
575                 }
576                 else
577                 {
578                     while (adc->adc_device->STATUS & ADC_STATUS_SCANACT);
579                     *((rt_uint32_t *)control->buffer) = \
580                         ADC_DataScanGet(adc->adc_device) << adcErrataShift;
581                 }
582                 break;
583 
584             case ADC_MODE_TAILGATE:
585                 {
586                     void *index = control->buffer;
587 
588                     if ((adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA) && \
589                         !(adc->mode & ADC_OP_SCAN_REPEAT))
590                     {
591                         index += adc->scanCount;
592                     }
593                     if ((adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA) && \
594                         !(adc->mode & ADC_OP_SINGLE_REPEAT))
595                     {
596                         index += adc->singleCount;
597                     }
598 
599                     if (adc->scanDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
600                     {
601                         if (adc->mode & ADC_OP_SCAN_REPEAT)
602                         {
603                             if (!(DMA->IF & (1 << adc->scanDmaChannel)))
604                             {
605                                 efm32_adc_on_dma(
606                                     adc->adc_device,
607                                     control->mode,
608                                     adc->scanCount,
609                                     adc->scanDmaChannel,
610                                     index);
611                                 index += adc->scanCount;
612                             }
613                             while (!(DMA->IF & (1 << adc->scanDmaChannel)));
614                         }
615                         else
616                         {
617                             while (adc->adc_device->STATUS & ADC_STATUS_SCANACT);
618                         }
619                     }
620                     else
621                     {
622                         while (adc->adc_device->STATUS & ADC_STATUS_SCANACT);
623                         *(rt_uint32_t *)(index++) = \
624                             ADC_DataScanGet(adc->adc_device) << adcErrataShift;
625                     }
626                     if (adc->singleDmaChannel != (rt_uint8_t)EFM32_NO_DMA)
627                     {
628                         if (adc->mode & ADC_OP_SINGLE_REPEAT)
629                         {
630                             if (!(DMA->IF & (1 << adc->singleDmaChannel)))
631                             {
632                                 efm32_adc_on_dma(
633                                     adc->adc_device,
634                                     control->mode,
635                                     adc->singleCount,
636                                     adc->singleDmaChannel,
637                                     index);
638                                 index += adc->singleCount;
639                             }
640                             while (!(DMA->IF & (1 << adc->singleDmaChannel)));
641                         }
642                         else
643                         {
644                             while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT);
645                         }
646                     }
647                     else
648                     {
649                         while (adc->adc_device->STATUS & ADC_STATUS_SINGLEACT);
650                         *(rt_uint32_t *)(index++) = \
651                             ADC_DataSingleGet(adc->adc_device) << adcErrataShift;
652                     }
653                 }
654                 break;
655 
656             default:
657                 return -RT_ERROR;
658             }
659         }
660         break;
661 
662     default:
663         return -RT_ERROR;
664     }
665 
666     return RT_EOK;
667 }
668 
669 /***************************************************************************//**
670  * @brief
671  *  Register ADC device
672  *
673  * @details
674  *
675  * @note
676  *
677  * @param[in] device
678  *  Pointer to device descriptor
679  *
680  * @param[in] name
681  *  Device name
682  *
683  * @param[in] flag
684  *  Configuration flags
685  *
686  * @param[in] adc
687  *  Pointer to ADC device descriptor
688  *
689  * @return
690  *  Error code
691  ******************************************************************************/
rt_hw_adc_register(rt_device_t device,const char * name,rt_uint32_t flag,struct efm32_adc_device_t * adc)692 rt_err_t rt_hw_adc_register(
693     rt_device_t     device,
694     const char      *name,
695     rt_uint32_t     flag,
696     struct efm32_adc_device_t *adc)
697 {
698     RT_ASSERT(device != RT_NULL);
699 
700     device->type        = RT_Device_Class_Char; /* fixme: should be adc type */
701     device->rx_indicate = RT_NULL;
702     device->tx_complete = RT_NULL;
703     device->init        = rt_adc_init;
704     device->open        = RT_NULL;
705     device->close       = RT_NULL;
706     device->read        = RT_NULL;
707     device->write       = RT_NULL;
708     device->control     = rt_adc_control;
709     device->user_data   = adc;
710 
711     /* register a character device */
712     return rt_device_register(device, name, flag);
713 }
714 
715 /***************************************************************************//**
716  * @brief
717  *  Initialize the specified ADC unit
718  *
719  * @details
720  *
721  * @note
722  *
723  * @param[in] device
724  *  Pointer to device descriptor
725  *
726  * @param[in] unitNumber
727  *  Unit number
728  *
729  * @return
730  *  Pointer to ADC device
731  ******************************************************************************/
rt_hw_adc_unit_init(rt_device_t device,rt_uint8_t unitNumber)732 static struct efm32_adc_device_t *rt_hw_adc_unit_init(
733     rt_device_t device,
734     rt_uint8_t  unitNumber)
735 {
736     struct efm32_adc_device_t       *adc;
737     CMU_Clock_TypeDef               adcClock;
738     ADC_Init_TypeDef                init = ADC_INIT_DEFAULT;
739 
740     do
741     {
742         /* Allocate device and set default value */
743         adc = rt_malloc(sizeof(struct efm32_adc_device_t));
744         if (adc == RT_NULL)
745         {
746             adc_debug("no memory for ADC%d driver\n", unitNumber);
747             break;
748         }
749         adc->mode               = 0;
750         adc->singleCount        = 0;
751         adc->singleDmaChannel   = (rt_uint8_t)EFM32_NO_DMA;
752         adc->scanCount          = 0;
753         adc->scanDmaChannel     = (rt_uint8_t)EFM32_NO_DMA;
754 
755         /* Initialization */
756         if (unitNumber >= ADC_COUNT)
757         {
758             break;
759         }
760         switch (unitNumber)
761         {
762         case 0:
763             adc->adc_device     = ADC0;
764             adcClock            = (CMU_Clock_TypeDef)cmuClock_ADC0;
765             break;
766 
767         default:
768             break;
769         }
770 
771         /* Enable ADC clock */
772         CMU_ClockEnable(adcClock, true);
773 
774         /* Reset */
775         ADC_Reset(adc->adc_device);
776 
777         /* Configure ADC */
778         // TODO: Fixed oversampling rate?
779         init.ovsRateSel         = adcOvsRateSel4096;
780         init.timebase           = ADC_TimebaseCalc(0);
781         init.prescale           = ADC_PrescaleCalc(ADC_CONVERT_FREQUENCY, 0);
782         ADC_Init(adc->adc_device, &init);
783 
784         return adc;
785     } while(0);
786 
787     if (adc)
788     {
789         rt_free(adc);
790     }
791     rt_kprintf("ADC: Init failed!\n");
792     return RT_NULL;
793 }
794 
795 /***************************************************************************//**
796  * @brief
797  *  Initialize all ADC module related hardware and register ADC device to kernel
798  *
799  * @details
800  *
801  * @note
802  *
803  ******************************************************************************/
rt_hw_adc_init(void)804 void rt_hw_adc_init(void)
805 {
806     SYSTEM_ChipRevision_TypeDef chipRev;
807     struct efm32_adc_device_t   *adc;
808 
809 #ifdef RT_USING_ADC0
810     if ((adc = rt_hw_adc_unit_init(&adc0_device, 0)) != RT_NULL)
811     {
812         rt_hw_adc_register(&adc0_device, RT_ADC0_NAME, EFM32_NO_DATA, adc);
813     }
814 #endif
815 
816     /* ADC errata for rev B when using VDD as reference, need to multiply */
817     /* result by 2 */
818     SYSTEM_ChipRevisionGet(&chipRev);
819     if ((chipRev.major == 0x01) && (chipRev.minor == 0x01))
820     {
821       adcErrataShift = 1;
822     }
823 }
824 
825 #endif
826 /***************************************************************************//**
827  * @}
828  ******************************************************************************/
829