Linux IIO development
 help / color / mirror / Atom feed
From: Joshua Crofts <joshua.crofts1@gmail.com>
To: Marcin Bis <marcin@bis-linux.com>
Cc: linux-iio@vger.kernel.org
Subject: Re: [PATCH 1/2] iio: dac: ad5337: Add driver for the AD5337 DAC
Date: Fri, 12 Jun 2026 16:20:22 +0200	[thread overview]
Message-ID: <20260612162022.00003e66@gmail.com> (raw)
In-Reply-To: <20260612133125.196208-1-marcin@bis-linux.com>

On Fri, 12 Jun 2026 15:31:21 +0200
Marcin Bis <marcin@bis-linux.com> wrote:

> Add driver for the AD5337 dual 8-bit I2C voltage-output DAC.
> This part uses the pointer-byte protocol and is not compatible with
> the AD5337R nanoDAC+ driver (adi,ad5337r).
> 
> Signed-off-by: Marcin Bis <marcin@bis-linux.com>
> ---
>  MAINTAINERS              |   5 ++
>  drivers/iio/dac/Kconfig  |  12 ++-
>  drivers/iio/dac/Makefile |   1 +
>  drivers/iio/dac/ad5337.c | 159 +++++++++++++++++++++++++++++++++++++++
>  4 files changed, 176 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/iio/dac/ad5337.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e035a3be797c..614589b6efa4 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -438,6 +438,11 @@ W:	http://wiki.analog.com/AD5398
>  W:	https://ez.analog.com/linux-software-drivers
>  F:	drivers/regulator/ad5398.c
>  
> +AD5337  ANALOG DEVICES INC AD5337 DAC DRIVER
> +M:	Marcin Bis <marcin@bis-linux.com>
> +S:	Maintained
> +F:	drivers/iio/dac/ad5337.c

Once you reorder your patches, this should go into the (first)
dt-binding patch.

> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Analog Devices AD5337 I2C DAC driver
> + *
> + * Copyright 2017 Marcin Bis <marcin@bis-linux.com>
> + */
> +
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/regulator/consumer.h>

You're definitely missing array_size.h, types.h, mod_devicetable.h
and err.h.

> +#include <linux/iio/iio.h>
> +
> +#define AD5337_NUM_CHANNELS	2
> +#define AD5337_RESOLUTION	8
> +/*
> + * AD5338 - 10bit, AD5339 - 12bit
> + */

This comment can just be on one line.

> +
> +#define AD5337_PTR_DAC_A	0x01
> +#define AD5337_PTR_DAC_B	0x02
> +
> +struct ad5337_state {
> +	struct i2c_client *client;
> +	struct mutex lock;

Add a comment on why you need a mutex.

> +	unsigned int vref_mv;
> +	u8 cache[AD5337_NUM_CHANNELS];
> +};
> +
> +static int ad5337_write_dac(struct ad5337_state *st, int channel, u8 value)
> +{
> +	u8 buf[3];
> +	int ret;
> +
> +	if (channel)
> +		buf[0] = AD5337_PTR_DAC_B;
> +	else
> +		buf[0] = AD5337_PTR_DAC_A;
> +
> +	/* PD1=0, PD0=0, CLR=1, LDAC=0, D[7:4] */
> +	buf[1] = 0x20 | (value >> 4);
> +	buf[2] = (value & 0x0f) << 4;

You should definitely use FIELD_GET/FIELD_PREP macros from the 
<linux/bitfield.h> header, it improves readability by a lot!

Also, use macros instead of just defining magic numbers like this.

> +
> +	ret = i2c_master_send(st->client, buf, 3);

Use sizeof(buf) instead of just hardcoding the size.

> +
> +	return (ret < 0) ? ret : (ret == 3 ? 0 : -EIO);

I'd definitely abandon using a terniary operator and just break it into
if statements, on first glance this is really hard to read.

> +}
> +
> +static int ad5337_read_raw(struct iio_dev *indio_dev,
> +			   struct iio_chan_spec const *chan,
> +			   int *val, int *val2, long mask)
> +{
> +	struct ad5337_state *st = iio_priv(indio_dev);
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		*val = st->cache[chan->channel];
> +		return IIO_VAL_INT;
> +	case IIO_CHAN_INFO_SCALE:
> +		*val = st->vref_mv;
> +		*val2 = AD5337_RESOLUTION;
> +		return IIO_VAL_FRACTIONAL_LOG2;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static int ad5337_write_raw(struct iio_dev *indio_dev,
> +			    struct iio_chan_spec const *chan,
> +			    int val, int val2, long mask)
> +{
> +	struct ad5337_state *st = iio_priv(indio_dev);
> +	int ret;
> +
> +	if (mask != IIO_CHAN_INFO_RAW)
> +		return -EINVAL;
> +
> +	if (val < 0 || val > ((1 << AD5337_RESOLUTION) - 1))
> +		return -EINVAL;
> +
> +	mutex_lock(&st->lock);

Consider using the guard(mutex)() macro from cleanup.h, it saves lines
and prevents future developers from accidentally forgetting to release
locks (don't forget to add the header as well though)!

> +	ret = ad5337_write_dac(st, chan->channel, val);
> +	if (!ret)
> +		st->cache[chan->channel] = val;
> +	mutex_unlock(&st->lock);
> +
> +	return ret;
> +}
> +
> +static const struct iio_info ad5337_info = {
> +	.read_raw = ad5337_read_raw,
> +	.write_raw = ad5337_write_raw,
> +};
> +
> +#define AD5337_CHANNEL(_chan) {						\

A very tiny nitpick, but you don't need to align your backslashes when defining
a macro.

> +	.type = IIO_VOLTAGE,						\
> +	.indexed = 1,							\
> +	.output = 1,							\
> +	.channel = (_chan),						\
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
> +	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\
> +}
> +
> +static const struct iio_chan_spec ad5337_channels[] = {
> +	AD5337_CHANNEL(0),
> +	AD5337_CHANNEL(1),
> +};
> +
> +static int ad5337_probe(struct i2c_client *client)
> +{
> +	struct ad5337_state *st;
> +	struct iio_dev *indio_dev;

Very much a nit, but swap these lines.

> +	int ret;
> +
> +	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
> +		return -ENODEV;
> +
> +	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	st = iio_priv(indio_dev);
> +	st->client = client;
> +	mutex_init(&st->lock);

Use devm_mutex_init().

> +
> +	ret = devm_regulator_get_enable_read_voltage(&client->dev, "vcc");
> +	if (ret < 0 && ret != -ENODEV)
> +		return ret;

Return dev_err_probe() here.

> +
> +	st->vref_mv = ret > 0 ? ret / 1000 : 3300;

More magic numbers. If you're converting units, consider using
macros from <linux/units.h>.

-- 
Kind regards

CJD

  parent reply	other threads:[~2026-06-12 14:20 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-12 13:31 [PATCH 1/2] iio: dac: ad5337: Add driver for the AD5337 DAC Marcin Bis
2026-06-12 13:31 ` [PATCH 2/2] dt-bindings: iio: dac: adi,ad5337: add dt-bindings Marcin Bis
2026-06-12 13:58   ` Joshua Crofts
2026-06-12 17:09   ` Jonathan Cameron
2026-06-13  7:48   ` Krzysztof Kozlowski
2026-06-12 14:20 ` Joshua Crofts [this message]
2026-06-12 17:27 ` [PATCH 1/2] iio: dac: ad5337: Add driver for the AD5337 DAC Jonathan Cameron

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260612162022.00003e66@gmail.com \
    --to=joshua.crofts1@gmail.com \
    --cc=linux-iio@vger.kernel.org \
    --cc=marcin@bis-linux.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox