[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <525a44e7-8e38-48fd-af84-4c56a6a0ffe7@baylibre.com>
Date: Tue, 2 Sep 2025 10:44:28 -0500
From: David Lechner <dlechner@...libre.com>
To: Marilene Andrade Garcia <marilene.agarcia@...il.com>,
linux-iio@...r.kernel.org, linux-kernel@...r.kernel.org,
devicetree@...r.kernel.org
Cc: Kim Seer Paller <kimseer.paller@...log.com>,
Jonathan Cameron <jic23@...nel.org>, Nuno Sá
<nuno.sa@...log.com>, Andy Shevchenko <andy@...nel.org>,
Lars-Peter Clausen <lars@...afoo.de>,
Michael Hennerich <Michael.Hennerich@...log.com>,
Rob Herring <robh@...nel.org>, Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>,
Marcelo Schmitt <marcelo.schmitt1@...il.com>,
Marcelo Schmitt <Marcelo.Schmitt@...log.com>,
Ceclan Dumitru <dumitru.ceclan@...log.com>,
Jonathan Santos <Jonathan.Santos@...log.com>,
Dragos Bogdan <dragos.bogdan@...log.com>
Subject: Re: [PATCH v10 2/2] iio: adc: max14001: New driver
On 9/2/25 8:16 AM, Marilene Andrade Garcia wrote:
> The MAX14001/MAX14002 is configurable, isolated 10-bit ADCs for multi-range
> binary inputs. In addition to ADC readings, the MAX14001/MAX14002 offers
> more features, like a binary comparator, a filtered reading that can
> provide the average of the last 2, 4, or 8 ADC readings, and an inrush
> comparator that triggers the inrush current. There is also a fault feature
> that can diagnose seven possible fault conditions. And an option to select
> an external or internal ADC voltage reference.
>
> MAX14001/MAX14002 features implemented so far:
> - Raw ADC reading.
> - Filtered ADC average reading with the default configuration.
> - MV fault disable.
> - Selection of external or internal ADC voltage reference, depending on
> whether it is declared in the device tree.
>
> Co-developed-by: Marilene Andrade Garcia <marilene.agarcia@...il.com>
> Signed-off-by: Marilene Andrade Garcia <marilene.agarcia@...il.com>
> Signed-off-by: Kim Seer Paller <kimseer.paller@...log.com>
> ---
> MAINTAINERS | 1 +
> drivers/iio/adc/Kconfig | 10 ++
> drivers/iio/adc/Makefile | 1 +
> drivers/iio/adc/max14001.c | 355 +++++++++++++++++++++++++++++++++++++
> 4 files changed, 367 insertions(+)
> create mode 100644 drivers/iio/adc/max14001.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f145f0204407..b6457063da6c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -14976,6 +14976,7 @@ L: linux-iio@...r.kernel.org
> S: Maintained
> W: https://ez.analog.com/linux-software-drivers
> F: Documentation/devicetree/bindings/iio/adc/adi,max14001.yaml
> +F: drivers/iio/adc/max14001.c
>
> MAXBOTIX ULTRASONIC RANGER IIO DRIVER
> M: Andreas Klinger <ak@...klinger.de>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index e3d3826c3357..11e911ceab4c 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -958,6 +958,16 @@ config MAX11410
> To compile this driver as a module, choose M here: the module will be
> called max11410.
>
> +config MAX14001
> + tristate "Analog Devices MAX14001/MAX14002 ADC driver"
> + depends on SPI
> + help
> + Say yes here to build support for Analog Devices MAX14001/MAX14002
> + Configurable, Isolated 10-bit ADCs for Multi-Range Binary Inputs.
> +
> + To compile this driver as a module, choose M here: the module will be
> + called max14001.
> +
> config MAX1241
> tristate "Maxim max1241 ADC driver"
> depends on SPI_MASTER
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 89d72bf9ce70..569f2f5613d4 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -85,6 +85,7 @@ obj-$(CONFIG_MAX11100) += max11100.o
> obj-$(CONFIG_MAX1118) += max1118.o
> obj-$(CONFIG_MAX11205) += max11205.o
> obj-$(CONFIG_MAX11410) += max11410.o
> +obj-$(CONFIG_MAX14001) += max14001.o
> obj-$(CONFIG_MAX1241) += max1241.o
> obj-$(CONFIG_MAX1363) += max1363.o
> obj-$(CONFIG_MAX34408) += max34408.o
> diff --git a/drivers/iio/adc/max14001.c b/drivers/iio/adc/max14001.c
> new file mode 100644
> index 000000000000..6755df152976
> --- /dev/null
> +++ b/drivers/iio/adc/max14001.c
> @@ -0,0 +1,355 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
> +/*
> + * Analog Devices MAX14001/MAX14002 ADC driver
> + *
> + * Copyright (C) 2023-2025 Analog Devices Inc.
> + * Copyright (C) 2023 Kim Seer Paller <kimseer.paller@...log.com>
> + * Copyright (c) 2025 Marilene Andrade Garcia <marilene.agarcia@...il.com>
> + *
> + * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/MAX14001-MAX14002.pdf
> + */
> +
> +#include <linux/array_size.h>
> +#include <linux/bitfield.h>
> +#include <linux/bitrev.h>
> +#include <linux/bits.h>
> +#include <linux/byteorder/generic.h>
> +#include <linux/device.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/types.h>
> +#include <linux/kernel.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/spi/spi.h>
> +#include <linux/types.h>
> +
> +/* MAX14001 Registers Address */
> +#define MAX14001_REG_ADC 0x00
> +#define MAX14001_REG_FADC 0x01
> +#define MAX14001_REG_FLAGS 0x02
> +#define MAX14001_REG_FLTEN 0x03
> +#define MAX14001_REG_THL 0x04
> +#define MAX14001_REG_THU 0x05
> +#define MAX14001_REG_INRR 0x06
> +#define MAX14001_REG_INRT 0x07
> +#define MAX14001_REG_INRP 0x08
> +#define MAX14001_REG_CFG 0x09
> +#define MAX14001_REG_ENBL 0x0A
> +#define MAX14001_REG_ACT 0x0B
> +#define MAX14001_REG_WEN 0x0C
> +
> +#define MAX14001_REG_VERIFICATION(x) ((x) + 0x10)
> +
> +#define MAX14001_REG_CFG_EXRF BIT(5)
> +
> +#define MAX14001_MASK_ADDR GENMASK(15, 11)
> +#define MAX14001_MASK_DATA GENMASK(9, 0)
> +
> +#define MAX14001_SET_WRITE_BIT BIT(10)
> +#define MAX14001_WRITE_WEN 0x294
> +
> +enum max14001_chip_model {
> + max14001,
> + max14002,
> +};
> +
> +struct max14001_chip_info {
> + const char *name;
> +};
> +
> +struct max14001_state {
> + const struct max14001_chip_info *chip_info;
> + struct spi_device *spi;
> + int vref_mv;
> + /*
> + * lock protect against multiple concurrent accesses, RMW sequence,
> + * and SPI transfer.
> + */
> + struct mutex lock;
> + /*
> + * The following buffers will be bit-reversed during device
> + * communication, because the device transmits and receives data
> + * LSB-first.
Some SPI controllers may be able to handle LSB first without us having
to reverse things in the driver. Search the kernel for SPI_LSB_FIRST
to see what I mean.
By setting `spi-lsb-first;` in the devicetree, the core SPI code will
check if the controller supports it and let the hardare handle everything
so we don't need to reverse bits here in this driver.
If we need to make this work on a SPI controller that doesn't support
SPI_LSB_FIRST, then we should add something in the core SPI code that
does the reversing during __spi_optimize_message() so that every
peripheral driver doesn't have to do this. For example, search spi.c
for SPI_CS_WORD to see how it handles that flag for controllers that
don't support it.
> + * DMA (thus cache coherency maintenance) requires the transfer
> + * buffers to live in their own cache lines.
> + */
> + __be16 spi_tx_buffer __aligned(IIO_DMA_MINALIGN);
> + __be16 spi_rx_buffer;
> +};
> +
> +static int max14001_probe(struct spi_device *spi)
> +{
...
> + ret = devm_mutex_init(dev, &st->lock);
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "Failed to init the mutex\n");
> +
The only possible error here is -ENOMEM, which we don't
print messages for. So just `return ret;` on this one.
Powered by blists - more mailing lists