diff --git a/drivers/adc/adc_nrfx_saadc.c b/drivers/adc/adc_nrfx_saadc.c index 7d442b482e6..0e39e3bafae 100644 --- a/drivers/adc/adc_nrfx_saadc.c +++ b/drivers/adc/adc_nrfx_saadc.c @@ -187,7 +187,6 @@ static int input_assign(nrf_saadc_input_t *pin_p, if (channel_cfg->differential) { if (channel_cfg->input_negative > ARRAY_SIZE(saadc_psels) || - channel_cfg->input_negative < NRF_SAADC_AIN0 || (IS_ENABLED(CONFIG_NRF_PLATFORM_HALTIUM) && (channel_cfg->input_positive > NRF_SAADC_AIN7) != (channel_cfg->input_negative > NRF_SAADC_AIN7))) { @@ -195,14 +194,17 @@ static int input_assign(nrf_saadc_input_t *pin_p, channel_cfg->input_negative); return -EINVAL; } - *pin_n = saadc_psels[channel_cfg->input_negative]; + *pin_n = channel_cfg->input_negative == NRF_SAADC_GND ? + NRF_SAADC_INPUT_DISABLED : + saadc_psels[channel_cfg->input_negative]; } else { *pin_n = NRF_SAADC_INPUT_DISABLED; } #else *pin_p = channel_cfg->input_positive; - *pin_n = channel_cfg->differential ? channel_cfg->input_negative - : NRF_SAADC_INPUT_DISABLED; + *pin_n = (channel_cfg->differential && (channel_cfg->input_negative != NRF_SAADC_GND)) + ? channel_cfg->input_negative + : NRF_SAADC_INPUT_DISABLED; #endif LOG_DBG("ADC positive input: %d", *pin_p); LOG_DBG("ADC negative input: %d", *pin_n); @@ -352,8 +354,14 @@ static int adc_nrfx_channel_setup(const struct device *dev, * after ADC sequence ends. */ if (channel_cfg->differential) { - ch_cfg->mode = NRF_SAADC_MODE_DIFFERENTIAL; - m_data.single_ended_channels &= ~BIT(channel_cfg->channel_id); + if (channel_cfg->input_negative == NRF_SAADC_GND) { + ch_cfg->mode = NRF_SAADC_MODE_SINGLE_ENDED; + /* Do not mark as single-ended to not correct negative values. */ + m_data.single_ended_channels &= ~BIT(channel_cfg->channel_id); + } else { + ch_cfg->mode = NRF_SAADC_MODE_DIFFERENTIAL; + m_data.single_ended_channels &= ~BIT(channel_cfg->channel_id); + } } else { ch_cfg->mode = NRF_SAADC_MODE_SINGLE_ENDED; m_data.single_ended_channels |= BIT(channel_cfg->channel_id); diff --git a/include/zephyr/dt-bindings/adc/nrf-saadc.h b/include/zephyr/dt-bindings/adc/nrf-saadc.h index 4a3deb95cff..e5a86150cd4 100644 --- a/include/zephyr/dt-bindings/adc/nrf-saadc.h +++ b/include/zephyr/dt-bindings/adc/nrf-saadc.h @@ -7,6 +7,30 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ADC_NRF_SAADC_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_ADC_NRF_SAADC_H_ +/** + * @brief Short ADC negative input to ground + * + * @details The nRF SAADC hardware only supports differential readings. + * The nRF SAADC SE (single ended) mode is differential with the negative + * input shorted to GND (ground). To use the nRF SAADC SE mode, set the + * negative input to NRF_SAADC_GND: + * + * @code{.dts} + * zephyr,input-positive = ; + * zephyr,input-negative = ; + * @endcode + * + * The nRF SAADC driver also supports using the nRF SAADC SE mode in + * emulated "single-ended" mode, as defined by zephyr. In this mode, + * negative readings will be clamped to 0 by software to emulate the + * behavior of an ADC in "single-ended" mode, as defined by zephyr. To + * do this, only define the positive input: + * + * @code{.dts} + * zephyr,input-positive = ; + * @endcode + */ +#define NRF_SAADC_GND 0 #define NRF_SAADC_AIN0 1 #define NRF_SAADC_AIN1 2 #define NRF_SAADC_AIN2 3