]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
iio: adc: update ad7779 to use IIO backend
authorIoana Risteiu <Ioana.Risteiu@analog.com>
Mon, 25 Aug 2025 22:13:52 +0000 (01:13 +0300)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Wed, 10 Sep 2025 18:46:59 +0000 (19:46 +0100)
Add a new functionality to ad7779 driver that streams data through data
output interface using IIO backend interface.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Ioana Risteiu <Ioana.Risteiu@analog.com>
Link: https://patch.msgid.link/20250825221355.6214-5-Ioana.Risteiu@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/adc/Kconfig
drivers/iio/adc/ad7779.c

index 6de2abad0197bf3ce8df911703072e23d9a8dca2..25177a5dc4021c59cdda220db01edaa3ff62cf86 100644 (file)
@@ -389,6 +389,7 @@ config AD7779
        depends on SPI
        select CRC8
        select IIO_BUFFER
+       select IIO_BACKEND
        help
          Say yes here to build support for Analog Devices AD777X family
          (AD7770, AD7771, AD7779) analog to digital converter (ADC).
index 4e6fa63705935bc4efa4f013ed4dcb0ae17d4411..aac5049c9a07b6fafdd4b3545a03d297d5823a2d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/units.h>
 
 #include <linux/iio/iio.h>
+#include <linux/iio/backend.h>
 #include <linux/iio/buffer.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/trigger.h>
@@ -145,6 +146,7 @@ struct ad7779_state {
        struct completion completion;
        unsigned int sampling_freq;
        enum ad7779_filter filter_enabled;
+       struct iio_backend *back;
        /*
         * DMA (thus cache coherency maintenance) requires the
         * transfer buffers to live in their own cache lines.
@@ -630,12 +632,38 @@ static int ad7779_reset(struct iio_dev *indio_dev, struct gpio_desc *reset_gpio)
        return ret;
 }
 
+static int ad7779_update_scan_mode(struct iio_dev *indio_dev,
+                                  const unsigned long *scan_mask)
+{
+       struct ad7779_state *st = iio_priv(indio_dev);
+       unsigned int c;
+       int ret;
+
+       for (c = 0; c < AD7779_NUM_CHANNELS; c++) {
+               if (test_bit(c, scan_mask))
+                       ret = iio_backend_chan_enable(st->back, c);
+               else
+                       ret = iio_backend_chan_disable(st->back, c);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static const struct iio_info ad7779_info = {
        .read_raw = ad7779_read_raw,
        .write_raw = ad7779_write_raw,
        .debugfs_reg_access = &ad7779_reg_access,
 };
 
+static const struct iio_info ad7779_info_data = {
+       .read_raw = ad7779_read_raw,
+       .write_raw = ad7779_write_raw,
+       .debugfs_reg_access = &ad7779_reg_access,
+       .update_scan_mode = &ad7779_update_scan_mode,
+};
+
 static const struct iio_enum ad7779_filter_enum = {
        .items = ad7779_filter_type,
        .num_items = ARRAY_SIZE(ad7779_filter_type),
@@ -752,6 +780,47 @@ static int ad7779_conf(struct ad7779_state *st, struct gpio_desc *start_gpio)
        return 0;
 }
 
+static int ad7779_set_data_lines(struct iio_dev *indio_dev, u32 num_lanes)
+{
+       struct ad7779_state *st = iio_priv(indio_dev);
+       int ret;
+
+       if (num_lanes != 1 && num_lanes != 2 && num_lanes != 4)
+               return -EINVAL;
+
+       ret = ad7779_set_sampling_frequency(st, num_lanes * AD7779_DEFAULT_SAMPLING_1LINE);
+       if (ret)
+               return ret;
+
+       ret = iio_backend_num_lanes_set(st->back, num_lanes);
+       if (ret)
+               return ret;
+
+       return ad7779_spi_write_mask(st, AD7779_REG_DOUT_FORMAT,
+                                    AD7779_DOUT_FORMAT_MSK,
+                                    FIELD_PREP(AD7779_DOUT_FORMAT_MSK, 2 - ilog2(num_lanes)));
+}
+
+static int ad7779_setup_channels(struct iio_dev *indio_dev, const struct ad7779_state *st)
+{
+       struct iio_chan_spec *channels;
+       struct device *dev = &st->spi->dev;
+
+       channels = devm_kmemdup_array(dev, st->chip_info->channels,
+                                     ARRAY_SIZE(ad7779_channels),
+                                     sizeof(*channels), GFP_KERNEL);
+       if (!channels)
+               return -ENOMEM;
+
+       for (unsigned int i = 0; i < ARRAY_SIZE(ad7779_channels); i++)
+               channels[i].scan_type.endianness = IIO_CPU;
+
+       indio_dev->channels = channels;
+       indio_dev->num_channels = ARRAY_SIZE(ad7779_channels);
+
+       return 0;
+}
+
 static int ad7779_setup_without_backend(struct ad7779_state *st, struct iio_dev *indio_dev)
 {
        int ret;
@@ -797,6 +866,39 @@ static int ad7779_setup_without_backend(struct ad7779_state *st, struct iio_dev
                                     FIELD_PREP(AD7779_DCLK_CLK_DIV_MSK, 7));
 }
 
+static int ad7779_setup_backend(struct ad7779_state *st, struct iio_dev *indio_dev)
+{
+       struct device *dev = &st->spi->dev;
+       int ret;
+       u32 num_lanes;
+
+       indio_dev->info = &ad7779_info_data;
+
+       ret = ad7779_setup_channels(indio_dev, st);
+       if (ret)
+               return ret;
+
+       st->back = devm_iio_backend_get(dev, NULL);
+       if (IS_ERR(st->back))
+               return dev_err_probe(dev, PTR_ERR(st->back),
+                                    "failed to get iio backend");
+
+       ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
+       if (ret)
+               return ret;
+
+       ret = devm_iio_backend_enable(dev, st->back);
+       if (ret)
+               return ret;
+
+       num_lanes = 4;
+       ret = device_property_read_u32(dev, "adi,num-lanes", &num_lanes);
+       if (ret && ret != -EINVAL)
+               return ret;
+
+       return ad7779_set_data_lines(indio_dev, num_lanes);
+}
+
 static int ad7779_probe(struct spi_device *spi)
 {
        struct iio_dev *indio_dev;
@@ -848,7 +950,10 @@ static int ad7779_probe(struct spi_device *spi)
        indio_dev->name = st->chip_info->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
-       ret = ad7779_setup_without_backend(st, indio_dev);
+       if (device_property_present(dev, "io-backends"))
+               ret = ad7779_setup_backend(st, indio_dev);
+       else
+               ret = ad7779_setup_without_backend(st, indio_dev);
        if (ret)
                return ret;
 
@@ -942,3 +1047,4 @@ module_spi_driver(ad7779_driver);
 MODULE_AUTHOR("Ramona Alexandra Nechita <ramona.nechita@analog.com>");
 MODULE_DESCRIPTION("Analog Devices AD7779 ADC");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_BACKEND");