Skip to content

Commit e4d4eac

Browse files
attie-argentumcarlescufi
authored andcommitted
soc: atmel_sam0: Implement fixup.h for ADC driver
The ADC driver now supports three different implementations. To maintain readability, this patch implements an adc_fixup.h that permits more generic access to relevant registers. This patch also introduces support for a new third shape ADC - as found in the SAML21 for example. Signed-off-by: Attie Grande <[email protected]>
1 parent ec1ab6d commit e4d4eac

File tree

9 files changed

+163
-74
lines changed

9 files changed

+163
-74
lines changed

drivers/adc/adc_sam0.c

Lines changed: 25 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,8 @@ struct adc_sam0_cfg {
6060

6161
static void wait_synchronization(Adc *const adc)
6262
{
63-
#if defined(ADC_SYNCBUSY_MASK)
64-
while ((adc->SYNCBUSY.reg & ADC_SYNCBUSY_MASK) != 0) {
63+
while ((ADC_SYNC(adc) & ADC_SYNC_MASK) != 0) {
6564
}
66-
#else
67-
while ((adc->STATUS.reg & ADC_STATUS_SYNCBUSY) != 0) {
68-
}
69-
#endif
7065
}
7166

7267
static int adc_sam0_acquisition_to_clocks(const struct device *dev,
@@ -141,26 +136,16 @@ static int adc_sam0_channel_setup(const struct device *dev,
141136

142137
switch (channel_cfg->reference) {
143138
case ADC_REF_INTERNAL:
144-
#ifdef ADC_REFCTRL_REFSEL_INTREF
145-
REFCTRL = ADC_REFCTRL_REFSEL_INTREF | ADC_REFCTRL_REFCOMP;
146-
/* Enable the internal reference, defaulting to 1V */
147-
SUPC->VREF.bit.VREFOE = 1;
148-
#else
149-
REFCTRL = ADC_REFCTRL_REFSEL_INT1V | ADC_REFCTRL_REFCOMP;
139+
REFCTRL = ADC_REFCTRL_REFSEL_INTERNAL | ADC_REFCTRL_REFCOMP;
150140
/* Enable the internal bandgap reference */
151-
SYSCTRL->VREF.bit.BGOUTEN = 1;
152-
#endif
141+
ADC_BGEN = 1;
153142
break;
154143
case ADC_REF_VDD_1_2:
155-
#ifdef ADC_REFCTRL_REFSEL_INTVCC0
156-
REFCTRL = ADC_REFCTRL_REFSEL_INTVCC0 | ADC_REFCTRL_REFCOMP;
157-
#else
158-
REFCTRL = ADC_REFCTRL_REFSEL_INTVCC1 | ADC_REFCTRL_REFCOMP;
159-
#endif
144+
REFCTRL = ADC_REFCTRL_REFSEL_VDD_1_2 | ADC_REFCTRL_REFCOMP;
160145
break;
161-
#ifdef ADC_REFCTRL_REFSEL_INTVCC1
146+
#ifdef ADC_REFCTRL_REFSEL_VDD_1
162147
case ADC_REF_VDD_1:
163-
REFCTRL = ADC_REFCTRL_REFSEL_INTVCC1 | ADC_REFCTRL_REFCOMP;
148+
REFCTRL = ADC_REFCTRL_REFSEL_VDD_1 | ADC_REFCTRL_REFCOMP;
164149
break;
165150
#endif
166151
case ADC_REF_EXTERNAL0:
@@ -226,20 +211,13 @@ static int adc_sam0_channel_setup(const struct device *dev,
226211
if (channel_cfg->differential) {
227212
INPUTCTRL |= ADC_INPUTCTRL_MUXNEG(channel_cfg->input_negative);
228213

229-
#ifdef ADC_INPUTCTRL_DIFFMODE
230-
INPUTCTRL |= ADC_INPUTCTRL_DIFFMODE;
231-
#else
232-
adc->CTRLB.bit.DIFFMODE = 1;
233-
wait_synchronization(adc);
234-
#endif
214+
ADC_DIFF(adc) |= ADC_DIFF_MASK;
235215
} else {
236216
INPUTCTRL |= ADC_INPUTCTRL_MUXNEG_GND;
237217

238-
#ifndef ADC_INPUTCTRL_DIFFMODE
239-
adc->CTRLB.bit.DIFFMODE = 0;
240-
wait_synchronization(adc);
241-
#endif
218+
ADC_DIFF(adc) &= ~ADC_DIFF_MASK;
242219
}
220+
wait_synchronization(adc);
243221

244222
adc->INPUTCTRL.reg = INPUTCTRL;
245223
wait_synchronization(adc);
@@ -248,25 +226,21 @@ static int adc_sam0_channel_setup(const struct device *dev,
248226
switch (channel_cfg->input_positive) {
249227
#ifdef ADC_INPUTCTRL_MUXPOS_TEMP_Val
250228
case ADC_INPUTCTRL_MUXPOS_TEMP_Val:
251-
SYSCTRL->VREF.bit.TSEN = 1;
229+
ADC_TSEN = 1;
252230
break;
253231
#endif
254232
#ifdef ADC_INPUTCTRL_MUXPOS_PTAT_Val
255233
case ADC_INPUTCTRL_MUXPOS_PTAT_Val:
256-
SUPC->VREF.bit.TSEN = 1;
234+
ADC_TSEN = 1;
257235
break;
258236
#endif
259237
#ifdef ADC_INPUTCTRL_MUXPOS_CTAT_Val
260238
case ADC_INPUTCTRL_MUXPOS_CTAT_Val:
261-
SUPC->VREF.bit.TSEN = 1;
239+
ADC_TSEN = 1;
262240
break;
263241
#endif
264242
case ADC_INPUTCTRL_MUXPOS_BANDGAP_Val:
265-
#ifdef ADC_REFCTRL_REFSEL_INTREF
266-
SUPC->VREF.bit.VREFOE = 1;
267-
#else
268-
SYSCTRL->VREF.bit.BGOUTEN = 1;
269-
#endif
243+
ADC_BGEN = 1;
270244
break;
271245
default:
272246
break;
@@ -361,23 +335,22 @@ static int start_read(const struct device *dev,
361335
return -EINVAL;
362336
}
363337

364-
adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_8BIT_Val;
338+
ADC_RESSEL(adc) = ADC_RESSEL_8BIT;
365339
break;
366340
case 10:
367341
if (sequence->oversampling) {
368342
LOG_ERR("Oversampling requires 12 bit resolution");
369343
return -EINVAL;
370344
}
371345

372-
adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
346+
ADC_RESSEL(adc) = ADC_RESSEL_10BIT;
373347
break;
374348
case 12:
375349
if (sequence->oversampling) {
376-
adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_16BIT_Val;
350+
ADC_RESSEL(adc) = ADC_RESSEL_16BIT;
377351
} else {
378-
adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val;
352+
ADC_RESSEL(adc) = ADC_RESSEL_12BIT;
379353
}
380-
381354
break;
382355
default:
383356
LOG_ERR("ADC resolution value %d is not valid",
@@ -473,11 +446,7 @@ static int adc_sam0_init(const struct device *dev)
473446
GCLK->CLKCTRL.reg = cfg->gclk | GCLK_CLKCTRL_CLKEN;
474447
#endif
475448

476-
#ifdef ADC_CTRLA_PRESCALER_Pos
477-
adc->CTRLA.reg = cfg->prescaler;
478-
#else
479-
adc->CTRLB.reg = cfg->prescaler;
480-
#endif
449+
ADC_PRESCALER(adc) = cfg->prescaler;
481450
wait_synchronization(adc);
482451

483452
adc->INTENCLR.reg = ADC_INTENCLR_MASK;
@@ -532,43 +501,25 @@ static const struct adc_driver_api adc_sam0_api = {
532501
.gclk_mask = UTIL_CAT(GCLK_PCHCTRL_GEN_GCLK, \
533502
DT_INST_PROP(n, gclk)), \
534503
.gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, periph_ch), \
535-
.prescaler = UTIL_CAT(ADC_CTRLA_PRESCALER_DIV, \
536-
DT_INST_PROP(n, prescaler)),
537-
538-
#define ADC_SAM0_BIASCOMP_SHIFT(n) \
539-
(ADC0_FUSES_BIASCOMP_Pos + DT_INST_PROP(n, calib_offset))
540-
#define ADC_SAM0_BIASCOMP(n) \
541-
(((*(uint32_t *)NVMCTRL_SW0) >> ADC_SAM0_BIASCOMP_SHIFT(n)) & 0x7)
542-
543-
#define ADC_SAM0_BIASR2R_SHIFT(n) \
544-
(ADC0_FUSES_BIASR2R_Pos + DT_INST_PROP(n, calib_offset))
545-
#define ADC_SAM0_BIASR2R(n) \
546-
(((*(uint32_t *)NVMCTRL_SW0) >> ADC_SAM0_BIASR2R_SHIFT(n)) & 0x7)
547-
548-
#define ADC_SAM0_BIASREFBUF_SHIFT(n) \
549-
(ADC0_FUSES_BIASREFBUF_Pos + DT_INST_PROP(n, calib_offset))
550-
#define ADC_SAM0_BIASREFBUF(n) \
551-
(((*(uint32_t *)NVMCTRL_SW0) >> ADC_SAM0_BIASREFBUF_SHIFT(n)) & 0x7)
504+
.prescaler = UTIL_CAT(ADC_CTRLx_PRESCALER_DIV, \
505+
UTIL_CAT(DT_INST_PROP(n, prescaler), _Val)),
552506

553507
#define ADC_SAM0_CONFIGURE(n) \
554508
do { \
555509
const struct adc_sam0_cfg *const cfg = dev->config; \
556510
Adc * const adc = cfg->regs; \
557-
uint32_t comp = ADC_SAM0_BIASCOMP(n); \
558-
uint32_t r2r = ADC_SAM0_BIASR2R(n); \
559-
uint32_t rbuf = ADC_SAM0_BIASREFBUF(n); \
560-
adc->CALIB.reg = ADC_CALIB_BIASCOMP(comp) | \
561-
ADC_CALIB_BIASR2R(r2r) | \
562-
ADC_CALIB_BIASREFBUF(rbuf); \
511+
adc->CALIB.reg = ADC_SAM0_BIASCOMP(n) \
512+
| ADC_SAM0_BIASR2R(n) \
513+
| ADC_SAM0_BIASREFBUF(n); \
563514
} while (0)
564515

565516
#else
566517

567518
#define ADC_SAM0_CLOCK_CONTROL(n) \
568519
.gclk = UTIL_CAT(GCLK_CLKCTRL_GEN_GCLK, DT_INST_PROP(n, gclk)) |\
569520
GCLK_CLKCTRL_ID_ADC, \
570-
.prescaler = UTIL_CAT(ADC_CTRLB_PRESCALER_DIV, \
571-
DT_INST_PROP(n, prescaler)), \
521+
.prescaler = UTIL_CAT(ADC_CTRLx_PRESCALER_DIV, \
522+
UTIL_CAT(DT_INST_PROP(n, prescaler), _Val)),
572523

573524
#define ADC_SAM0_CONFIGURE(n) \
574525
do { \
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright (c) 2021 Argentum Systems Ltd.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef _ATMEL_SAM_ADC_FIXUP_H_
8+
#define _ATMEL_SAM_ADC_FIXUP_H_
9+
10+
#if defined(ADC_SYNCBUSY_MASK)
11+
#define ADC_SYNC(adc) ((adc)->SYNCBUSY.reg)
12+
#define ADC_SYNC_MASK (ADC_SYNCBUSY_MASK)
13+
#elif defined(ADC_STATUS_SYNCBUSY)
14+
#define ADC_SYNC(adc) ((adc)->STATUS.reg)
15+
#define ADC_SYNC_MASK (ADC_STATUS_SYNCBUSY)
16+
#else
17+
#error ADC not supported...
18+
#endif
19+
20+
#if defined(ADC_INPUTCTRL_DIFFMODE)
21+
#define ADC_DIFF(adc) (INPUTCTRL)
22+
#define ADC_DIFF_MASK (ADC_INPUTCTRL_DIFFMODE)
23+
#elif defined(ADC_CTRLB_DIFFMODE)
24+
#define ADC_DIFF(adc) ((adc)->CTRLB.reg)
25+
#define ADC_DIFF_MASK (ADC_CTRLB_DIFFMODE)
26+
#elif defined(ADC_CTRLC_DIFFMODE)
27+
#define ADC_DIFF(adc) ((adc)->CTRLC.reg)
28+
#define ADC_DIFF_MASK (ADC_CTRLC_DIFFMODE)
29+
#else
30+
#error ADC not supported...
31+
#endif
32+
33+
#if defined(ADC_CTRLB_RESSEL)
34+
#define ADC_RESSEL(adc) ((adc)->CTRLB.bit.RESSEL)
35+
#define ADC_RESSEL_8BIT ADC_CTRLB_RESSEL_8BIT_Val
36+
#define ADC_RESSEL_10BIT ADC_CTRLB_RESSEL_10BIT_Val
37+
#define ADC_RESSEL_12BIT ADC_CTRLB_RESSEL_12BIT_Val
38+
#define ADC_RESSEL_16BIT ADC_CTRLB_RESSEL_16BIT_Val
39+
#elif defined(ADC_CTRLC_RESSEL)
40+
#define ADC_RESSEL(adc) ((adc)->CTRLC.bit.RESSEL)
41+
#define ADC_RESSEL_8BIT ADC_CTRLC_RESSEL_8BIT_Val
42+
#define ADC_RESSEL_10BIT ADC_CTRLC_RESSEL_10BIT_Val
43+
#define ADC_RESSEL_12BIT ADC_CTRLC_RESSEL_12BIT_Val
44+
#define ADC_RESSEL_16BIT ADC_CTRLC_RESSEL_16BIT_Val
45+
#else
46+
#error ADC not supported...
47+
#endif
48+
49+
#if defined(ADC_CTRLA_PRESCALER)
50+
#define ADC_PRESCALER(adc) ((adc)->CTRLA.bit.PRESCALER)
51+
#define ADC_CTRLx_PRESCALER_DIV ADC_CTRLA_PRESCALER_DIV
52+
#elif defined(ADC_CTRLB_PRESCALER)
53+
#define ADC_PRESCALER(adc) ((adc)->CTRLB.bit.PRESCALER)
54+
#define ADC_CTRLx_PRESCALER_DIV ADC_CTRLB_PRESCALER_DIV
55+
#else
56+
#error ADC not supported...
57+
#endif
58+
59+
#if defined(SYSCTRL_VREF_TSEN)
60+
#define ADC_TSEN (SYSCTRL->VREF.bit.TSEN)
61+
#elif defined(SUPC_VREF_TSEN)
62+
#define ADC_TSEN (SUPC->VREF.bit.TSEN)
63+
#else
64+
#error ADC not supported...
65+
#endif
66+
67+
#if defined(SYSCTRL_VREF_BGOUTEN)
68+
#define ADC_BGEN (SYSCTRL->VREF.bit.BGOUTEN)
69+
#elif defined(SUPC_VREF_VREFOE)
70+
#define ADC_BGEN (SUPC->VREF.bit.VREFOE)
71+
#else
72+
#error ADC not supported...
73+
#endif
74+
75+
#if defined(MCLK)
76+
/* a trailing underscore and/or lumpy concatenation is used to prevent expansion */
77+
#define ADC_SAM0_CALIB(prefix, val) \
78+
UTIL_CAT(ADC_CALIB_, val)( \
79+
(((*(uint32_t *)UTIL_CAT(UTIL_CAT(UTIL_CAT(prefix, FUSES_), val), _ADDR)) \
80+
>> UTIL_CAT(UTIL_CAT(UTIL_CAT(prefix, FUSES_), val), _Pos)) \
81+
& UTIL_CAT(UTIL_CAT(UTIL_CAT(prefix, FUSES_), val), _Msk)) \
82+
)
83+
84+
#if ADC_INST_NUM == 1
85+
# define ADC_FUSES_PREFIX(n) ADC_
86+
#else
87+
# define ADC_FUSES_PREFIX(n) UTIL_CAT(AD, UTIL_CAT(C, UTIL_CAT(n, _)))
88+
#endif
89+
90+
#if defined(ADC_FUSES_BIASCOMP) || defined(ADC0_FUSES_BIASCOMP)
91+
# define ADC_SAM0_BIASCOMP(n) ADC_SAM0_CALIB(ADC_FUSES_PREFIX(n), BIASCOMP)
92+
#else
93+
# define ADC_SAM0_BIASCOMP(n) 0
94+
#endif
95+
96+
#if defined(ADC_FUSES_BIASR2R) || defined(ADC0_FUSES_BIASR2R)
97+
# define ADC_SAM0_BIASR2R(n) ADC_SAM0_CALIB(ADC_FUSES_PREFIX(n), BIASR2R)
98+
#else
99+
# define ADC_SAM0_BIASR2R(n) 0
100+
#endif
101+
102+
#if defined(ADC_FUSES_BIASREFBUF) || defined(ADC0_FUSES_BIASREFBUF)
103+
# define ADC_SAM0_BIASREFBUF(n) ADC_SAM0_CALIB(ADC_FUSES_PREFIX(n), BIASREFBUF)
104+
#else
105+
# define ADC_SAM0_BIASREFBUF(n) 0
106+
#endif
107+
#endif /* MCLK */
108+
109+
#ifndef ADC_REFCTRL_REFSEL_INTERNAL
110+
# ifdef ADC_REFCTRL_REFSEL_INTREF
111+
# define ADC_REFCTRL_REFSEL_INTERNAL ADC_REFCTRL_REFSEL_INTREF
112+
# else
113+
# define ADC_REFCTRL_REFSEL_INTERNAL ADC_REFCTRL_REFSEL_INT1V
114+
# endif
115+
#endif
116+
117+
#ifndef ADC_REFCTRL_REFSEL_VDD_1_2
118+
# ifdef ADC_REFCTRL_REFSEL_INTVCC0
119+
# define ADC_REFCTRL_REFSEL_VDD_1_2 ADC_REFCTRL_REFSEL_INTVCC0
120+
# else
121+
# define ADC_REFCTRL_REFSEL_VDD_1_2 ADC_REFCTRL_REFSEL_INTVCC1
122+
# endif
123+
#endif
124+
125+
#ifndef ADC_REFCTRL_REFSEL_VDD_1
126+
# ifdef ADC_REFCTRL_REFSEL_INTVCC1
127+
# define ADC_REFCTRL_REFSEL_VDD_1 ADC_REFCTRL_REFSEL_INTVCC1
128+
# endif
129+
#endif
130+
131+
#endif /* _ATMEL_SAM0_ADC_FIXUP_H_ */

soc/arm/atmel_sam0/samd20/soc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454

5555
#endif /* _ASMLANGUAGE */
5656

57+
#include "adc_fixup_sam0.h"
5758
#include "../common/soc_port.h"
5859
#include "../common/atmel_sam0_dt.h"
5960

soc/arm/atmel_sam0/samd21/soc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848

4949
#endif /* _ASMLANGUAGE */
5050

51+
#include "adc_fixup_sam0.h"
5152
#include "../common/soc_port.h"
5253
#include "../common/atmel_sam0_dt.h"
5354

soc/arm/atmel_sam0/samd51/soc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040

4141
#include "sercom_fixup_samd5x.h"
4242
#include "tc_fixup_samd5x.h"
43+
#include "adc_fixup_sam0.h"
4344
#include "../common/soc_port.h"
4445
#include "../common/atmel_sam0_dt.h"
4546

soc/arm/atmel_sam0/same51/soc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
#include "sercom_fixup_samd5x.h"
3434
#include "tc_fixup_samd5x.h"
35+
#include "adc_fixup_sam0.h"
3536
#include "../common/soc_port.h"
3637
#include "../common/atmel_sam0_dt.h"
3738

soc/arm/atmel_sam0/same53/soc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "sercom_fixup_samd5x.h"
3434
#include "tc_fixup_samd5x.h"
3535
#include "gmac_fixup_samd5x.h"
36+
#include "adc_fixup_sam0.h"
3637
#include "../common/soc_port.h"
3738
#include "../common/atmel_sam0_dt.h"
3839

soc/arm/atmel_sam0/same54/soc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "sercom_fixup_samd5x.h"
3232
#include "tc_fixup_samd5x.h"
3333
#include "gmac_fixup_samd5x.h"
34+
#include "adc_fixup_sam0.h"
3435
#include "../common/soc_port.h"
3536
#include "../common/atmel_sam0_dt.h"
3637

soc/arm/atmel_sam0/samr21/soc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
#endif /* _ASMLANGUAGE */
3636

37+
#include "adc_fixup_sam0.h"
3738
#include "../common/soc_port.h"
3839
#include "../common/atmel_sam0_dt.h"
3940

0 commit comments

Comments
 (0)