All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] iio: dac: ad5337: Add driver for the AD5337 DAC
@ 2026-06-12 13:31 Marcin Bis
  2026-06-12 13:31 ` [PATCH 2/2] dt-bindings: iio: dac: adi,ad5337: add dt-bindings Marcin Bis
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Marcin Bis @ 2026-06-12 13:31 UTC (permalink / raw)
  To: linux-iio; +Cc: Marcin Bis

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
+
 AD5446	ANALOG DEVICES INC AD5446 DAC DRIVER
 M:	Michael Hennerich <michael.hennerich@analog.com>
 M:	Nuno Sá <nuno.sa@analog.com>
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index cd4870b65415..de2bc2ec2269 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -62,6 +62,16 @@ config AD5064
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad5064.
 
+config AD5337
+	tristate "Analog Devices AD5337 I2C DAC"
+	depends on I2C
+	help
+	  Say yes here to build support for the Analog Devices AD5337 dual
+	  8-bit I2C voltage-output DAC.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called ad5337.
+
 config AD5360
 	tristate "Analog Devices AD5360/61/62/63/70/71/73 DAC driver"
 	depends on SPI
@@ -247,7 +257,7 @@ config AD5696_I2C
 	depends on I2C
 	select AD5686
 	help
-	  Say yes here to build support for Analog Devices AD5311R, AD5337,
+	  Say yes here to build support for Analog Devices AD5311R, AD5337R,
 	  AD5338R, AD5671R, AD5673R, AD5675R, AD5677R, AD5691R, AD5692R, AD5693,
 	  AD5693R, AD5694, AD5694R, AD5695R, AD5696, and AD5696R Digital to
 	  Analog converters.
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 2a80bbf4e80a..1adf80dde4cc 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_AD3530R) += ad3530r.o
 obj-$(CONFIG_AD3552R_HS) += ad3552r-hs.o
 obj-$(CONFIG_AD3552R_LIB) += ad3552r-common.o
 obj-$(CONFIG_AD3552R) += ad3552r.o
+obj-$(CONFIG_AD5337) += ad5337.o
 obj-$(CONFIG_AD5360) += ad5360.o
 obj-$(CONFIG_AD5380) += ad5380.o
 obj-$(CONFIG_AD5421) += ad5421.o
diff --git a/drivers/iio/dac/ad5337.c b/drivers/iio/dac/ad5337.c
new file mode 100644
index 000000000000..b983baa203fe
--- /dev/null
+++ b/drivers/iio/dac/ad5337.c
@@ -0,0 +1,159 @@
+// 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>
+
+#include <linux/iio/iio.h>
+
+#define AD5337_NUM_CHANNELS	2
+#define AD5337_RESOLUTION	8
+/*
+ * AD5338 - 10bit, AD5339 - 12bit
+ */
+
+#define AD5337_PTR_DAC_A	0x01
+#define AD5337_PTR_DAC_B	0x02
+
+struct ad5337_state {
+	struct i2c_client *client;
+	struct mutex lock;
+	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;
+
+	ret = i2c_master_send(st->client, buf, 3);
+
+	return (ret < 0) ? ret : (ret == 3 ? 0 : -EIO);
+}
+
+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);
+	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) {						\
+	.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;
+	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);
+
+	ret = devm_regulator_get_enable_read_voltage(&client->dev, "vcc");
+	if (ret < 0 && ret != -ENODEV)
+		return ret;
+
+	st->vref_mv = ret > 0 ? ret / 1000 : 3300;
+
+	indio_dev->name = "ad5337";
+	indio_dev->info = &ad5337_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = ad5337_channels;
+	indio_dev->num_channels = ARRAY_SIZE(ad5337_channels);
+
+	return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct of_device_id ad5337_of_match[] = {
+	{ .compatible = "adi,ad5337" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ad5337_of_match);
+
+static struct i2c_driver ad5337_driver = {
+	.driver = {
+		.name = "ad5337",
+		.of_match_table = ad5337_of_match,
+	},
+	.probe = ad5337_probe,
+};
+module_i2c_driver(ad5337_driver);
+
+MODULE_AUTHOR("Marcin Bis <marcin@bis-linux.com>");
+MODULE_DESCRIPTION("Analog Devices AD5337 I2C DAC");
+MODULE_LICENSE("GPL");
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-06-12 17:27 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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-12 14:20 ` [PATCH 1/2] iio: dac: ad5337: Add driver for the AD5337 DAC Joshua Crofts
2026-06-12 17:27 ` Jonathan Cameron

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.