From 00b152d3718371b95046f19a2d7eb66c6e6ff723 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Wed, 2 Oct 2024 16:08:42 +0200 Subject: [PATCH] drivers: adc: nrf: add support for nrf54l internal SAADC inputs SAADC peripheral for nRF54L Series allows to choose internal voltages as positive inputs. Signed-off-by: Nikodem Kastelik --- drivers/adc/adc_nrfx_saadc.c | 38 +++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/drivers/adc/adc_nrfx_saadc.c b/drivers/adc/adc_nrfx_saadc.c index 052eab45b6ca57a..41c2babd3040ab2 100644 --- a/drivers/adc/adc_nrfx_saadc.c +++ b/drivers/adc/adc_nrfx_saadc.c @@ -7,7 +7,8 @@ #define ADC_CONTEXT_USES_KERNEL_TIMER #include "adc_context.h" #include -#include +#include +#include #include #define LOG_LEVEL CONFIG_ADC_LOG_LEVEL @@ -17,6 +18,8 @@ LOG_MODULE_REGISTER(adc_nrfx_saadc); #define DT_DRV_COMPAT nordic_nrf_saadc +#define SAADC_INPUT_INVALID 0xFEU + #if (NRF_SAADC_HAS_AIN_AS_PIN) #if defined(CONFIG_SOC_NRF54H20) || defined(CONFIG_SOC_NRF9280) @@ -31,7 +34,7 @@ static const uint8_t saadc_psels[NRF_SAADC_AIN7 + 1] = { [NRF_SAADC_AIN7] = NRF_PIN_PORT_TO_PIN_NUMBER(7U, 1), }; #elif defined(CONFIG_SOC_NRF54L15) -static const uint8_t saadc_psels[NRF_SAADC_AIN7 + 1] = { +static const uint32_t saadc_psels[NRF_SAADC_DVDD + 1] = { [NRF_SAADC_AIN0] = NRF_PIN_PORT_TO_PIN_NUMBER(4U, 1), [NRF_SAADC_AIN1] = NRF_PIN_PORT_TO_PIN_NUMBER(5U, 1), [NRF_SAADC_AIN2] = NRF_PIN_PORT_TO_PIN_NUMBER(6U, 1), @@ -40,6 +43,9 @@ static const uint8_t saadc_psels[NRF_SAADC_AIN7 + 1] = { [NRF_SAADC_AIN5] = NRF_PIN_PORT_TO_PIN_NUMBER(12U, 1), [NRF_SAADC_AIN6] = NRF_PIN_PORT_TO_PIN_NUMBER(13U, 1), [NRF_SAADC_AIN7] = NRF_PIN_PORT_TO_PIN_NUMBER(14U, 1), + [NRF_SAADC_VDD] = NRF_SAADC_INPUT_VDD, + [NRF_SAADC_AVDD] = NRF_SAADC_INPUT_AVDD, + [NRF_SAADC_DVDD] = NRF_SAADC_INPUT_DVDD, }; #endif @@ -273,13 +279,8 @@ static int adc_nrfx_channel_setup(const struct device *dev, m_data.single_ended_channels |= BIT(channel_cfg->channel_id); } - /* Keep the channel disabled in hardware (set positive input to - * NRF_SAADC_INPUT_DISABLED) until it is selected to be included - * in a sampling sequence. - */ - #if (NRF_SAADC_HAS_AIN_AS_PIN) - if ((channel_cfg->input_positive > NRF_SAADC_AIN7) || + if ((channel_cfg->input_positive >= ARRAY_SIZE(saadc_psels)) || (channel_cfg->input_positive < NRF_SAADC_AIN0)) { return -EINVAL; } @@ -294,17 +295,18 @@ static int adc_nrfx_channel_setup(const struct device *dev, } else { input_negative = NRF_SAADC_INPUT_DISABLED; } - +#endif /* Store the positive input selection in a dedicated array, * to get it later when the channel is selected for a sampling * and to mark the channel as configured (ready to be selected). */ - m_data.positive_inputs[channel_id] = saadc_psels[channel_cfg->input_positive]; -#else m_data.positive_inputs[channel_id] = channel_cfg->input_positive; -#endif nrf_saadc_channel_init(NRF_SAADC, channel_id, &config); + /* Keep the channel disabled in hardware (set positive input to + * NRF_SAADC_INPUT_DISABLED) until it is selected to be included + * in a sampling sequence. + */ nrf_saadc_channel_input_set(NRF_SAADC, channel_id, NRF_SAADC_INPUT_DISABLED, @@ -494,7 +496,7 @@ static int start_read(const struct device *dev, /* Signal an error if a selected channel has not been * configured yet. */ - if (m_data.positive_inputs[channel_id] == 0U) { + if (m_data.positive_inputs[channel_id] == SAADC_INPUT_INVALID) { LOG_ERR("Channel %u not configured", channel_id); return -EINVAL; @@ -531,7 +533,12 @@ static int start_read(const struct device *dev, nrf_saadc_channel_pos_input_set( NRF_SAADC, channel_id, - m_data.positive_inputs[channel_id]); +#if NRF_SAADC_HAS_AIN_AS_PIN + saadc_psels[m_data.positive_inputs[channel_id]] +#else + m_data.positive_inputs[channel_id] +#endif + ); ++active_channels; } else { nrf_saadc_burst_set( @@ -642,6 +649,9 @@ static void saadc_irq_handler(const struct device *dev) static int init_saadc(const struct device *dev) { + for (uint8_t ch = 0; ch < ARRAY_SIZE(m_data.positive_inputs); ch++) { + m_data.positive_inputs[ch] = SAADC_INPUT_INVALID; + } nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END); nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE); nrf_saadc_int_enable(NRF_SAADC,