Skip to content

iio: adc: Add initial driver support for MAX22531 #2854

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: rpi-6.6.y_GSOC_2025_MAX22531
Choose a base branch
from

Conversation

KernelShinobi
Copy link
Contributor

MAX22531 is a galvanically isolated, field-side self-powered, 4-channel, multiplexed, 12-bit ADC.

PR Description

Basic IIO ADC max22531 driver features:

  • Definitions for register addresses and useful constants (if any).
  • Definitions for the IIO channels.
  • A device state struct.
  • A read_raw function implementation (may be just a mock for now).
  • An iio_info struct populated with a reference to the read_raw function.
  • A probe function to initialize and setup the device.
  • SPI and device tree MODULE_DEVICE_TABLEs

PR Type

  • New feature (a change that adds new functionality)

PR Checklist

  • I have conducted a self-review of my own code changes
  • I could not test the DT overlay and/or the driver probing. However, I have compiled it on my machine and used static tools to ensure the code is okay.

psychild added 4 commits July 10, 2025 15:58
Signed-off-by: Abhinav Jain <jain.abhinav177@gmail.com>
Signed-off-by: Abhinav Jain <jain.abhinav177@gmail.com>
Signed-off-by: Abhinav Jain <jain.abhinav177@gmail.com>
Signed-off-by: Abhinav Jain <jain.abhinav177@gmail.com>
Copy link
Contributor

@machschmitt machschmitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @KernelShinobi , a few comments about this initial driver version.
Note that, aside from the comments above, there are still some improvements that need to be made to make this driver usable (e.g. read ADC sample data, provide scale to convert output codes to mV). Those features shall be implemented next. Though, overall, this looks good to me as an initial driver version.

/plugin/;

/ {
compatible = "brcm,bcm2835-spi", "brcm,bcm2711";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may need to add brcm,bcm2712 to this list to actually indicate this overlay is compatible with rpi5.

-	compatible = "brcm,bcm2835-spi", "brcm,bcm2711";
+	compatible = "brcm,bcm2712", "brcm,bcm2835-spi", "brcm,bcm2711";

max22531@0 {
compatible = "maxim,max22531";
reg = <0>; /* Using CS0 on spi0 */
spi-max-frequency = <10000000>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10 MHz is relatively fast for a rpi SPI controller. If you observe transfers bringing strange results or failing when you receive the hw, then consider decreasing the SPI clock frequency.

tristate "Analog Devices MAX22531 ADC Driver"
depends on SPI
help
Say yes here to build support for this driver.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a thing crucial for the moment, but I'd add the usual config help text boilerplate here. Upstream folks may request it, and there's nothing preventing us from adding a few more lines of text here.

.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.scan_index = ch, \
.output = 0, \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

-		.output = 0,						\

MAX22531_CHANNEL(1),
MAX22531_CHANNEL(2),
MAX22531_CHANNEL(3),
IIO_CHAN_SOFT_TIMESTAMP(2),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave the timestamp channel for after buffer support is implemented. Timestamp channels are not very useful on their own.

adc = iio_priv(indio_dev);
adc->spi_dev = spi;

indio_dev->name = "max22531";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be better set according to the specific device (max22530, max22531, or max22532) if a chip_info struct is implemented. See https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/iio/adc/ad7124.c?h=v6.16-rc6#n196 for an example.

}

static const struct spi_device_id max22531_id[] = {
{ "max22531" },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

provide entries for max22530, and max22532 too

MODULE_DEVICE_TABLE(spi, max22531_id);

static const struct of_device_id max22531_spi_of_id[] = {
{ .compatible = "adi,max22531" },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, add OF entries for matching with max22530 and max22532.

Comment on lines +130 to +136
adc->vref = devm_regulator_get(&spi->dev, "vref");
if (IS_ERR(adc->vref))
dev_err(&spi->dev, "Failed to retrieve vref\n");

ret = regulator_enable(adc->vref);
if (ret)
return ret;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vref is an internal voltage reference that is always on/enabled. If I'm not missing anything, we can just use vref. E.g.

#define MAX22531_VREF_MV	1800

thus we don't need to keep a vref regulator field in struct max22351.
For regulators, the driver should request VDDL and VDDPL regulators, as those must be supplied to power the MAX22531 chip.

};

static const struct regmap_config regmap_config = {
.reg_bits = 16,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SPI read/write commands (datasheet Table 1 and Table 2) have 8-bit header so we would have .reg_bits = 8 (or reg_bits = 6 maybe).
Though, the header also contains the W/R and burst bits.
I think the W/R can be handled with
.write_flag_mask = BIT(1)
the burst bit skipped with
.pad_bits = 1
See https://elixir.bootlin.com/linux/v6.15.6/source/include/linux/regmap.h#L254


adc->regmap = devm_regmap_init_spi(spi, &regmap_config);
if (IS_ERR(adc->regmap))
dev_err(&spi->dev, "regmap init failure\n");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually when something critical fails in the probe it is better to stop and return, like:
return dev_err_probe(&spi->dev, PTR_ERR(adc->regmap), "regmap init failure\n")

Same for other similar cases here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants