diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index 721de86c98f..ac0babf123f 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -33,6 +33,11 @@ config ADC_CONFIGURABLE_INPUTS config ADC_CONFIGURABLE_EXCITATION_CURRENT_SOURCE_PIN bool +# By selecting or not this option particular ADC drivers indicate if they +# allow a configurable voltage bias pin. +config ADC_CONFIGURABLE_VBIAS_PIN + bool + config ADC_ASYNC bool "Asynchronous call support" select POLL diff --git a/drivers/adc/Kconfig.ads114s0x b/drivers/adc/Kconfig.ads114s0x index 4507ad30217..45191bb92ea 100644 --- a/drivers/adc/Kconfig.ads114s0x +++ b/drivers/adc/Kconfig.ads114s0x @@ -9,6 +9,7 @@ menuconfig ADC_ADS114S0X select SPI select ADC_CONFIGURABLE_INPUTS select ADC_CONFIGURABLE_EXCITATION_CURRENT_SOURCE_PIN + select ADC_CONFIGURABLE_VBIAS_PIN help Enable the driver implementation for the ADS114S0X family diff --git a/drivers/adc/adc_ads114s0x.c b/drivers/adc/adc_ads114s0x.c index 16a7bfabfad..9864fd689f4 100644 --- a/drivers/adc/adc_ads114s0x.c +++ b/drivers/adc/adc_ads114s0x.c @@ -32,6 +32,8 @@ LOG_MODULE_REGISTER(ads114s0x, CONFIG_ADC_LOG_LEVEL); #define ADS114S0X_REF_INTERNAL 2500 #define ADS114S0X_GPIO_MAX 3 #define ADS114S0X_POWER_ON_RESET_TIME_IN_US 2200 +#define ADS114S0X_VBIAS_PIN_MAX 7 +#define ADS114S0X_VBIAS_PIN_MIN 0 /* Not mentioned in the datasheet, but instead determined experimentally. */ #define ADS114S0X_RESET_DELAY_TIME_SAFETY_MARGIN_IN_US 1000 @@ -317,6 +319,14 @@ enum ads114s0x_register { #define ADS114S0X_REGISTER_IDACMUX_I1MUX_SET(target, value) \ ADS114S0X_REGISTER_SET_VALUE(target, value, ADS114S0X_REGISTER_IDACMUX_I1MUX_POS, \ ADS114S0X_REGISTER_IDACMUX_I1MUX_LENGTH) +#define ADS114S0X_REGISTER_VBIAS_VB_LEVEL_LENGTH 1 +#define ADS114S0X_REGISTER_VBIAS_VB_LEVEL_POS 7 +#define ADS114S0X_REGISTER_VBIAS_VB_LEVEL_GET(value) \ + ADS114S0X_REGISTER_GET_VALUE(value, ADS114S0X_REGISTER_VBIAS_VB_LEVEL_POS, \ + ADS114S0X_REGISTER_VBIAS_VB_LEVEL_LENGTH) +#define ADS114S0X_REGISTER_VBIAS_VB_LEVEL_SET(target, value) \ + ADS114S0X_REGISTER_SET_VALUE(target, value, ADS114S0X_REGISTER_VBIAS_VB_LEVEL_POS, \ + ADS114S0X_REGISTER_VBIAS_VB_LEVEL_LENGTH) #define ADS114S0X_REGISTER_GPIODAT_DIR_LENGTH 4 #define ADS114S0X_REGISTER_GPIODAT_DIR_POS 4 #define ADS114S0X_REGISTER_GPIODAT_DIR_GET(value) \ @@ -410,6 +420,7 @@ struct ads114s0x_config { const struct gpio_dt_spec gpio_data_ready; const struct gpio_dt_spec gpio_start_sync; int idac_current; + uint8_t vbias_level; }; struct ads114s0x_data { @@ -597,9 +608,10 @@ static int ads114s0x_channel_setup(const struct device *dev, uint8_t idac_magnitude = 0; uint8_t idac_mux = 0; uint8_t pin_selections[4]; + uint8_t vbias = 0; size_t pin_selections_size; int result; - enum ads114s0x_register register_addresses[6]; + enum ads114s0x_register register_addresses[7]; uint8_t values[ARRAY_SIZE(register_addresses)]; uint16_t acquisition_time_value = ADC_ACQ_TIME_VALUE(channel_cfg->acquisition_time); uint16_t acquisition_time_unit = ADC_ACQ_TIME_UNIT(channel_cfg->acquisition_time); @@ -820,20 +832,33 @@ static int ads114s0x_channel_setup(const struct device *dev, } } + ADS114S0X_REGISTER_VBIAS_VB_LEVEL_SET(vbias, config->vbias_level); + + if ((channel_cfg->vbias_pins & + ~GENMASK(ADS114S0X_VBIAS_PIN_MAX, ADS114S0X_VBIAS_PIN_MIN)) != 0) { + LOG_ERR("%s: invalid VBIAS pin selection 0x%08X", dev->name, + channel_cfg->vbias_pins); + return -EINVAL; + } + + vbias |= channel_cfg->vbias_pins; + register_addresses[0] = ADS114S0X_REGISTER_INPMUX; register_addresses[1] = ADS114S0X_REGISTER_PGA; register_addresses[2] = ADS114S0X_REGISTER_DATARATE; register_addresses[3] = ADS114S0X_REGISTER_REF; register_addresses[4] = ADS114S0X_REGISTER_IDACMAG; register_addresses[5] = ADS114S0X_REGISTER_IDACMUX; - BUILD_ASSERT(ARRAY_SIZE(register_addresses) == 6); + register_addresses[6] = ADS114S0X_REGISTER_VBIAS; + BUILD_ASSERT(ARRAY_SIZE(register_addresses) == 7); values[0] = input_mux; values[1] = gain; values[2] = data_rate; values[3] = reference_control; values[4] = idac_magnitude; values[5] = idac_mux; - BUILD_ASSERT(ARRAY_SIZE(values) == 6); + values[6] = vbias; + BUILD_ASSERT(ARRAY_SIZE(values) == 7); result = ads114s0x_write_multiple_registers(dev, register_addresses, values, ARRAY_SIZE(values)); @@ -1474,6 +1499,7 @@ BUILD_ASSERT(CONFIG_ADC_INIT_PRIORITY > CONFIG_SPI_INIT_PRIORITY, .gpio_data_ready = GPIO_DT_SPEC_INST_GET(n, drdy_gpios), \ .gpio_start_sync = GPIO_DT_SPEC_INST_GET_OR(n, start_sync_gpios, {0}), \ .idac_current = DT_INST_PROP(n, idac_current), \ + .vbias_level = DT_INST_PROP(n, vbias_level), \ }; \ static struct ads114s0x_data data_##n; \ DEVICE_DT_INST_DEFINE(n, ads114s0x_init, NULL, &data_##n, &config_##n, POST_KERNEL, \ diff --git a/dts/bindings/adc/adc-controller.yaml b/dts/bindings/adc/adc-controller.yaml index 4c9c3e3fea6..c52c913d522 100644 --- a/dts/bindings/adc/adc-controller.yaml +++ b/dts/bindings/adc/adc-controller.yaml @@ -160,3 +160,10 @@ child-binding: interpretation depends on the driver. This is used only for drivers which select the ADC_CONFIGURABLE_EXCITATION_CURRENT_SOURCE_PIN Kconfig option. + + zephyr,vbias-pins: + type: int + description: | + Output pin selection for the bias voltage. The actual interpretation + depends on the driver. This is used only for drivers which select + the ADC_CONFIGURABLE_VBIAS_PIN Kconfig option. diff --git a/dts/bindings/adc/ti,ads114s08.yaml b/dts/bindings/adc/ti,ads114s08.yaml index a172439e051..cf91c11652b 100644 --- a/dts/bindings/adc/ti,ads114s08.yaml +++ b/dts/bindings/adc/ti,ads114s08.yaml @@ -45,5 +45,14 @@ properties: description: | IDAC current in microampere, the default value turns the current source off + vbias-level: + type: int + enum: + - 0 + - 1 + default: 0 + description: | + bias voltage level: 0 - (AVDD+AVSS)/2, 1 - (AVDD+AVSS)/12 + io-channel-cells: - input diff --git a/include/zephyr/drivers/adc.h b/include/zephyr/drivers/adc.h index be88e78b067..01ec48672f3 100644 --- a/include/zephyr/drivers/adc.h +++ b/include/zephyr/drivers/adc.h @@ -156,6 +156,18 @@ struct adc_channel_cfg { */ uint8_t current_source_pin[2]; #endif /* CONFIG_ADC_CONFIGURABLE_EXCITATION_CURRENT_SOURCE_PIN */ + +#ifdef CONFIG_ADC_CONFIGURABLE_VBIAS_PIN + /** + * Output pins for the bias voltage. + * This is only available if the driver enables this feature + * via the hidden configuration option ADC_CONFIGURABLE_VBIAS_PIN. + * The field is interpreted as a bitmask, where each bit represents + * one of the input pins. The actual mapping to the physical pins + * depends on the driver itself. + */ + uint32_t vbias_pins; +#endif /* CONFIG_ADC_CONFIGURABLE_VBIAS_PIN */ }; /** @@ -236,6 +248,8 @@ IF_ENABLED(DT_PROP(node_id, zephyr_differential), \ IF_ENABLED(CONFIG_ADC_CONFIGURABLE_EXCITATION_CURRENT_SOURCE_PIN, \ (.current_source_pin_set = DT_NODE_HAS_PROP(node_id, zephyr_current_source_pin), \ .current_source_pin = DT_PROP_OR(node_id, zephyr_current_source_pin, {0}),)) \ +IF_ENABLED(CONFIG_ADC_CONFIGURABLE_VBIAS_PIN, \ + (.vbias_pins = DT_PROP_OR(node_id, zephyr_vbias_pins, 0),)) \ } /**