iio: adc: add max11205 adc driver
authorRamona Bolboaca <ramona.bolboaca@analog.com>
Wed, 31 Aug 2022 13:30:21 +0000 (16:30 +0300)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Mon, 5 Sep 2022 17:08:34 +0000 (18:08 +0100)
Adding support for max11205 16-bit single-channel ultra-low power
delta-sigma adc.
The MAX11205 is compatible with the 2-wire interface and uses
SCLK and RDY/DOUT for serial communications. In this mode, all
controls are implemented by timing the high or low phase of the SCLK.
The 2-wire serial interface only allows for data to be read out through
the RDY/DOUT output.

Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX11205.pdf
Signed-off-by: Ramona Bolboaca <ramona.bolboaca@analog.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Link: https://lore.kernel.org/r/20220831133021.215625-2-ramona.bolboaca@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/adc/Kconfig
drivers/iio/adc/Makefile
drivers/iio/adc/max11205.c [new file with mode: 0644]

index e3c2881..56e3ca3 100644 (file)
@@ -653,6 +653,20 @@ config MAX1118
          To compile this driver as a module, choose M here: the module will be
          called max1118.
 
+config MAX11205
+       tristate "Maxim max11205 ADC driver"
+       depends on SPI
+       select AD_SIGMA_DELTA
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
+
+       help
+         Say yes here to build support for Maxim max11205 16-bit, single-channel
+         ultra-low power delta-sigma ADC.
+
+         To compile this driver as a module, choose M here: the module will be
+         called max11205.
+
 config MAX1241
        tristate "Maxim max1241 ADC driver"
        depends on SPI_MASTER
index ab08409..46caba7 100644 (file)
@@ -61,6 +61,7 @@ obj-$(CONFIG_LTC2497) += ltc2497.o ltc2497-core.o
 obj-$(CONFIG_MAX1027) += max1027.o
 obj-$(CONFIG_MAX11100) += max11100.o
 obj-$(CONFIG_MAX1118) += max1118.o
+obj-$(CONFIG_MAX11205) += max11205.o
 obj-$(CONFIG_MAX1241) += max1241.o
 obj-$(CONFIG_MAX1363) += max1363.o
 obj-$(CONFIG_MAX9611) += max9611.o
diff --git a/drivers/iio/adc/max11205.c b/drivers/iio/adc/max11205.c
new file mode 100644 (file)
index 0000000..65fc329
--- /dev/null
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Maxim MAX11205 16-Bit Delta-Sigma ADC
+ *
+ * Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX1240-max11205.pdf
+ * Copyright (C) 2022 Analog Devices, Inc.
+ * Author: Ramona Bolboaca <ramona.bolboaca@analog.com>
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/adc/ad_sigma_delta.h>
+
+#define MAX11205_BIT_SCALE     15
+#define MAX11205A_OUT_DATA_RATE        116
+#define MAX11205B_OUT_DATA_RATE        13
+
+enum max11205_chip_type {
+       TYPE_MAX11205A,
+       TYPE_MAX11205B,
+};
+
+struct max11205_chip_info {
+       unsigned int    out_data_rate;
+       const char      *name;
+};
+
+struct max11205_state {
+       const struct max11205_chip_info *chip_info;
+       struct regulator                *vref;
+       struct ad_sigma_delta           sd;
+};
+
+static const struct ad_sigma_delta_info max11205_sigma_delta_info = {
+       .has_registers = false,
+};
+
+static int max11205_read_raw(struct iio_dev *indio_dev,
+                            struct iio_chan_spec const *chan,
+                            int *val, int *val2, long mask)
+{
+       struct max11205_state *st = iio_priv(indio_dev);
+       int reg_mv;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               return ad_sigma_delta_single_conversion(indio_dev, chan, val);
+       case IIO_CHAN_INFO_SCALE:
+               reg_mv = regulator_get_voltage(st->vref);
+               if (reg_mv < 0)
+                       return reg_mv;
+               reg_mv /= 1000;
+               *val = reg_mv;
+               *val2 = MAX11205_BIT_SCALE;
+               return IIO_VAL_FRACTIONAL_LOG2;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               *val = st->chip_info->out_data_rate;
+               return IIO_VAL_INT;
+       default:
+               return -EINVAL;
+       }
+}
+
+static const struct iio_info max11205_iio_info = {
+       .read_raw = max11205_read_raw,
+       .validate_trigger = ad_sd_validate_trigger,
+};
+
+static const struct iio_chan_spec max11205_channels[] = {
+       {
+               .type = IIO_VOLTAGE,
+               .indexed = 1,
+               .scan_type = {
+                       .sign = 's',
+                       .realbits = 16,
+                       .storagebits = 16,
+                       .endianness = IIO_BE,
+               },
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+                                     BIT(IIO_CHAN_INFO_SCALE),
+       },
+};
+
+static const struct max11205_chip_info max11205_chip_info[] = {
+       [TYPE_MAX11205A] = {
+               .out_data_rate = MAX11205A_OUT_DATA_RATE,
+               .name = "max11205a",
+       },
+       [TYPE_MAX11205B] = {
+               .out_data_rate = MAX11205B_OUT_DATA_RATE,
+               .name = "max11205b",
+       },
+};
+
+static void max11205_reg_disable(void *reg)
+{
+       regulator_disable(reg);
+}
+
+static int max11205_probe(struct spi_device *spi)
+{
+       struct max11205_state *st;
+       struct iio_dev *indio_dev;
+       int ret;
+
+       indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       st = iio_priv(indio_dev);
+
+       ad_sd_init(&st->sd, indio_dev, spi, &max11205_sigma_delta_info);
+
+       st->chip_info = device_get_match_data(&spi->dev);
+       if (!st->chip_info)
+               st->chip_info =
+                       (const struct max11205_chip_info *)spi_get_device_id(spi)->driver_data;
+
+       indio_dev->name = st->chip_info->name;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = max11205_channels;
+       indio_dev->num_channels = 1;
+       indio_dev->info = &max11205_iio_info;
+
+       st->vref = devm_regulator_get(&spi->dev, "vref");
+       if (IS_ERR(st->vref))
+               return dev_err_probe(&spi->dev, PTR_ERR(st->vref),
+                                    "Failed to get vref regulator\n");
+
+       ret = regulator_enable(st->vref);
+       if (ret)
+               return ret;
+
+       ret = devm_add_action_or_reset(&spi->dev, max11205_reg_disable, st->vref);
+       if (ret)
+               return ret;
+
+       ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev);
+       if (ret)
+               return ret;
+
+       return devm_iio_device_register(&spi->dev, indio_dev);
+}
+
+static const struct spi_device_id max11205_spi_ids[] = {
+       { "max11205a", (kernel_ulong_t)&max11205_chip_info[TYPE_MAX11205A] },
+       { "max11205b", (kernel_ulong_t)&max11205_chip_info[TYPE_MAX11205B] },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, max11205_spi_ids);
+
+static const struct of_device_id max11205_dt_ids[] = {
+       {
+               .compatible = "maxim,max11205a",
+               .data = &max11205_chip_info[TYPE_MAX11205A],
+       },
+       {
+               .compatible = "maxim,max11205b",
+               .data = &max11205_chip_info[TYPE_MAX11205B],
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, max11205_dt_ids);
+
+static struct spi_driver max11205_spi_driver = {
+       .driver = {
+               .name = "max11205",
+               .of_match_table = max11205_dt_ids,
+       },
+       .probe = max11205_probe,
+       .id_table = max11205_spi_ids,
+};
+module_spi_driver(max11205_spi_driver);
+
+MODULE_AUTHOR("Ramona Bolboaca <ramona.bolboaca@analog.com>");
+MODULE_DESCRIPTION("MAX11205 ADC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA);