From ecac441171ea33668328c5a9751e2432932fea5d Mon Sep 17 00:00:00 2001 From: Benedikt Schmidt Date: Thu, 4 May 2023 16:41:14 +0200 Subject: [PATCH] drivers: gpio: implement GPIOs in ADS114S08 Implement GPIO exander within the ADC ADS114S08. Signed-off-by: Benedikt Schmidt --- drivers/adc/Kconfig.ads114s0x | 10 + drivers/adc/adc_ads114s0x.c | 312 ++++++++++++++++++++++++- drivers/gpio/CMakeLists.txt | 1 + drivers/gpio/Kconfig | 2 + drivers/gpio/Kconfig.ads114s0x | 25 ++ drivers/gpio/gpio_ads114s0x.c | 157 +++++++++++++ include/zephyr/drivers/adc/ads114s0x.h | 35 +++ 7 files changed, 541 insertions(+), 1 deletion(-) create mode 100644 drivers/gpio/Kconfig.ads114s0x create mode 100644 drivers/gpio/gpio_ads114s0x.c create mode 100644 include/zephyr/drivers/adc/ads114s0x.h diff --git a/drivers/adc/Kconfig.ads114s0x b/drivers/adc/Kconfig.ads114s0x index 69ec9e84378..39ed5c56e61 100644 --- a/drivers/adc/Kconfig.ads114s0x +++ b/drivers/adc/Kconfig.ads114s0x @@ -23,3 +23,13 @@ config ADC_ADS114S0X_ACQUISITION_THREAD_STACK_SIZE help Size of the stack used for the internal data acquisition thread. + +config ADC_ADS114S0X_GPIO + bool "GPIO support" + default n + depends on GPIO && ADC_ADS114S0X + help + Enable GPIO child device support in the ADS114S0x ADC driver. + + The GPIO functionality is handled by the ADS114S0x GPIO + driver. diff --git a/drivers/adc/adc_ads114s0x.c b/drivers/adc/adc_ads114s0x.c index 80c5496502b..709d4f3896b 100644 --- a/drivers/adc/adc_ads114s0x.c +++ b/drivers/adc/adc_ads114s0x.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,7 @@ LOG_MODULE_REGISTER(ads114s0x, CONFIG_ADC_LOG_LEVEL); #define ADS114S0X_INPUT_SELECTION_AINCOM 12 #define ADS114S0X_RESOLUTION 16 #define ADS114S0X_REF_INTERNAL 2500 +#define ADS114S0X_GPIO_MAX 3 #define ADS114S0X_POWER_ON_RESET_TIME_IN_US 2200 /* Not mentioned in the datasheet, but instead determined experimentally. */ @@ -272,6 +274,70 @@ enum ads114s0x_register { #define ADS114S0X_REGISTER_REF_REFCON_SET(target, value) \ ADS114S0X_REGISTER_SET_VALUE(target, value, ADS114S0X_REGISTER_REF_REFCON_POS, \ ADS114S0X_REGISTER_REF_REFCON_LENGTH) +#define ADS114S0X_REGISTER_IDACMAG_FL_RAIL_EN_LENGTH 1 +#define ADS114S0X_REGISTER_IDACMAG_FL_RAIL_EN_POS 7 +#define ADS114S0X_REGISTER_IDACMAG_FL_RAIL_EN_GET(value) \ + ADS114S0X_REGISTER_GET_VALUE(value, ADS114S0X_REGISTER_IDACMAG_FL_RAIL_EN_POS, \ + ADS114S0X_REGISTER_IDACMAG_FL_RAIL_EN_LENGTH) +#define ADS114S0X_REGISTER_IDACMAG_FL_RAIL_EN_SET(target, value) \ + ADS114S0X_REGISTER_SET_VALUE(target, value, ADS114S0X_REGISTER_IDACMAG_FL_RAIL_EN_POS, \ + ADS114S0X_REGISTER_IDACMAG_FL_RAIL_EN_LENGTH) +#define ADS114S0X_REGISTER_IDACMAG_PSW_LENGTH 1 +#define ADS114S0X_REGISTER_IDACMAG_PSW_POS 6 +#define ADS114S0X_REGISTER_IDACMAG_PSW_GET(value) \ + ADS114S0X_REGISTER_GET_VALUE(value, ADS114S0X_REGISTER_IDACMAG_PSW_POS, \ + ADS114S0X_REGISTER_IDACMAG_PSW_LENGTH) +#define ADS114S0X_REGISTER_IDACMAG_PSW_SET(target, value) \ + ADS114S0X_REGISTER_SET_VALUE(target, value, ADS114S0X_REGISTER_IDACMAG_PSW_POS, \ + ADS114S0X_REGISTER_IDACMAG_PSW_LENGTH) +#define ADS114S0X_REGISTER_IDACMAG_IMAG_LENGTH 4 +#define ADS114S0X_REGISTER_IDACMAG_IMAG_POS 0 +#define ADS114S0X_REGISTER_IDACMAG_IMAG_GET(value) \ + ADS114S0X_REGISTER_GET_VALUE(value, ADS114S0X_REGISTER_IDACMAG_IMAG_POS, \ + ADS114S0X_REGISTER_IDACMAG_IMAG_LENGTH) +#define ADS114S0X_REGISTER_IDACMAG_IMAG_SET(target, value) \ + ADS114S0X_REGISTER_SET_VALUE(target, value, ADS114S0X_REGISTER_IDACMAG_IMAG_POS, \ + ADS114S0X_REGISTER_IDACMAG_IMAG_LENGTH) +#define ADS114S0X_REGISTER_IDACMUX_I2MUX_LENGTH 4 +#define ADS114S0X_REGISTER_IDACMUX_I2MUX_POS 4 +#define ADS114S0X_REGISTER_IDACMUX_I2MUX_GET(value) \ + ADS114S0X_REGISTER_GET_VALUE(value, ADS114S0X_REGISTER_IDACMUX_I2MUX_POS, \ + ADS114S0X_REGISTER_IDACMUX_I2MUX_LENGTH) +#define ADS114S0X_REGISTER_IDACMUX_I2MUX_SET(target, value) \ + ADS114S0X_REGISTER_SET_VALUE(target, value, ADS114S0X_REGISTER_IDACMUX_I2MUX_POS, \ + ADS114S0X_REGISTER_IDACMUX_I2MUX_LENGTH) +#define ADS114S0X_REGISTER_IDACMUX_I1MUX_LENGTH 4 +#define ADS114S0X_REGISTER_IDACMUX_I1MUX_POS 0 +#define ADS114S0X_REGISTER_IDACMUX_I1MUX_GET(value) \ + ADS114S0X_REGISTER_GET_VALUE(value, ADS114S0X_REGISTER_IDACMUX_I1MUX_POS, \ + ADS114S0X_REGISTER_IDACMUX_I1MUX_LENGTH) +#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_GPIODAT_DIR_LENGTH 4 +#define ADS114S0X_REGISTER_GPIODAT_DIR_POS 4 +#define ADS114S0X_REGISTER_GPIODAT_DIR_GET(value) \ + ADS114S0X_REGISTER_GET_VALUE(value, ADS114S0X_REGISTER_GPIODAT_DIR_POS, \ + ADS114S0X_REGISTER_GPIODAT_DIR_LENGTH) +#define ADS114S0X_REGISTER_GPIODAT_DIR_SET(target, value) \ + ADS114S0X_REGISTER_SET_VALUE(target, value, ADS114S0X_REGISTER_GPIODAT_DIR_POS, \ + ADS114S0X_REGISTER_GPIODAT_DIR_LENGTH) +#define ADS114S0X_REGISTER_GPIODAT_DAT_LENGTH 4 +#define ADS114S0X_REGISTER_GPIODAT_DAT_POS 0 +#define ADS114S0X_REGISTER_GPIODAT_DAT_GET(value) \ + ADS114S0X_REGISTER_GET_VALUE(value, ADS114S0X_REGISTER_GPIODAT_DAT_POS, \ + ADS114S0X_REGISTER_GPIODAT_DAT_LENGTH) +#define ADS114S0X_REGISTER_GPIODAT_DAT_SET(target, value) \ + ADS114S0X_REGISTER_SET_VALUE(target, value, ADS114S0X_REGISTER_GPIODAT_DAT_POS, \ + ADS114S0X_REGISTER_GPIODAT_DAT_LENGTH) +#define ADS114S0X_REGISTER_GPIOCON_CON_LENGTH 4 +#define ADS114S0X_REGISTER_GPIOCON_CON_POS 0 +#define ADS114S0X_REGISTER_GPIOCON_CON_GET(value) \ + ADS114S0X_REGISTER_GET_VALUE(value, ADS114S0X_REGISTER_GPIOCON_CON_POS, \ + ADS114S0X_REGISTER_GPIOCON_CON_LENGTH) +#define ADS114S0X_REGISTER_GPIOCON_CON_SET(target, value) \ + ADS114S0X_REGISTER_SET_VALUE(target, value, ADS114S0X_REGISTER_GPIOCON_CON_POS, \ + ADS114S0X_REGISTER_GPIOCON_CON_LENGTH) /* * - AIN0 as positive input @@ -330,12 +396,18 @@ struct ads114s0x_data { struct adc_context ctx; #if CONFIG_ADC_ASYNC struct k_thread thread; -#endif +#endif /* CONFIG_ADC_ASYNC */ struct gpio_callback callback_data_ready; struct k_sem data_ready_signal; struct k_sem acquire_signal; int16_t *buffer; int16_t *buffer_ptr; +#if CONFIG_ADC_ADS114S0X_GPIO + struct k_mutex gpio_lock; + uint8_t gpio_enabled; /* one bit per GPIO, 1 = enabled */ + uint8_t gpio_direction; /* one bit per GPIO, 1 = input */ + uint8_t gpio_value; /* one bit per GPIO, 1 = high */ +#endif /* CONFIG_ADC_ADS114S0X_GPIO */ }; static void ads114s0x_data_ready_handler(const struct device *dev, struct gpio_callback *gpio_cb, @@ -870,6 +942,227 @@ static void ads114s0x_acquisition_thread(struct device *dev) } #endif +#ifdef CONFIG_ADC_ADS114S0X_GPIO +static int ads114s0x_gpio_write_config(const struct device *dev) +{ + struct ads114s0x_data *data = dev->data; + const struct ads114s0x_config *config = dev->config; + uint8_t register_addresses[2]; + uint8_t register_values[ARRAY_SIZE(register_addresses)]; + uint8_t gpio_dat = 0; + uint8_t gpio_con = 0; + + ADS114S0X_REGISTER_GPIOCON_CON_SET(gpio_con, data->gpio_enabled); + ADS114S0X_REGISTER_GPIODAT_DAT_SET(gpio_dat, data->gpio_value); + ADS114S0X_REGISTER_GPIODAT_DIR_SET(gpio_dat, data->gpio_direction); + + register_values[0] = gpio_dat; + register_values[1] = gpio_con; + register_addresses[0] = ADS114S0X_REGISTER_GPIODAT; + register_addresses[1] = ADS114S0X_REGISTER_GPIOCON; + return ads114s0x_write_multiple_registers(&config->bus, register_addresses, register_values, + ARRAY_SIZE(register_values)); +} + +static int ads114s0x_gpio_write_value(const struct device *dev) +{ + struct ads114s0x_data *data = dev->data; + const struct ads114s0x_config *config = dev->config; + uint8_t gpio_dat = 0; + + ADS114S0X_REGISTER_GPIODAT_DAT_SET(gpio_dat, data->gpio_value); + ADS114S0X_REGISTER_GPIODAT_DIR_SET(gpio_dat, data->gpio_direction); + + return ads114s0x_write_register(&config->bus, ADS114S0X_REGISTER_GPIODAT, gpio_dat); +} + +int ads114s0x_gpio_set_output(const struct device *dev, uint8_t pin, bool initial_value) +{ + struct ads114s0x_data *data = dev->data; + int result = 0; + + if (pin > ADS114S0X_GPIO_MAX) { + LOG_ERR("invalid pin %i", pin); + return -EINVAL; + } + + k_mutex_lock(&data->gpio_lock, K_FOREVER); + + data->gpio_enabled |= BIT(pin); + data->gpio_direction &= ~BIT(pin); + + if (initial_value) { + data->gpio_value |= BIT(pin); + } else { + data->gpio_value &= ~BIT(pin); + } + + result = ads114s0x_gpio_write_config(dev); + + k_mutex_unlock(&data->gpio_lock); + + return result; +} + +int ads114s0x_gpio_set_input(const struct device *dev, uint8_t pin) +{ + struct ads114s0x_data *data = dev->data; + int result = 0; + + if (pin > ADS114S0X_GPIO_MAX) { + LOG_ERR("invalid pin %i", pin); + return -EINVAL; + } + + k_mutex_lock(&data->gpio_lock, K_FOREVER); + + data->gpio_enabled |= BIT(pin); + data->gpio_direction |= BIT(pin); + data->gpio_value &= ~BIT(pin); + + result = ads114s0x_gpio_write_config(dev); + + k_mutex_unlock(&data->gpio_lock); + + return result; +} + +int ads114s0x_gpio_deconfigure(const struct device *dev, uint8_t pin) +{ + struct ads114s0x_data *data = dev->data; + int result = 0; + + if (pin > ADS114S0X_GPIO_MAX) { + LOG_ERR("invalid pin %i", pin); + return -EINVAL; + } + + k_mutex_lock(&data->gpio_lock, K_FOREVER); + + data->gpio_enabled &= ~BIT(pin); + data->gpio_direction |= BIT(pin); + data->gpio_value &= ~BIT(pin); + + result = ads114s0x_gpio_write_config(dev); + + k_mutex_unlock(&data->gpio_lock); + + return result; +} + +int ads114s0x_gpio_set_pin_value(const struct device *dev, uint8_t pin, bool value) +{ + struct ads114s0x_data *data = dev->data; + int result = 0; + + if (pin > ADS114S0X_GPIO_MAX) { + LOG_ERR("invalid pin %i", pin); + return -EINVAL; + } + + k_mutex_lock(&data->gpio_lock, K_FOREVER); + + if ((BIT(pin) & data->gpio_enabled) == 0) { + LOG_ERR("gpio pin %i not configured", pin); + result = -EINVAL; + } else if ((BIT(pin) & data->gpio_direction) != 0) { + LOG_ERR("gpio pin %i not configured as output", pin); + result = -EINVAL; + } else { + data->gpio_value |= BIT(pin); + + result = ads114s0x_gpio_write_value(dev); + } + + k_mutex_unlock(&data->gpio_lock); + + return result; +} + +int ads114s0x_gpio_get_pin_value(const struct device *dev, uint8_t pin, bool *value) +{ + struct ads114s0x_data *data = dev->data; + const struct ads114s0x_config *config = dev->config; + int result = 0; + uint8_t gpio_dat; + + if (pin > ADS114S0X_GPIO_MAX) { + LOG_ERR("invalid pin %i", pin); + return -EINVAL; + } + + k_mutex_lock(&data->gpio_lock, K_FOREVER); + + if ((BIT(pin) & data->gpio_enabled) == 0) { + LOG_ERR("gpio pin %i not configured", pin); + result = -EINVAL; + } else if ((BIT(pin) & data->gpio_direction) == 0) { + LOG_ERR("gpio pin %i not configured as input", pin); + result = -EINVAL; + } else { + result = ads114s0x_read_register(&config->bus, ADS114S0X_REGISTER_GPIODAT, + &gpio_dat); + data->gpio_value = ADS114S0X_REGISTER_GPIODAT_DAT_GET(gpio_dat); + *value = (BIT(pin) & data->gpio_value) != 0; + } + + k_mutex_unlock(&data->gpio_lock); + + return result; +} + +int ads114s0x_gpio_port_get_raw(const struct device *dev, gpio_port_value_t *value) +{ + struct ads114s0x_data *data = dev->data; + const struct ads114s0x_config *config = dev->config; + int result = 0; + uint8_t gpio_dat; + + k_mutex_lock(&data->gpio_lock, K_FOREVER); + + result = ads114s0x_read_register(&config->bus, ADS114S0X_REGISTER_GPIODAT, &gpio_dat); + data->gpio_value = ADS114S0X_REGISTER_GPIODAT_DAT_GET(gpio_dat); + *value = data->gpio_value; + + k_mutex_unlock(&data->gpio_lock); + + return result; +} + +int ads114s0x_gpio_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + struct ads114s0x_data *data = dev->data; + int result = 0; + + k_mutex_lock(&data->gpio_lock, K_FOREVER); + + data->gpio_value = ((data->gpio_value & ~mask) | (mask & value)) & data->gpio_enabled & + ~data->gpio_direction; + result = ads114s0x_gpio_write_value(dev); + + k_mutex_unlock(&data->gpio_lock); + + return result; +} + +int ads114s0x_gpio_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +{ + struct ads114s0x_data *data = dev->data; + int result = 0; + + k_mutex_lock(&data->gpio_lock, K_FOREVER); + + data->gpio_value = (data->gpio_value ^ pins) & data->gpio_enabled & ~data->gpio_direction; + result = ads114s0x_gpio_write_value(dev); + + k_mutex_unlock(&data->gpio_lock); + + return result; +} + +#endif /* CONFIG_ADC_ADS114S0X_GPIO */ + static int ads114s0x_init(const struct device *dev) { uint8_t status = 0; @@ -884,6 +1177,10 @@ static int ads114s0x_init(const struct device *dev) k_sem_init(&data->data_ready_signal, 0, 1); k_sem_init(&data->acquire_signal, 0, 1); +#ifdef CONFIG_ADC_ADS114S0X_GPIO + k_mutex_init(&data->gpio_lock); +#endif /* CONFIG_ADC_ADS114S0X_GPIO */ + if (!spi_is_ready_dt(&config->bus)) { LOG_ERR("SPI device is not ready"); return -ENODEV; @@ -986,6 +1283,19 @@ static int ads114s0x_init(const struct device *dev) return -EIO; } +#ifdef CONFIG_ADC_ADS114S0X_GPIO + data->gpio_enabled = 0x00; + data->gpio_direction = 0x0F; + data->gpio_value = 0x00; + + result = ads114s0x_gpio_write_config(dev); + + if (result != 0) { + LOG_ERR("unable to configure defaults for GPIOs"); + return result; + } +#endif + adc_context_unlock_unconditionally(&data->ctx); return result; diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 810236106d3..1237fe7bd74 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -37,6 +37,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_STELLARIS gpio_stellaris.c) zephyr_library_sources_ifdef(CONFIG_GPIO_RPI_PICO gpio_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_GPIO_RV32M1 gpio_rv32m1.c) zephyr_library_sources_ifdef(CONFIG_GPIO_LMP90XXX gpio_lmp90xxx.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_ADS114S0X gpio_ads114s0x.c) zephyr_library_sources_ifdef(CONFIG_GPIO_LITEX gpio_litex.c) zephyr_library_sources_ifdef(CONFIG_GPIO_LPC11U6X gpio_lpc11u6x.c) zephyr_library_sources_ifdef(CONFIG_GPIO_XLNX_AXI gpio_xlnx_axi.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 53688855d07..b4a2f0bef67 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -127,6 +127,8 @@ source "drivers/gpio/Kconfig.rv32m1" source "drivers/gpio/Kconfig.lmp90xxx" +source "drivers/gpio/Kconfig.ads114s0x" + source "drivers/gpio/Kconfig.litex" source "drivers/gpio/Kconfig.lpc11u6x" diff --git a/drivers/gpio/Kconfig.ads114s0x b/drivers/gpio/Kconfig.ads114s0x new file mode 100644 index 00000000000..1dd642c6def --- /dev/null +++ b/drivers/gpio/Kconfig.ads114s0x @@ -0,0 +1,25 @@ +# ADS114S0x GPIO configuration options + +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +menuconfig GPIO_ADS114S0X + bool "ADS114S0x GPIO driver" + default y + depends on DT_HAS_TI_ADS114S0X_GPIO_ENABLED + depends on ADC_ADS114S0X_GPIO + help + Enable GPIO driver for ADS114S0x. + + The ADS114S0x is a multi-channel analog frontend (AFE). + + The GPIO port of the ADS114S0x (GPIO0 to GPIO3) is exposed as a + GPIO controller driver with read/write support. + +config GPIO_ADS114S0X_INIT_PRIORITY + int "Driver init priority" + default 99 + depends on GPIO_ADS114S0X + help + Device driver initialization priority. This driver must be + initialized after the ADS114S0x ADC driver. diff --git a/drivers/gpio/gpio_ads114s0x.c b/drivers/gpio/gpio_ads114s0x.c new file mode 100644 index 00000000000..79383d38154 --- /dev/null +++ b/drivers/gpio/gpio_ads114s0x.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief GPIO driver for the ADS114S0x AFE. + */ + +#define DT_DRV_COMPAT ti_ads114s0x_gpio + +#include +#include + +#define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL +#include +LOG_MODULE_REGISTER(gpio_ads114s0x); + +#include + +#include + +struct gpio_ads114s0x_config { + /* gpio_driver_config needs to be first */ + struct gpio_driver_config common; + const struct device *parent; +}; + +struct gpio_ads114s0x_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; +}; + +static int gpio_ads114s0x_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct gpio_ads114s0x_config *config = dev->config; + int err = 0; + + if ((flags & (GPIO_INPUT | GPIO_OUTPUT)) == GPIO_DISCONNECTED) { + return ads114s0x_gpio_deconfigure(config->parent, pin); + } + + if ((flags & GPIO_SINGLE_ENDED) != 0) { + return -ENOTSUP; + } + + if ((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0) { + return -ENOTSUP; + } + + if (flags & GPIO_INT_ENABLE) { + /* ads114s0x GPIOs do not support interrupts */ + return -ENOTSUP; + } + + switch (flags & GPIO_DIR_MASK) { + case GPIO_INPUT: + err = ads114s0x_gpio_set_input(config->parent, pin); + break; + case GPIO_OUTPUT: + err = ads114s0x_gpio_set_output(config->parent, pin, + (flags & GPIO_OUTPUT_INIT_HIGH) != 0); + break; + default: + return -ENOTSUP; + } + + return err; +} + +static int gpio_ads114s0x_port_get_raw(const struct device *dev, gpio_port_value_t *value) +{ + const struct gpio_ads114s0x_config *config = dev->config; + + return ads114s0x_gpio_port_get_raw(config->parent, value); +} + +static int gpio_ads114s0x_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + const struct gpio_ads114s0x_config *config = dev->config; + + return ads114s0x_gpio_port_set_masked_raw(config->parent, mask, value); +} + +static int gpio_ads114s0x_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct gpio_ads114s0x_config *config = dev->config; + + return ads114s0x_gpio_port_set_masked_raw(config->parent, pins, pins); +} + +static int gpio_ads114s0x_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct gpio_ads114s0x_config *config = dev->config; + + return ads114s0x_gpio_port_set_masked_raw(config->parent, pins, 0); +} + +static int gpio_ads114s0x_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +{ + const struct gpio_ads114s0x_config *config = dev->config; + + return ads114s0x_gpio_port_toggle_bits(config->parent, pins); +} + +static int gpio_ads114s0x_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + ARG_UNUSED(dev); + ARG_UNUSED(pin); + ARG_UNUSED(mode); + ARG_UNUSED(trig); + + return -ENOTSUP; +} + +static int gpio_ads114s0x_init(const struct device *dev) +{ + const struct gpio_ads114s0x_config *config = dev->config; + + if (!device_is_ready(config->parent)) { + LOG_ERR("parent ads114s0x device '%s' not ready", config->parent->name); + return -EINVAL; + } + + return 0; +} + +static const struct gpio_driver_api gpio_ads114s0x_api = { + .pin_configure = gpio_ads114s0x_config, + .port_set_masked_raw = gpio_ads114s0x_port_set_masked_raw, + .port_set_bits_raw = gpio_ads114s0x_port_set_bits_raw, + .port_clear_bits_raw = gpio_ads114s0x_port_clear_bits_raw, + .port_toggle_bits = gpio_ads114s0x_port_toggle_bits, + .pin_interrupt_configure = gpio_ads114s0x_pin_interrupt_configure, + .port_get_raw = gpio_ads114s0x_port_get_raw, +}; + +BUILD_ASSERT(CONFIG_GPIO_ADS114S0X_INIT_PRIORITY > CONFIG_ADC_INIT_PRIORITY, + "ADS114S0X GPIO driver must be initialized after ADS114S0X ADC driver"); + +#define GPIO_ADS114S0X_DEVICE(id) \ + static const struct gpio_ads114s0x_config gpio_ads114s0x_##id##_cfg = { \ + .common = {.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(id)}, \ + .parent = DEVICE_DT_GET(DT_INST_BUS(id)), \ + }; \ + \ + static struct gpio_ads114s0x_data gpio_ads114s0x_##id##_data; \ + \ + DEVICE_DT_INST_DEFINE(id, &gpio_ads114s0x_init, NULL, &gpio_ads114s0x_##id##_data, \ + &gpio_ads114s0x_##id##_cfg, POST_KERNEL, \ + CONFIG_GPIO_ADS114S0X_INIT_PRIORITY, &gpio_ads114s0x_api); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_ADS114S0X_DEVICE) diff --git a/include/zephyr/drivers/adc/ads114s0x.h b/include/zephyr/drivers/adc/ads114s0x.h new file mode 100644 index 00000000000..af8cae7a96a --- /dev/null +++ b/include/zephyr/drivers/adc/ads114s0x.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_ADC_ADS114S0X_H_ +#define ZEPHYR_INCLUDE_DRIVERS_ADC_ADS114S0X_H_ + +#include +#include + +int ads114s0x_gpio_set_output(const struct device *dev, uint8_t pin, bool initial_value); + +int ads114s0x_gpio_set_input(const struct device *dev, uint8_t pin); + +int ads114s0x_gpio_deconfigure(const struct device *dev, uint8_t pin); + +int ads114s0x_gpio_set_pin_value(const struct device *dev, uint8_t pin, + bool value); + +int ads114s0x_gpio_get_pin_value(const struct device *dev, uint8_t pin, + bool *value); + +int ads114s0x_gpio_port_get_raw(const struct device *dev, + gpio_port_value_t *value); + +int ads114s0x_gpio_port_set_masked_raw(const struct device *dev, + gpio_port_pins_t mask, + gpio_port_value_t value); + +int ads114s0x_gpio_port_toggle_bits(const struct device *dev, + gpio_port_pins_t pins); + +#endif /* ZEPHYR_INCLUDE_DRIVERS_ADC_ADS114S0X_H_ */