From 44dac1513bebf02135c5b9ac17ececefc99d66cd Mon Sep 17 00:00:00 2001 From: Marilene A Garcia Date: Sun, 17 Aug 2025 09:39:19 -0300 Subject: [PATCH 1/3] dt-bindings: iio: adc: Add MAX14001 Add device-tree documentation for MAX14001/MAX14002 ADCs. The MAX14001/MAX14002 are isolated, single-channel analog-to-digital converters with programmable voltage comparators and inrush current control optimized for configurable binary input applications. Signed-off-by: Marilene Andrade Garcia --- .../bindings/iio/adc/adi,max14001.yaml | 78 +++++++++++++++++++ MAINTAINERS | 7 ++ 2 files changed, 85 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,max14001.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/adi,max14001.yaml b/Documentation/devicetree/bindings/iio/adc/adi,max14001.yaml new file mode 100644 index 00000000000000..3b2a2e788a17c4 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,max14001.yaml @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright 2025 Marilene Andrade Garcia +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,max14001.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices MAX14001-MAX14002 10-bit ADCs + +maintainers: + - Marilene Andrade Garcia + +description: + Bindings for the Analog Devices MAX14001-MAX14002 Configurable, + Isolated 10-bit ADCs for Multi-Range Binary Inputs. + + Datasheet can be found here + https://www.analog.com/media/en/technical-documentation/data-sheets/MAX14001-MAX14002.pdf + +$ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + enum: + - adi,max14001 + - adi,max14002 + + reg: + maxItems: 1 + + vdd-supply: + description: + Isolated DC-DC power supply input voltage. + + vddl-supply: + description: + Logic power supply. + + vrefin-supply: + description: + ADC voltage reference supply. + + interrupts: + items: + - description: | + Interrupt for signaling when conversion results exceed the configured + upper threshold for ADC readings or fall below the lower threshold for + them. Interrupt source must be attached to COUT pin. + - description: | + Alert output that asserts low during a number of different error + conditions. The interrupt source must be attached to FAULT pin. + + spi-max-frequency: + maximum: 5000000 + +required: + - compatible + - reg + - vdd-supply + - vddl-supply + +unevaluatedProperties: false + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + max14001: adc@0 { + compatible = "adi,max14001"; + reg = <0>; + spi-max-frequency = <5000000>; + vdd-supply = <&vdd>; + vddl-supply = <&vddl>; + }; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index 56f521c7321d4a..5cfad34b3e2a29 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13122,6 +13122,13 @@ W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/adc/maxim,max11205.yaml F: drivers/iio/adc/max11205.c +MAXIM MAX14001/MAX14002 DRIVER +M: Marilene Andrade Garcia +L: linux-iio@vger.kernel.org +S: Maintained +W: https://ez.analog.com/linux-software-drivers +F: Documentation/devicetree/bindings/iio/adc/adi,max14001.yaml + MAXIM MAX17040 FAMILY FUEL GAUGE DRIVERS R: Iskren Chernev R: Krzysztof Kozlowski From aa26b18fc03402a99f3c719aaa6e4fd9b432f5e1 Mon Sep 17 00:00:00 2001 From: Marilene A Garcia Date: Sun, 17 Aug 2025 09:53:09 -0300 Subject: [PATCH 2/3] iio: adc: Add basic support for MAX14001 The MAX14001/MAX14002 are configurable, isolated 10-bit ADCs for multi-range binary inputs. Besides the 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. Add basic support for MAX14001/MAX14002 with the following features: - Raw ADC reading. - Filtered ADC average reading with the default configuration. Signed-off-by: Marilene Andrade Garcia --- MAINTAINERS | 1 + drivers/iio/adc/Kconfig | 10 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/max14001.c | 213 +++++++++++++++++++++++++++++++++++++ 4 files changed, 225 insertions(+) create mode 100644 drivers/iio/adc/max14001.c diff --git a/MAINTAINERS b/MAINTAINERS index 5cfad34b3e2a29..c3031290f91ba0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13128,6 +13128,7 @@ L: linux-iio@vger.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 MAXIM MAX17040 FAMILY FUEL GAUGE DRIVERS R: Iskren Chernev diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index d3d12ed064e50f..22b348bb675a87 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -1126,6 +1126,16 @@ config MAX1363 To compile this driver as a module, choose M here: the module will be called max1363. +config MAX14001 + tristate "Analog Devices MAX14001/MAX14002 ADCs 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 MAX77541_ADC tristate "Analog Devices MAX77541 ADC driver" depends on MFD_MAX77541 diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 6a71631c984217..bc4c6d7a57dd9a 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -156,6 +156,7 @@ obj-$(CONFIG_MAX11205) += max11205.o obj-$(CONFIG_MAX11410) += max11410.o obj-$(CONFIG_MAX1241) += max1241.o obj-$(CONFIG_MAX1363) += max1363.o +obj-$(CONFIG_MAX14001) += max14001.o obj-$(CONFIG_MAX77541_ADC) += max77541-adc.o obj-$(CONFIG_MAX9611) += max9611.o obj-$(CONFIG_MCP320X) += mcp320x.o diff --git a/drivers/iio/adc/max14001.c b/drivers/iio/adc/max14001.c new file mode 100644 index 00000000000000..fb79f3b81e0c70 --- /dev/null +++ b/drivers/iio/adc/max14001.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * MAX14001/MAX14002 SPI ADC driver + * + * Copyright (c) 2025 Marilene Andrade Garcia + * + * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/MAX14001-MAX14002.pdf + */ + +#include +#include +#include +#include +#include +#include +#include + +/* MAX14001 registers definition */ +#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 + +/* MAX14001 CONTROL values*/ +#define MAX14001_REG_WRITE 0x1 +#define MAX14001_REG_READ 0x0 + +/* MAX14001 MASKS */ +#define MAX14001_MASK_ADDR GENMASK(15, 11) +#define MAX14001_MASK_WR BIT(10) +#define MAX14001_MASK_DATA GENMASK(9, 0) + +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; + + __be16 rx_buffer __aligned(IIO_DMA_MINALIGN); + __be16 tx_buffer; +}; + +static struct max14001_chip_info max14001_chip_info_tbl[] = { + [max14001] = { + .name = "max14001", + }, + [max14002] = { + .name = "max14002", + }, +}; + +static int max14001_spi_read(struct max14001_state *st, u16 reg, int *val) +{ + struct spi_transfer xfer[] = { + { + .tx_buf = &st->tx_buffer, + .len = sizeof(st->tx_buffer), + .cs_change = 1, + }, + { + .rx_buf = &st->rx_buffer, + .len = sizeof(st->rx_buffer), + }, + }; + int ret; + + st->tx_buffer = FIELD_PREP(MAX14001_MASK_ADDR, reg) | + FIELD_PREP(MAX14001_MASK_WR, MAX14001_REG_READ); + st->tx_buffer = bitrev16(st->tx_buffer); + + ret = spi_sync_transfer(st->spi, xfer, ARRAY_SIZE(xfer)); + if (ret < 0) + return ret; + + st->rx_buffer = bitrev16(be16_to_cpu(st->rx_buffer)); + *val = FIELD_GET(MAX14001_MASK_DATA, st->rx_buffer); + + return 0; +} + +static int max14001_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct max14001_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = max14001_spi_read(st, MAX14001_REG_ADC, val); + if (ret < 0) + return ret; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_AVERAGE_RAW: + ret = max14001_spi_read(st, MAX14001_REG_FADC, val); + if (ret < 0) + return ret; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = st->vref_mv; + *val2 = 10; + + return IIO_VAL_FRACTIONAL_LOG2; + } + + return -EINVAL; +} + +static const struct iio_info max14001_info = { + .read_raw = max14001_read_raw, +}; + +static const struct iio_chan_spec max14001_channel[] = { + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_AVERAGE_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + } +}; + +static int max14001_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct max14001_state *st; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + st->spi = spi; + st->chip_info = spi_get_device_match_data(spi); + if (!st->chip_info) + return dev_err_probe(dev, -ENODEV, "Failed to get match data\n"); + + indio_dev->name = st->chip_info->name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &max14001_info; + indio_dev->channels = max14001_channel; + indio_dev->num_channels = ARRAY_SIZE(max14001_channel); + + ret = devm_regulator_get_enable(dev, "vdd"); + if (ret) + return dev_err_probe(dev, ret, + "Failed to enable specified Vdd supply\n"); + + ret = devm_regulator_get_enable(dev, "vddl"); + if (ret) + return dev_err_probe(dev, ret, + "Failed to enable specified Vddl supply\n"); + + ret = devm_regulator_get_enable_read_voltage(dev, "vrefin"); + if (ret < 0) + st->vref_mv = 1250000 / 1000; + else + st->vref_mv = ret / 1000; + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct spi_device_id max14001_id_table[] = { + { "max14001", (kernel_ulong_t)&max14001_chip_info_tbl[max14001] }, + { "max14002", (kernel_ulong_t)&max14001_chip_info_tbl[max14002] }, + {} +}; +MODULE_DEVICE_TABLE(spi, max14001_id_table); + +static const struct of_device_id max14001_of_match[] = { + { .compatible = "adi,max14001", + .data = &max14001_chip_info_tbl[max14001], }, + { .compatible = "adi,max14002", + .data = &max14001_chip_info_tbl[max14002], }, + { } +}; +MODULE_DEVICE_TABLE(of, max14001_of_match); + +static struct spi_driver max14001_driver = { + .driver = { + .name = "max14001", + .of_match_table = max14001_of_match, + }, + .probe = max14001_probe, + .id_table = max14001_id_table, +}; +module_spi_driver(max14001_driver); + +MODULE_AUTHOR("Marilene Andrade Garcia "); +MODULE_DESCRIPTION("Analog Devices MAX14001/MAX14002 ADCs driver"); +MODULE_LICENSE("GPL"); From d6dc4f704761a15b1f4850808b758887a9640d12 Mon Sep 17 00:00:00 2001 From: Marilene A Garcia Date: Sun, 17 Aug 2025 10:09:55 -0300 Subject: [PATCH 3/3] overlays: rpi-max14001-pmb-overlay.dts: Add MAX14001PMB example overlay The MAX14001 is a configurable, isolated 10-bit ADC for multi-range binary inputs. Besides the ADC readings, the MAX14001 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. The MAX14001PMB provides the hardware to evaluate the MAX14001 to measure two channels of data, line voltage and load current. Signed-off-by: Marilene Andrade Garcia --- arch/arm/boot/dts/overlays/Makefile | 1 + .../dts/overlays/rpi-max14001-pmb-overlay.dts | 77 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 arch/arm/boot/dts/overlays/rpi-max14001-pmb-overlay.dts diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile index a9fa5cc30d63fe..d34acec61e0399 100644 --- a/arch/arm/boot/dts/overlays/Makefile +++ b/arch/arm/boot/dts/overlays/Makefile @@ -309,6 +309,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ rpi-ltc2991.dtbo \ rpi-ltc4162.dtbo \ rpi-ltc6952.dtbo \ + rpi-max14001-pmb.dtbo \ rpi-max14830-i2c.dtbo \ rpi-max14830-spi.dtbo \ rpi-max31335.dtbo \ diff --git a/arch/arm/boot/dts/overlays/rpi-max14001-pmb-overlay.dts b/arch/arm/boot/dts/overlays/rpi-max14001-pmb-overlay.dts new file mode 100644 index 00000000000000..837113c22eeb2e --- /dev/null +++ b/arch/arm/boot/dts/overlays/rpi-max14001-pmb-overlay.dts @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Overlay for the MAX14001 ADC + * + * Copyright (c) 2025 Marilene Andrade Garcia + * + * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/MAX14001-MAX14002.pdf + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2712"; +}; + +&{/} { + vdd: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "Isolated DC-DC Power Supply Input Voltage"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + status = "okay"; + }; + + vddl: fixedregulator@1 { + compatible = "regulator-fixed"; + regulator-name = "Logic Power Supply Voltage"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + status = "okay"; + }; + + vrefin: fixedregulator@2 { + compatible = "regulator-fixed"; + regulator-name = "Reference Input Range Voltage"; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-boot-on; + regulator-always-on; + status = "okay"; + }; +}; + +&spi0 { + status = "okay"; + max14001_u51: max14001@0 { + compatible = "adi,max14001"; + reg = <0x0>; + spi-max-frequency = <5000000>; + vdd-supply = <&vdd>; + vddl-supply = <&vddl>; + vrefin-supply = <&vrefin>; + status = "okay"; + }; + max14001_u11: max14001@1 { + compatible = "adi,max14001"; + reg = <0x1>; + spi-max-frequency = <5000000>; + vdd-supply = <&vdd>; + vddl-supply = <&vddl>; + vrefin-supply = <&vrefin>; + status = "okay"; + }; +}; + +&spidev0 { + status = "disabled"; +}; + +&spidev1 { + status = "disabled"; +};