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 <attie.grande@argentum-systems.co.uk>
This commit is contained in:
parent
ec1ab6d104
commit
e4d4eaca03
|
@ -60,13 +60,8 @@ struct adc_sam0_cfg {
|
|||
|
||||
static void wait_synchronization(Adc *const adc)
|
||||
{
|
||||
#if defined(ADC_SYNCBUSY_MASK)
|
||||
while ((adc->SYNCBUSY.reg & ADC_SYNCBUSY_MASK) != 0) {
|
||||
while ((ADC_SYNC(adc) & ADC_SYNC_MASK) != 0) {
|
||||
}
|
||||
#else
|
||||
while ((adc->STATUS.reg & ADC_STATUS_SYNCBUSY) != 0) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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,
|
|||
|
||||
switch (channel_cfg->reference) {
|
||||
case ADC_REF_INTERNAL:
|
||||
#ifdef ADC_REFCTRL_REFSEL_INTREF
|
||||
REFCTRL = ADC_REFCTRL_REFSEL_INTREF | ADC_REFCTRL_REFCOMP;
|
||||
/* Enable the internal reference, defaulting to 1V */
|
||||
SUPC->VREF.bit.VREFOE = 1;
|
||||
#else
|
||||
REFCTRL = ADC_REFCTRL_REFSEL_INT1V | ADC_REFCTRL_REFCOMP;
|
||||
REFCTRL = ADC_REFCTRL_REFSEL_INTERNAL | ADC_REFCTRL_REFCOMP;
|
||||
/* Enable the internal bandgap reference */
|
||||
SYSCTRL->VREF.bit.BGOUTEN = 1;
|
||||
#endif
|
||||
ADC_BGEN = 1;
|
||||
break;
|
||||
case ADC_REF_VDD_1_2:
|
||||
#ifdef ADC_REFCTRL_REFSEL_INTVCC0
|
||||
REFCTRL = ADC_REFCTRL_REFSEL_INTVCC0 | ADC_REFCTRL_REFCOMP;
|
||||
#else
|
||||
REFCTRL = ADC_REFCTRL_REFSEL_INTVCC1 | ADC_REFCTRL_REFCOMP;
|
||||
#endif
|
||||
REFCTRL = ADC_REFCTRL_REFSEL_VDD_1_2 | ADC_REFCTRL_REFCOMP;
|
||||
break;
|
||||
#ifdef ADC_REFCTRL_REFSEL_INTVCC1
|
||||
#ifdef ADC_REFCTRL_REFSEL_VDD_1
|
||||
case ADC_REF_VDD_1:
|
||||
REFCTRL = ADC_REFCTRL_REFSEL_INTVCC1 | ADC_REFCTRL_REFCOMP;
|
||||
REFCTRL = ADC_REFCTRL_REFSEL_VDD_1 | ADC_REFCTRL_REFCOMP;
|
||||
break;
|
||||
#endif
|
||||
case ADC_REF_EXTERNAL0:
|
||||
|
@ -226,20 +211,13 @@ static int adc_sam0_channel_setup(const struct device *dev,
|
|||
if (channel_cfg->differential) {
|
||||
INPUTCTRL |= ADC_INPUTCTRL_MUXNEG(channel_cfg->input_negative);
|
||||
|
||||
#ifdef ADC_INPUTCTRL_DIFFMODE
|
||||
INPUTCTRL |= ADC_INPUTCTRL_DIFFMODE;
|
||||
#else
|
||||
adc->CTRLB.bit.DIFFMODE = 1;
|
||||
wait_synchronization(adc);
|
||||
#endif
|
||||
ADC_DIFF(adc) |= ADC_DIFF_MASK;
|
||||
} else {
|
||||
INPUTCTRL |= ADC_INPUTCTRL_MUXNEG_GND;
|
||||
|
||||
#ifndef ADC_INPUTCTRL_DIFFMODE
|
||||
adc->CTRLB.bit.DIFFMODE = 0;
|
||||
wait_synchronization(adc);
|
||||
#endif
|
||||
ADC_DIFF(adc) &= ~ADC_DIFF_MASK;
|
||||
}
|
||||
wait_synchronization(adc);
|
||||
|
||||
adc->INPUTCTRL.reg = INPUTCTRL;
|
||||
wait_synchronization(adc);
|
||||
|
@ -248,25 +226,21 @@ static int adc_sam0_channel_setup(const struct device *dev,
|
|||
switch (channel_cfg->input_positive) {
|
||||
#ifdef ADC_INPUTCTRL_MUXPOS_TEMP_Val
|
||||
case ADC_INPUTCTRL_MUXPOS_TEMP_Val:
|
||||
SYSCTRL->VREF.bit.TSEN = 1;
|
||||
ADC_TSEN = 1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef ADC_INPUTCTRL_MUXPOS_PTAT_Val
|
||||
case ADC_INPUTCTRL_MUXPOS_PTAT_Val:
|
||||
SUPC->VREF.bit.TSEN = 1;
|
||||
ADC_TSEN = 1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef ADC_INPUTCTRL_MUXPOS_CTAT_Val
|
||||
case ADC_INPUTCTRL_MUXPOS_CTAT_Val:
|
||||
SUPC->VREF.bit.TSEN = 1;
|
||||
ADC_TSEN = 1;
|
||||
break;
|
||||
#endif
|
||||
case ADC_INPUTCTRL_MUXPOS_BANDGAP_Val:
|
||||
#ifdef ADC_REFCTRL_REFSEL_INTREF
|
||||
SUPC->VREF.bit.VREFOE = 1;
|
||||
#else
|
||||
SYSCTRL->VREF.bit.BGOUTEN = 1;
|
||||
#endif
|
||||
ADC_BGEN = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -361,7 +335,7 @@ static int start_read(const struct device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_8BIT_Val;
|
||||
ADC_RESSEL(adc) = ADC_RESSEL_8BIT;
|
||||
break;
|
||||
case 10:
|
||||
if (sequence->oversampling) {
|
||||
|
@ -369,15 +343,14 @@ static int start_read(const struct device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
|
||||
ADC_RESSEL(adc) = ADC_RESSEL_10BIT;
|
||||
break;
|
||||
case 12:
|
||||
if (sequence->oversampling) {
|
||||
adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_16BIT_Val;
|
||||
ADC_RESSEL(adc) = ADC_RESSEL_16BIT;
|
||||
} else {
|
||||
adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val;
|
||||
ADC_RESSEL(adc) = ADC_RESSEL_12BIT;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("ADC resolution value %d is not valid",
|
||||
|
@ -473,11 +446,7 @@ static int adc_sam0_init(const struct device *dev)
|
|||
GCLK->CLKCTRL.reg = cfg->gclk | GCLK_CLKCTRL_CLKEN;
|
||||
#endif
|
||||
|
||||
#ifdef ADC_CTRLA_PRESCALER_Pos
|
||||
adc->CTRLA.reg = cfg->prescaler;
|
||||
#else
|
||||
adc->CTRLB.reg = cfg->prescaler;
|
||||
#endif
|
||||
ADC_PRESCALER(adc) = cfg->prescaler;
|
||||
wait_synchronization(adc);
|
||||
|
||||
adc->INTENCLR.reg = ADC_INTENCLR_MASK;
|
||||
|
@ -532,34 +501,16 @@ static const struct adc_driver_api adc_sam0_api = {
|
|||
.gclk_mask = UTIL_CAT(GCLK_PCHCTRL_GEN_GCLK, \
|
||||
DT_INST_PROP(n, gclk)), \
|
||||
.gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, periph_ch), \
|
||||
.prescaler = UTIL_CAT(ADC_CTRLA_PRESCALER_DIV, \
|
||||
DT_INST_PROP(n, prescaler)),
|
||||
|
||||
#define ADC_SAM0_BIASCOMP_SHIFT(n) \
|
||||
(ADC0_FUSES_BIASCOMP_Pos + DT_INST_PROP(n, calib_offset))
|
||||
#define ADC_SAM0_BIASCOMP(n) \
|
||||
(((*(uint32_t *)NVMCTRL_SW0) >> ADC_SAM0_BIASCOMP_SHIFT(n)) & 0x7)
|
||||
|
||||
#define ADC_SAM0_BIASR2R_SHIFT(n) \
|
||||
(ADC0_FUSES_BIASR2R_Pos + DT_INST_PROP(n, calib_offset))
|
||||
#define ADC_SAM0_BIASR2R(n) \
|
||||
(((*(uint32_t *)NVMCTRL_SW0) >> ADC_SAM0_BIASR2R_SHIFT(n)) & 0x7)
|
||||
|
||||
#define ADC_SAM0_BIASREFBUF_SHIFT(n) \
|
||||
(ADC0_FUSES_BIASREFBUF_Pos + DT_INST_PROP(n, calib_offset))
|
||||
#define ADC_SAM0_BIASREFBUF(n) \
|
||||
(((*(uint32_t *)NVMCTRL_SW0) >> ADC_SAM0_BIASREFBUF_SHIFT(n)) & 0x7)
|
||||
.prescaler = UTIL_CAT(ADC_CTRLx_PRESCALER_DIV, \
|
||||
UTIL_CAT(DT_INST_PROP(n, prescaler), _Val)),
|
||||
|
||||
#define ADC_SAM0_CONFIGURE(n) \
|
||||
do { \
|
||||
const struct adc_sam0_cfg *const cfg = dev->config; \
|
||||
Adc * const adc = cfg->regs; \
|
||||
uint32_t comp = ADC_SAM0_BIASCOMP(n); \
|
||||
uint32_t r2r = ADC_SAM0_BIASR2R(n); \
|
||||
uint32_t rbuf = ADC_SAM0_BIASREFBUF(n); \
|
||||
adc->CALIB.reg = ADC_CALIB_BIASCOMP(comp) | \
|
||||
ADC_CALIB_BIASR2R(r2r) | \
|
||||
ADC_CALIB_BIASREFBUF(rbuf); \
|
||||
adc->CALIB.reg = ADC_SAM0_BIASCOMP(n) \
|
||||
| ADC_SAM0_BIASR2R(n) \
|
||||
| ADC_SAM0_BIASREFBUF(n); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
@ -567,8 +518,8 @@ do { \
|
|||
#define ADC_SAM0_CLOCK_CONTROL(n) \
|
||||
.gclk = UTIL_CAT(GCLK_CLKCTRL_GEN_GCLK, DT_INST_PROP(n, gclk)) |\
|
||||
GCLK_CLKCTRL_ID_ADC, \
|
||||
.prescaler = UTIL_CAT(ADC_CTRLB_PRESCALER_DIV, \
|
||||
DT_INST_PROP(n, prescaler)), \
|
||||
.prescaler = UTIL_CAT(ADC_CTRLx_PRESCALER_DIV, \
|
||||
UTIL_CAT(DT_INST_PROP(n, prescaler), _Val)),
|
||||
|
||||
#define ADC_SAM0_CONFIGURE(n) \
|
||||
do { \
|
||||
|
|
131
soc/arm/atmel_sam0/common/adc_fixup_sam0.h
Normal file
131
soc/arm/atmel_sam0/common/adc_fixup_sam0.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Argentum Systems Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _ATMEL_SAM_ADC_FIXUP_H_
|
||||
#define _ATMEL_SAM_ADC_FIXUP_H_
|
||||
|
||||
#if defined(ADC_SYNCBUSY_MASK)
|
||||
#define ADC_SYNC(adc) ((adc)->SYNCBUSY.reg)
|
||||
#define ADC_SYNC_MASK (ADC_SYNCBUSY_MASK)
|
||||
#elif defined(ADC_STATUS_SYNCBUSY)
|
||||
#define ADC_SYNC(adc) ((adc)->STATUS.reg)
|
||||
#define ADC_SYNC_MASK (ADC_STATUS_SYNCBUSY)
|
||||
#else
|
||||
#error ADC not supported...
|
||||
#endif
|
||||
|
||||
#if defined(ADC_INPUTCTRL_DIFFMODE)
|
||||
#define ADC_DIFF(adc) (INPUTCTRL)
|
||||
#define ADC_DIFF_MASK (ADC_INPUTCTRL_DIFFMODE)
|
||||
#elif defined(ADC_CTRLB_DIFFMODE)
|
||||
#define ADC_DIFF(adc) ((adc)->CTRLB.reg)
|
||||
#define ADC_DIFF_MASK (ADC_CTRLB_DIFFMODE)
|
||||
#elif defined(ADC_CTRLC_DIFFMODE)
|
||||
#define ADC_DIFF(adc) ((adc)->CTRLC.reg)
|
||||
#define ADC_DIFF_MASK (ADC_CTRLC_DIFFMODE)
|
||||
#else
|
||||
#error ADC not supported...
|
||||
#endif
|
||||
|
||||
#if defined(ADC_CTRLB_RESSEL)
|
||||
#define ADC_RESSEL(adc) ((adc)->CTRLB.bit.RESSEL)
|
||||
#define ADC_RESSEL_8BIT ADC_CTRLB_RESSEL_8BIT_Val
|
||||
#define ADC_RESSEL_10BIT ADC_CTRLB_RESSEL_10BIT_Val
|
||||
#define ADC_RESSEL_12BIT ADC_CTRLB_RESSEL_12BIT_Val
|
||||
#define ADC_RESSEL_16BIT ADC_CTRLB_RESSEL_16BIT_Val
|
||||
#elif defined(ADC_CTRLC_RESSEL)
|
||||
#define ADC_RESSEL(adc) ((adc)->CTRLC.bit.RESSEL)
|
||||
#define ADC_RESSEL_8BIT ADC_CTRLC_RESSEL_8BIT_Val
|
||||
#define ADC_RESSEL_10BIT ADC_CTRLC_RESSEL_10BIT_Val
|
||||
#define ADC_RESSEL_12BIT ADC_CTRLC_RESSEL_12BIT_Val
|
||||
#define ADC_RESSEL_16BIT ADC_CTRLC_RESSEL_16BIT_Val
|
||||
#else
|
||||
#error ADC not supported...
|
||||
#endif
|
||||
|
||||
#if defined(ADC_CTRLA_PRESCALER)
|
||||
#define ADC_PRESCALER(adc) ((adc)->CTRLA.bit.PRESCALER)
|
||||
#define ADC_CTRLx_PRESCALER_DIV ADC_CTRLA_PRESCALER_DIV
|
||||
#elif defined(ADC_CTRLB_PRESCALER)
|
||||
#define ADC_PRESCALER(adc) ((adc)->CTRLB.bit.PRESCALER)
|
||||
#define ADC_CTRLx_PRESCALER_DIV ADC_CTRLB_PRESCALER_DIV
|
||||
#else
|
||||
#error ADC not supported...
|
||||
#endif
|
||||
|
||||
#if defined(SYSCTRL_VREF_TSEN)
|
||||
#define ADC_TSEN (SYSCTRL->VREF.bit.TSEN)
|
||||
#elif defined(SUPC_VREF_TSEN)
|
||||
#define ADC_TSEN (SUPC->VREF.bit.TSEN)
|
||||
#else
|
||||
#error ADC not supported...
|
||||
#endif
|
||||
|
||||
#if defined(SYSCTRL_VREF_BGOUTEN)
|
||||
#define ADC_BGEN (SYSCTRL->VREF.bit.BGOUTEN)
|
||||
#elif defined(SUPC_VREF_VREFOE)
|
||||
#define ADC_BGEN (SUPC->VREF.bit.VREFOE)
|
||||
#else
|
||||
#error ADC not supported...
|
||||
#endif
|
||||
|
||||
#if defined(MCLK)
|
||||
/* a trailing underscore and/or lumpy concatenation is used to prevent expansion */
|
||||
#define ADC_SAM0_CALIB(prefix, val) \
|
||||
UTIL_CAT(ADC_CALIB_, val)( \
|
||||
(((*(uint32_t *)UTIL_CAT(UTIL_CAT(UTIL_CAT(prefix, FUSES_), val), _ADDR)) \
|
||||
>> UTIL_CAT(UTIL_CAT(UTIL_CAT(prefix, FUSES_), val), _Pos)) \
|
||||
& UTIL_CAT(UTIL_CAT(UTIL_CAT(prefix, FUSES_), val), _Msk)) \
|
||||
)
|
||||
|
||||
#if ADC_INST_NUM == 1
|
||||
# define ADC_FUSES_PREFIX(n) ADC_
|
||||
#else
|
||||
# define ADC_FUSES_PREFIX(n) UTIL_CAT(AD, UTIL_CAT(C, UTIL_CAT(n, _)))
|
||||
#endif
|
||||
|
||||
#if defined(ADC_FUSES_BIASCOMP) || defined(ADC0_FUSES_BIASCOMP)
|
||||
# define ADC_SAM0_BIASCOMP(n) ADC_SAM0_CALIB(ADC_FUSES_PREFIX(n), BIASCOMP)
|
||||
#else
|
||||
# define ADC_SAM0_BIASCOMP(n) 0
|
||||
#endif
|
||||
|
||||
#if defined(ADC_FUSES_BIASR2R) || defined(ADC0_FUSES_BIASR2R)
|
||||
# define ADC_SAM0_BIASR2R(n) ADC_SAM0_CALIB(ADC_FUSES_PREFIX(n), BIASR2R)
|
||||
#else
|
||||
# define ADC_SAM0_BIASR2R(n) 0
|
||||
#endif
|
||||
|
||||
#if defined(ADC_FUSES_BIASREFBUF) || defined(ADC0_FUSES_BIASREFBUF)
|
||||
# define ADC_SAM0_BIASREFBUF(n) ADC_SAM0_CALIB(ADC_FUSES_PREFIX(n), BIASREFBUF)
|
||||
#else
|
||||
# define ADC_SAM0_BIASREFBUF(n) 0
|
||||
#endif
|
||||
#endif /* MCLK */
|
||||
|
||||
#ifndef ADC_REFCTRL_REFSEL_INTERNAL
|
||||
# ifdef ADC_REFCTRL_REFSEL_INTREF
|
||||
# define ADC_REFCTRL_REFSEL_INTERNAL ADC_REFCTRL_REFSEL_INTREF
|
||||
# else
|
||||
# define ADC_REFCTRL_REFSEL_INTERNAL ADC_REFCTRL_REFSEL_INT1V
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ADC_REFCTRL_REFSEL_VDD_1_2
|
||||
# ifdef ADC_REFCTRL_REFSEL_INTVCC0
|
||||
# define ADC_REFCTRL_REFSEL_VDD_1_2 ADC_REFCTRL_REFSEL_INTVCC0
|
||||
# else
|
||||
# define ADC_REFCTRL_REFSEL_VDD_1_2 ADC_REFCTRL_REFSEL_INTVCC1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ADC_REFCTRL_REFSEL_VDD_1
|
||||
# ifdef ADC_REFCTRL_REFSEL_INTVCC1
|
||||
# define ADC_REFCTRL_REFSEL_VDD_1 ADC_REFCTRL_REFSEL_INTVCC1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _ATMEL_SAM0_ADC_FIXUP_H_ */
|
|
@ -54,6 +54,7 @@
|
|||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#include "adc_fixup_sam0.h"
|
||||
#include "../common/soc_port.h"
|
||||
#include "../common/atmel_sam0_dt.h"
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#include "adc_fixup_sam0.h"
|
||||
#include "../common/soc_port.h"
|
||||
#include "../common/atmel_sam0_dt.h"
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
#include "sercom_fixup_samd5x.h"
|
||||
#include "tc_fixup_samd5x.h"
|
||||
#include "adc_fixup_sam0.h"
|
||||
#include "../common/soc_port.h"
|
||||
#include "../common/atmel_sam0_dt.h"
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "sercom_fixup_samd5x.h"
|
||||
#include "tc_fixup_samd5x.h"
|
||||
#include "adc_fixup_sam0.h"
|
||||
#include "../common/soc_port.h"
|
||||
#include "../common/atmel_sam0_dt.h"
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "sercom_fixup_samd5x.h"
|
||||
#include "tc_fixup_samd5x.h"
|
||||
#include "gmac_fixup_samd5x.h"
|
||||
#include "adc_fixup_sam0.h"
|
||||
#include "../common/soc_port.h"
|
||||
#include "../common/atmel_sam0_dt.h"
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "sercom_fixup_samd5x.h"
|
||||
#include "tc_fixup_samd5x.h"
|
||||
#include "gmac_fixup_samd5x.h"
|
||||
#include "adc_fixup_sam0.h"
|
||||
#include "../common/soc_port.h"
|
||||
#include "../common/atmel_sam0_dt.h"
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#include "adc_fixup_sam0.h"
|
||||
#include "../common/soc_port.h"
|
||||
#include "../common/atmel_sam0_dt.h"
|
||||
|
||||
|
|
Loading…
Reference in a new issue