drivers: adc: stm32: add support for stm32g0 series

Adds support for ADC on G0 series.
Simple implementation: sequencer not fully configurable,
and only one common sampling time.

Signed-off-by: Thomas Stranger <thomas.stranger@outlook.com>
This commit is contained in:
Thomas Stranger 2020-12-21 03:00:00 +01:00 committed by Maureen Helm
commit 4ed375040e
2 changed files with 64 additions and 12 deletions

View file

@ -29,6 +29,7 @@ LOG_MODULE_REGISTER(adc_stm32);
#include <pinmux/stm32/pinmux_stm32.h>
#if !defined(CONFIG_SOC_SERIES_STM32F0X) && \
!defined(CONFIG_SOC_SERIES_STM32G0X) && \
!defined(CONFIG_SOC_SERIES_STM32L0X)
#define RANK(n) LL_ADC_REG_RANK_##n
static const uint32_t table_rank[] = {
@ -148,7 +149,8 @@ static const uint32_t table_samp_time[] = {
SMP_TIME(239, S_5),
};
#endif /* ADC5_V1_1 */
#elif defined(CONFIG_SOC_SERIES_STM32L0X)
#elif defined(CONFIG_SOC_SERIES_STM32L0X) || \
defined(CONFIG_SOC_SERIES_STM32G0X)
static const uint16_t acq_time_tbl[8] = {2, 4, 8, 13, 20, 40, 80, 161};
static const uint32_t table_samp_time[] = {
SMP_TIME(1, _5),
@ -211,7 +213,9 @@ struct adc_stm32_data {
uint8_t resolution;
uint8_t channel_count;
#if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32L0X)
#if defined(CONFIG_SOC_SERIES_STM32F0X) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32L0X)
int8_t acq_time_index;
#endif
};
@ -256,6 +260,7 @@ static void adc_stm32_start_conversion(const struct device *dev)
defined(CONFIG_SOC_SERIES_STM32L0X) || \
defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32WBX) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32G4X) || \
defined(CONFIG_SOC_SERIES_STM32H7X)
LL_ADC_REG_StartConversion(adc);
@ -332,6 +337,11 @@ static int start_read(const struct device *dev,
#if defined(CONFIG_SOC_SERIES_STM32F0X) || \
defined(CONFIG_SOC_SERIES_STM32L0X)
LL_ADC_REG_SetSequencerChannels(adc, channel);
#elif defined(CONFIG_SOC_SERIES_STM32G0X)
/* STM32G0 in "not fully configurable" sequencer mode */
LL_ADC_REG_SetSequencerChannels(adc, channel);
while (LL_ADC_IsActiveFlag_CCRDY(adc) == 0) {
}
#else
LL_ADC_REG_SetSequencerRanks(adc, table_rank[0], channel);
LL_ADC_REG_SetSequencerLength(adc, table_seq_len[0]);
@ -343,7 +353,21 @@ static int start_read(const struct device *dev,
return err;
}
#if !defined(CONFIG_SOC_SERIES_STM32F1X)
#if defined(CONFIG_SOC_SERIES_STM32G0X)
/*
* Errata: Writing ADC_CFGR1 register while ADEN bit is set
* resets RES[1:0] bitfield. We need to disable and enable adc.
*/
if (LL_ADC_IsEnabled(adc) == 1UL) {
LL_ADC_Disable(adc);
}
while (LL_ADC_IsEnabled(adc) == 1UL) {
}
LL_ADC_SetResolution(adc, resolution);
LL_ADC_Enable(adc);
while (LL_ADC_IsActiveFlag_ADRDY(adc) != 1UL) {
}
#elif !defined(CONFIG_SOC_SERIES_STM32F1X)
LL_ADC_SetResolution(adc, resolution);
#endif
@ -352,6 +376,7 @@ static int start_read(const struct device *dev,
defined(CONFIG_SOC_SERIES_STM32L0X) || \
defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32WBX) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32G4X) || \
defined(CONFIG_SOC_SERIES_STM32H7X)
LL_ADC_EnableIT_EOC(adc);
@ -457,6 +482,9 @@ static void adc_stm32_setup_speed(const struct device *dev, uint8_t id,
#if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32L0X)
LL_ADC_SetSamplingTimeCommonChannels(adc,
table_samp_time[acq_time_index]);
#elif defined(CONFIG_SOC_SERIES_STM32G0X)
LL_ADC_SetSamplingTimeCommonChannels(adc, LL_ADC_SAMPLINGTIME_COMMON_1,
table_samp_time[acq_time_index]);
#else
LL_ADC_SetChannelSamplingTime(adc,
__LL_ADC_DECIMAL_NB_TO_CHANNEL(id),
@ -467,7 +495,9 @@ static void adc_stm32_setup_speed(const struct device *dev, uint8_t id,
static int adc_stm32_channel_setup(const struct device *dev,
const struct adc_channel_cfg *channel_cfg)
{
#if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32L0X)
#if defined(CONFIG_SOC_SERIES_STM32F0X) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32L0X)
struct adc_stm32_data *data = dev->data;
#endif
int acq_time_index;
@ -482,7 +512,9 @@ static int adc_stm32_channel_setup(const struct device *dev,
if (acq_time_index < 0) {
return acq_time_index;
}
#if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32L0X)
#if defined(CONFIG_SOC_SERIES_STM32F0X) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32L0X)
if (data->acq_time_index == -1) {
data->acq_time_index = acq_time_index;
} else {
@ -533,6 +565,7 @@ static void adc_stm32_calib(const struct device *dev)
defined(CONFIG_SOC_SERIES_STM32G4X)
LL_ADC_StartCalibration(adc, LL_ADC_SINGLE_ENDED);
#elif defined(CONFIG_SOC_SERIES_STM32F0X) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32L0X)
LL_ADC_StartCalibration(adc);
#elif defined(CONFIG_SOC_SERIES_STM32H7X)
@ -555,12 +588,15 @@ static int adc_stm32_init(const struct device *dev)
LOG_DBG("Initializing....");
data->dev = dev;
#if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32L0X)
#if defined(CONFIG_SOC_SERIES_STM32F0X) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32L0X)
/*
* All conversion time for all channels on one ADC instance for F0 and
* L0 series chips has to be the same. This additional variable is for
* checking if the conversion time selection of all channels on one ADC
* instance is the same.
* L0 series chips has to be the same. For STM32G0 currently only one
* of the two available common channel conversion times is used.
* This additional variable is for checking if the conversion time
* selection of all channels on one ADC instance is the same.
*/
data->acq_time_index = -1;
#endif
@ -591,12 +627,13 @@ static int adc_stm32_init(const struct device *dev)
LL_ADC_DisableDeepPowerDown(adc);
#endif
/*
* F3, L4, WB and G4 ADC modules need some time to be stabilized before
* performing any enable or calibration actions.
* F3, L4, WB, G0 and G4 ADC modules need some time
* to be stabilized before performing any enable or calibration actions.
*/
#if defined(CONFIG_SOC_SERIES_STM32F3X) || \
defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32WBX) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32G4X) || \
defined(CONFIG_SOC_SERIES_STM32H7X)
LL_ADC_EnableInternalRegulator(adc);
@ -609,6 +646,7 @@ static int adc_stm32_init(const struct device *dev)
#elif defined(CONFIG_SOC_SERIES_STM32F3X) || \
defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32WBX) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32G4X) || \
defined(CONFIG_SOC_SERIES_STM32H7X)
LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(adc),
@ -634,6 +672,7 @@ static int adc_stm32_init(const struct device *dev)
defined(CONFIG_SOC_SERIES_STM32L0X) || \
defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32WBX) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32G4X) || \
defined(CONFIG_SOC_SERIES_STM32H7X)
if (LL_ADC_IsActiveFlag_ADRDY(adc)) {
@ -653,6 +692,7 @@ static int adc_stm32_init(const struct device *dev)
defined(CONFIG_SOC_SERIES_STM32L0X) || \
defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32WBX) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32G4X) || \
defined(CONFIG_SOC_SERIES_STM32H7X)
/*
@ -677,10 +717,11 @@ static int adc_stm32_init(const struct device *dev)
#if defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32WBX) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32G4X) || \
defined(CONFIG_SOC_SERIES_STM32H7X)
/*
* Enabling ADC modules in L4, WB and G4 series may fail if they are
* Enabling ADC modules in L4, WB, G0 and G4 series may fail if they are
* still not stabilized, this will wait for a short time to ensure ADC
* modules are properly enabled.
*/

View file

@ -230,6 +230,17 @@
status = "disabled";
label = "SPI_2";
};
adc1: adc@40012400 {
compatible = "st,stm32-adc";
reg = <0x40012400 0x400>;
clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00100000>;
interrupts = <12 0>;
interrupt-names = "combined";
status = "disabled";
label = "ADC_1";
#io-channel-cells = <1>;
};
};
};