[PATCH v2 4/7] iio: adc: Add AD7768 IIO Driver support

Janani Sunil <[email protected]>
Newsgroups org.kernel.vger.linux-gpio,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-doc,org.kernel.vger.linux-iio,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Add support for AD7768 4/8 channel,simultaneous sampling Sigma-Delta
ADCs. The driver supports configurable decimation filters, per-channel
conversion delay, VCM regulation, runtime PM and IIO backend data
capture.

Signed-off-by: Janani Sunil <[email protected]>
---
 MAINTAINERS              |    1 +
 drivers/iio/adc/Kconfig  |   16 +
 drivers/iio/adc/Makefile |    1 +
 drivers/iio/adc/ad7768.c | 1720 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1738 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index d667a0411f28..dc94e7803a7c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1639,6 +1639,7 @@ L:	[email protected]
 S:	Supported
 W:	https://ez.analog.com/linux-software-drivers
 F:	Documentation/devicetree/bindings/iio/adc/adi,ad7768.yaml
+F:	drivers/iio/adc/ad7768.c
 
 ANALOG DEVICES INC AD7780 DRIVER
 M:	Michael Hennerich <[email protected]>
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index d1b198cb8a80..1325cdbedea4 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -429,6 +429,22 @@ config AD7766
 	  To compile this driver as a module, choose M here: the module will be
 	  called ad7766.
 
+config AD7768
+	tristate "Analog Devices AD7768/AD7768-4 ADC driver"
+	depends on SPI
+	depends on REGULATOR || COMPILE_TEST
+	select AUXILIARY_BUS
+	select IIO_BUFFER
+	select IIO_BACKEND
+	select REGMAP
+	help
+	  Say yes here to build support for Analog Devices AD7768 and AD7768-4
+	  SPI analog to digital converters.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called ad7768.
+
+
 config AD7768_1
 	tristate "Analog Devices AD7768-1 ADC driver"
 	depends on SPI
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 0f90b75577ff..3e896c8aa7c3 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
 obj-$(CONFIG_AD7606) += ad7606.o
 obj-$(CONFIG_AD7625) += ad7625.o
 obj-$(CONFIG_AD7766) += ad7766.o
+obj-$(CONFIG_AD7768) += ad7768.o
 obj-$(CONFIG_AD7768_1) += ad7768-1.o
 obj-$(CONFIG_AD7779) += ad7779.o
 obj-$(CONFIG_AD7780) += ad7780.o
diff --git a/drivers/iio/adc/ad7768.c b/drivers/iio/adc/ad7768.c
new file mode 100644
index 000000000000..1bba066435e3
--- /dev/null
+++ b/drivers/iio/adc/ad7768.c
@@ -0,0 +1,1720 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Analog Devices AD7768 ADC driver
+ *
+ * Copyright 2018-2026 Analog Devices Inc.
+ */
+
+#include <linux/array_size.h>
+#include <linux/auxiliary_bus.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/reset.h>
+#include <linux/spi/spi.h>
+#include <linux/types.h>
+
+#include <linux/iio/backend.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/types.h>
+
+#define AD7768_REG_GPIO_CONTROL		0x0E
+
+/* AD7768 registers definition */
+#define AD7768_REG_CH_STANDBY			0x00
+#define AD7768_REG_CH_MODE(x)			(0x01 + (x))
+#define AD7768_REG_CH_MODE_SEL			0x03
+#define AD7768_REG_POWER_MODE			0x04
+#define AD7768_REG_GENERAL_CONFIG		0x05
+#define AD7768_REG_DATA_CONTROL			0x06
+#define AD7768_REG_INTERFACE_CFG		0x07
+#define AD7768_REG_REV_ID			0x0A
+#define AD7768_REG_PRECHARGE_BUF1		0x11
+#define AD7768_REG_PRECHARGE_BUF2		0x12
+#define AD7768_REG_REFP_BUF			0x13
+#define AD7768_REG_REFN_BUF			0x14
+#define AD7768_REG_OFFSET_BASE			0x1E
+#define AD7768_REG_GAIN_BASE			0x36
+#define AD7768_REG_PHASE_BASE			0x4E
+#define AD7768_REG_OFFSET(ch)			((AD7768_REG_OFFSET_BASE + (3 * (ch))))
+#define AD7768_REG_GAIN(ch)			((AD7768_REG_GAIN_BASE + (3 * (ch))))
+#define AD7768_REG_PHASE(ch)			((AD7768_REG_PHASE_BASE + (ch)))
+#define __AD7768_4_REG_MAP(ch)		((ch) < 2 ? (ch) : ((ch) + 2))
+#define AD7768_4_REG_OFFSET(ch) \
+	(AD7768_REG_OFFSET_BASE + (3 * __AD7768_4_REG_MAP(ch)))
+#define AD7768_4_REG_GAIN(ch) \
+	(AD7768_REG_GAIN_BASE + (3 * __AD7768_4_REG_MAP(ch)))
+#define AD7768_4_REG_PHASE(ch)		(AD7768_REG_PHASE_BASE + __AD7768_4_REG_MAP(ch))
+#define AD7768_REG_DIAGNOSTIC_RX		0x56
+#define AD7768_REG_DIAGNOSTIC_MUX_CTRL		0x57
+#define AD7768_REG_MODULATOR_DELAY_CTRL		0x58
+#define AD7768_REG_CHOP_CTRL			0x59
+
+/* AD7768_REG_CH_MODE */
+#define   AD7768_CH_MODE_FILTER_TYPE_MSK	BIT(3)
+#define   AD7768_CH_MODE_FILTER_TYPE_MODE(x)	(((x) & 0x1) << 3)
+#define   AD7768_CH_MODE_DEC_RATE_MSK		GENMASK(2, 0)
+#define   AD7768_CH_MODE_DEC_RATE_MODE(x)	(((x) & 0x7) << 0)
+
+/* AD7768_REG_CH_MODE_SEL */
+#define   AD7768_CH_MODE_READ_MSK		GENMASK(7, 0)
+#define   AD7768_CH_MODE_READ_MODE(x)		((x) & 0xFF)
+#define   AD7768_CH_MODE_READ_GET(x)		((x) & 0xFF)
+#define   AD7768_CH_MODE_READ_CHN(n)		BIT(n)
+#define   AD7768_GET_CH_MODE_8CH(ch, x)		(!!((x) & BIT(ch)))
+
+/* AD7768_REG_POWER_MODE */
+#define   AD7768_SLEEP_MODE_MSK			BIT(7)
+#define   AD7768_POWER_MODE_POWER_MODE_MSK	GENMASK(5, 4)
+#define   AD7768_POWER_MODE_POWER_MODE(x)	(((x) & 0x3) << 4)
+#define   AD7768_POWER_MODE_MCLK_DIV_MSK	GENMASK(1, 0)
+
+/* AD7768_REG_DATA_CONTROL */
+#define   AD7768_DATA_CONTROL_SPI_RESET_MSK	GENMASK(1, 0)
+#define   AD7768_DATA_CONTROL_SPI_RESET_1	0x03
+#define   AD7768_DATA_CONTROL_SPI_RESET_2	0x02
+#define   AD7768_DATA_CONTROL_SPI_SYNC_MSK	BIT(7)
+
+/* AD7768_REG_INTERFACE_CFG */
+#define   AD7768_INTERFACE_CFG_DCLK_DIV_MSK	GENMASK(1, 0)
+#define   AD7768_INTERFACE_CFG_DCLK_DIV_MODE(x)	(4 - ffs(x))
+#define   AD7768_MAX_DCLK_DIV			8
+
+#define   AD7768_INTERFACE_CFG_CRC_SELECT_MSK	GENMASK(3, 2)
+/* Hardware supports CRC every 4 or 16 samples; backend supports 4-sample only */
+#define   AD7768_INTERFACE_CFG_CRC_SELECT	FIELD_PREP(GENMASK(3, 2), 0x01)
+
+/* AD7768_REG_GENERAL_CONFIG */
+#define   AD7768_GEN_CONFIG_VCM_SEL_MSK		GENMASK(1, 0)
+#define   AD7768_GEN_CONFIG_VCM_PD		BIT(4)
+
+/* AD7768_REG_PRECHARGE_BUF1 and 2*/
+#define   AD7768_PREBUF_POS_EN(ch)	BIT((ch) * 2)
+#define   AD7768_PREBUF_NEG_EN(ch)	BIT(((ch) * 2) + 1)
+
+#define   AD7768_SPI_READ_CMD			BIT(15)
+#define   AD7768_SPI_REG_MASK			GENMASK(14, 8)
+#define   AD7768_SPI_DATA_MASK			GENMASK(7, 0)
+#define   AD7768_OUTPUT_MODE_TWOS_COMPLEMENT	0x01
+#define   AD7768_SAMPLE_SIZE				32
+#define   AD7768_PICO_PER_SEC			1000000000000ULL
+#define   MAX_FREQ_PER_MODE			6
+#define   AD7768_MAX_CHANNEL  8
+#define   AD7768_NUM_CHANNEL_MODES		2
+#define   AD7768_CALIB_REG_MSB_MSK		GENMASK(23, 16)
+#define   AD7768_CALIB_REG_MID_MSK		GENMASK(15, 8)
+#define   AD7768_CALIB_REG_LSB_MSK		GENMASK(7, 0)
+#define   AD7768_CALIB_REG_MSK			GENMASK(23, 0)
+#define   AD7768_REV_ID_VAL			0x06
+#define   AD7768_WIDEBAND_SETTLING_SAMPLES	68
+#define   AD7768_SINC5_SETTLING_SAMPLES		7
+
+enum ad7768_filter_type {
+	AD7768_FILTER_TYPE_WIDEBAND,
+	AD7768_FILTER_TYPE_SINC5,
+};
+
+enum ad7768_power_modes {
+	AD7768_LOW_POWER_MODE,
+	AD7768_MEDIAN_MODE,
+	AD7768_FAST_MODE,
+	AD7768_NUM_POWER_MODES
+};
+
+#define AD7768_MAX_FREQS	(MAX_FREQ_PER_MODE + AD7768_NUM_POWER_MODES)
+
+struct ad7768_precharge_config {
+	bool prebufp_en;
+	bool prebufn_en;
+	bool refbufp;
+	bool refbufn;
+};
+
+struct ad7768_freq_config {
+	unsigned int freq;
+	unsigned int dec_rate;
+};
+
+struct ad7768_convdelay_params {
+	unsigned int shift;
+	unsigned int max_raw;
+	u64 step_ps;
+};
+
+struct ad7768_avail_freq {
+	unsigned int n_freqs;
+	int freqs[MAX_FREQ_PER_MODE];
+	struct ad7768_freq_config freq_cfg[MAX_FREQ_PER_MODE];
+};
+
+struct ad7768_chip_info {
+	const char *name;
+	unsigned int num_channels;
+	const struct iio_chan_spec channel[AD7768_MAX_CHANNEL];
+	const struct regmap_config *regmap_config;
+	const unsigned int *available_datalines;
+	unsigned int num_datalines;
+	const u8 *chan_map;
+	u8 prebuf_split;
+};
+
+struct ad7768_state {
+	struct spi_device *spi;
+	struct regmap *regmap;
+	struct mutex lock; /* Protects device register access and configuration */
+	struct clk *mclk;
+	unsigned int datalines;
+	enum ad7768_power_modes power_mode;
+	const struct ad7768_chip_info *chip_info;
+	struct ad7768_avail_freq avail_freq[AD7768_NUM_POWER_MODES];
+	unsigned int n_freqs;
+	int freqs[AD7768_MAX_FREQS];
+	unsigned int chn_mode[AD7768_MAX_CHANNEL];
+	unsigned int ch_freq[AD7768_MAX_CHANNEL];
+	u64 ch_convdelay_ps[AD7768_MAX_CHANNEL];
+	enum ad7768_filter_type ch_filter[AD7768_MAX_CHANNEL];
+	struct iio_backend *back;
+	struct regulator_dev *vcm_rdev;
+	unsigned int avdd1_uv;
+
+	__be16 d16 __aligned(IIO_DMA_MINALIGN);
+};
+
+static const unsigned int ad7768_vcm_voltage_table[] = {
+	0, 1650000, 2500000, 2140000
+};
+
+static int ad7768_vcm_list_voltage(struct regulator_dev *rdev,
+				   unsigned int selector)
+{
+	struct ad7768_state *st = rdev_get_drvdata(rdev);
+
+	if (selector >= ARRAY_SIZE(ad7768_vcm_voltage_table))
+		return -EINVAL;
+
+	if (!selector)
+		return DIV_ROUND_CLOSEST(st->avdd1_uv, 2);
+
+	return ad7768_vcm_voltage_table[selector];
+}
+
+static int ad7768_vcm_enable(struct regulator_dev *rdev)
+{
+	struct ad7768_state *st = rdev_get_drvdata(rdev);
+	int ret;
+
+	ret = pm_runtime_resume_and_get(&st->spi->dev);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_clear_bits(st->regmap, AD7768_REG_GENERAL_CONFIG,
+				AD7768_GEN_CONFIG_VCM_PD);
+	if (ret)
+		pm_runtime_put_autosuspend(&st->spi->dev);
+
+	return ret;
+}
+
+static int ad7768_vcm_disable(struct regulator_dev *rdev)
+{
+	struct ad7768_state *st = rdev_get_drvdata(rdev);
+	int ret;
+
+	ret = regmap_set_bits(st->regmap, AD7768_REG_GENERAL_CONFIG,
+			      AD7768_GEN_CONFIG_VCM_PD);
+	if (ret)
+		return ret;
+
+	pm_runtime_put_autosuspend(&st->spi->dev);
+
+	return 0;
+}
+
+static int ad7768_vcm_is_enabled(struct regulator_dev *rdev)
+{
+	struct ad7768_state *st = rdev_get_drvdata(rdev);
+	unsigned int val;
+	int ret;
+
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(&st->spi->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(st->regmap, AD7768_REG_GENERAL_CONFIG, &val);
+	if (ret)
+		return ret;
+
+	return !(val & AD7768_GEN_CONFIG_VCM_PD);
+}
+
+static int ad7768_vcm_set_voltage_sel(struct regulator_dev *rdev,
+				      unsigned int selector)
+{
+	struct ad7768_state *st = rdev_get_drvdata(rdev);
+	int ret;
+
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(&st->spi->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	return regmap_update_bits(st->regmap, AD7768_REG_GENERAL_CONFIG,
+				  AD7768_GEN_CONFIG_VCM_SEL_MSK, selector);
+}
+
+static int ad7768_vcm_get_voltage_sel(struct regulator_dev *rdev)
+{
+	struct ad7768_state *st = rdev_get_drvdata(rdev);
+	unsigned int val;
+	int ret;
+
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(&st->spi->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(st->regmap, AD7768_REG_GENERAL_CONFIG, &val);
+	if (ret)
+		return ret;
+
+	return FIELD_GET(AD7768_GEN_CONFIG_VCM_SEL_MSK, val);
+}
+
+static const struct regulator_ops ad7768_vcm_ops = {
+	.enable = ad7768_vcm_enable,
+	.disable = ad7768_vcm_disable,
+	.is_enabled = ad7768_vcm_is_enabled,
+	.list_voltage = ad7768_vcm_list_voltage,
+	.set_voltage_sel = ad7768_vcm_set_voltage_sel,
+	.get_voltage_sel = ad7768_vcm_get_voltage_sel,
+};
+
+static const struct regulator_desc ad7768_vcm_desc = {
+	.name = "vcm",
+	.of_match = of_match_ptr("vcm-output"),
+	.n_voltages = ARRAY_SIZE(ad7768_vcm_voltage_table),
+	.ops = &ad7768_vcm_ops,
+	.type = REGULATOR_VOLTAGE,
+	.owner = THIS_MODULE,
+};
+
+static int ad7768_register_vcm_regulator(struct device *dev,
+					 struct ad7768_state *st)
+{
+	struct regulator_config config = {
+		.dev = dev,
+		.driver_data = st,
+	};
+	int ret;
+
+	/*
+	 * Start with VCM disabled so each enabled state is paired with the
+	 * runtime PM reference acquired by ad7768_vcm_enable().
+	 */
+	ret = regmap_set_bits(st->regmap, AD7768_REG_GENERAL_CONFIG,
+			      AD7768_GEN_CONFIG_VCM_PD);
+	if (ret)
+		return ret;
+
+	st->vcm_rdev = devm_regulator_register(dev, &ad7768_vcm_desc, &config);
+	return PTR_ERR_OR_ZERO(st->vcm_rdev);
+}
+
+static const int ad7768_dec_rate[MAX_FREQ_PER_MODE] = {
+	32, 64, 128, 256, 512, 1024
+};
+
+static const int ad7768_mclk_div[3] = {
+	32, 8, 4
+};
+
+static const unsigned int ad7768_available_datalines[] = {
+	1, 2, 8,
+};
+
+static const unsigned int ad7768_4_available_datalines[] = {
+	1, 4,
+};
+
+static const u8 ad7768_chan_map[] = {
+	0, 1, 2, 3, 4, 5, 6, 7,
+};
+
+static const u8 ad7768_4_chan_map[] = {
+	0, 1, 4, 5,
+};
+
+static const char * const ad7768_supply_names[] = {
+	"avss", "avdd2", "iovdd", "ref1", "ref2",
+};
+
+static u8 ad7768_map_power_mode_to_regval(u8 x)
+{
+	return x ? (x + 1) : 0;
+}
+
+static int ad7768_set_power_mode(struct ad7768_state *st, unsigned int mode);
+
+static u8 ad7768_channel_mask(const struct ad7768_state *st, u8 ch)
+{
+	return BIT(st->chip_info->chan_map[ch]);
+}
+
+static u8 ad7768_all_channels_mask(const struct ad7768_state *st)
+{
+	u8 mask = 0;
+	unsigned int ch;
+
+	for (ch = 0; ch < st->chip_info->num_channels; ch++)
+		mask |= ad7768_channel_mask(st, ch);
+
+	return mask;
+}
+
+static unsigned int ad7768_offset_reg(const struct ad7768_state *st,
+				      unsigned int ch)
+{
+	return AD7768_REG_OFFSET(st->chip_info->chan_map[ch]);
+}
+
+static unsigned int ad7768_gain_reg(const struct ad7768_state *st,
+				    unsigned int ch)
+{
+	return AD7768_REG_GAIN(st->chip_info->chan_map[ch]);
+}
+
+static unsigned int ad7768_phase_reg(const struct ad7768_state *st,
+				     unsigned int ch)
+{
+	return AD7768_REG_PHASE(st->chip_info->chan_map[ch]);
+}
+
+static u8 ad7768_precharge_buf1_mask(const struct ad7768_state *st, u16 val)
+{
+	return val & GENMASK(st->chip_info->prebuf_split - 1, 0);
+}
+
+static u8 ad7768_precharge_buf2_mask(const struct ad7768_state *st, u16 val)
+{
+	return (val >> st->chip_info->prebuf_split) &
+	       GENMASK(st->chip_info->prebuf_split - 1, 0);
+}
+
+static int ad7768_regmap_read(void *context, const void *reg_buf,
+			      size_t reg_size, void *val_buf, size_t val_size)
+{
+	struct spi_device *spi = context;
+	struct ad7768_state *st = spi_get_drvdata(spi);
+	u8 *data_val = val_buf;
+	unsigned int reg;
+	int ret;
+	struct spi_transfer t[] = {
+		{
+			.tx_buf = &st->d16,
+			.len = 2,
+			.cs_change = 1,
+		}, {
+			/*
+			 * The second transfer clocks out the readback data, so
+			 * we must provide dummy TX bytes while receiving the
+			 * response. The device ignores MOSI in this phase, so
+			 * reuse st->d16 for both TX and RX.
+			 */
+			.tx_buf = &st->d16,
+			.rx_buf = &st->d16,
+			.len = 2,
+		},
+	};
+
+	reg = *(const u8 *)reg_buf;
+
+	st->d16 = cpu_to_be16(AD7768_SPI_READ_CMD |
+			      FIELD_PREP(AD7768_SPI_REG_MASK, reg));
+
+	ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t));
+	if (ret)
+		return ret;
+
+	*data_val = FIELD_GET(AD7768_SPI_DATA_MASK, be16_to_cpu(st->d16));
+
+	return ret;
+}
+
+static int ad7768_regmap_write(void *context, const void *data, size_t count)
+{
+	struct spi_device *spi = context;
+
+	return spi_write(spi, data, count);
+}
+
+static const struct regmap_bus ad7768_regmap_bus = {
+	.read = ad7768_regmap_read,
+	.write = ad7768_regmap_write,
+	.reg_format_endian_default = REGMAP_ENDIAN_BIG,
+	.val_format_endian_default = REGMAP_ENDIAN_BIG,
+};
+
+static bool ad7768_readable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case AD7768_REG_CH_STANDBY ... AD7768_REG_REV_ID:
+	case AD7768_REG_GPIO_CONTROL ... AD7768_REG_REFN_BUF:
+		return true;
+	case AD7768_REG_OFFSET(0) ... AD7768_REG_OFFSET(7) + 2:
+	case AD7768_REG_GAIN(0) ... AD7768_REG_GAIN(7) + 2:
+	case AD7768_REG_PHASE(0) ... AD7768_REG_PHASE(7):
+	case AD7768_REG_DIAGNOSTIC_RX ... AD7768_REG_CHOP_CTRL:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool ad7768_4_readable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case AD7768_REG_CH_STANDBY ... AD7768_REG_REV_ID:
+	case AD7768_REG_GPIO_CONTROL ... AD7768_REG_REFN_BUF:
+		return true;
+	case AD7768_4_REG_OFFSET(0) ... AD7768_4_REG_OFFSET(1) + 2:
+	case AD7768_4_REG_OFFSET(2) ... AD7768_4_REG_OFFSET(3) + 2:
+	case AD7768_4_REG_GAIN(0) ... AD7768_4_REG_GAIN(1) + 2:
+	case AD7768_4_REG_GAIN(2) ... AD7768_4_REG_GAIN(3) + 2:
+	case AD7768_4_REG_PHASE(0) ... AD7768_4_REG_PHASE(1):
+	case AD7768_4_REG_PHASE(2) ... AD7768_4_REG_PHASE(3):
+	case AD7768_REG_DIAGNOSTIC_RX ... AD7768_REG_CHOP_CTRL:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config ad7768_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = AD7768_REG_CHOP_CTRL,
+	.use_single_read = true,
+	.readable_reg = ad7768_readable_reg,
+};
+
+static const struct regmap_config ad7768_4_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = AD7768_REG_CHOP_CTRL,
+	.use_single_read = true,
+	.readable_reg = ad7768_4_readable_reg,
+};
+
+static unsigned int ad7768_get_calib_reg_base(struct ad7768_state *st,
+					      const struct iio_chan_spec *chan,
+					      bool is_gain)
+{
+	if (is_gain)
+		return ad7768_gain_reg(st, chan->address);
+
+	return ad7768_offset_reg(st, chan->address);
+}
+
+static int ad7768_read_calib_value(struct ad7768_state *st,
+				   unsigned int base_reg, unsigned int *val)
+{
+	u8 data[3];
+	int ret;
+
+	guard(mutex)(&st->lock);
+
+	ret = regmap_bulk_read(st->regmap, base_reg, data, ARRAY_SIZE(data));
+	if (ret)
+		return ret;
+
+	*val = (data[0] << 16) | (data[1] << 8) | data[2];
+
+	return 0;
+}
+
+static int ad7768_write_calib_value(struct ad7768_state *st,
+				    unsigned int base_reg, unsigned int val)
+{
+	int ret;
+
+	if (val > AD7768_CALIB_REG_MSK)
+		return -EINVAL;
+
+	guard(mutex)(&st->lock);
+
+	ret = regmap_write(st->regmap, base_reg,
+			   FIELD_GET(AD7768_CALIB_REG_MSB_MSK, val));
+	if (ret)
+		return ret;
+
+	ret = regmap_write(st->regmap, base_reg + 1,
+			   FIELD_GET(AD7768_CALIB_REG_MID_MSK, val));
+	if (ret)
+		return ret;
+
+	return regmap_write(st->regmap, base_reg + 2,
+			    FIELD_GET(AD7768_CALIB_REG_LSB_MSK, val));
+}
+
+static int ad7768_reg_access(struct iio_dev *indio_dev,
+			     unsigned int reg,
+			     unsigned int writeval,
+			     unsigned int *readval)
+{
+	struct ad7768_state *st = iio_priv(indio_dev);
+	int ret;
+
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(&st->spi->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	if (readval)
+		return regmap_read(st->regmap, reg, readval);
+
+	return regmap_write(st->regmap, reg, writeval);
+}
+
+static int ad7768_sync(struct ad7768_state *st)
+{
+	int ret;
+
+	ret = regmap_update_bits(st->regmap, AD7768_REG_DATA_CONTROL,
+				 AD7768_DATA_CONTROL_SPI_SYNC_MSK, 0);
+	if (ret)
+		return ret;
+
+	return regmap_update_bits(st->regmap, AD7768_REG_DATA_CONTROL,
+				  AD7768_DATA_CONTROL_SPI_SYNC_MSK,
+				  FIELD_PREP(AD7768_DATA_CONTROL_SPI_SYNC_MSK, 1));
+}
+
+static int ad7768_set_clk_divs(struct ad7768_state *st,
+			       unsigned int freq)
+{
+	unsigned int mclk, dclk, dclk_div, i;
+	struct ad7768_freq_config f_cfg = {};
+	unsigned int chan_per_doutx;
+
+	mclk = clk_get_rate(st->mclk);
+
+	chan_per_doutx = st->chip_info->num_channels / st->datalines;
+	if (!chan_per_doutx)
+		return -EINVAL;
+
+	for (i = 0; i < st->avail_freq[st->power_mode].n_freqs; i++) {
+		f_cfg = st->avail_freq[st->power_mode].freq_cfg[i];
+		if (freq == f_cfg.freq)
+			break;
+	}
+
+	if (i == st->avail_freq[st->power_mode].n_freqs)
+		return -EINVAL;
+
+	dclk = f_cfg.freq * AD7768_SAMPLE_SIZE * chan_per_doutx;
+	if (dclk > mclk)
+		return -EINVAL;
+
+	/* Set dclk_div to the nearest power of 2 less than the original value */
+	dclk_div = DIV_ROUND_CLOSEST_ULL(mclk, dclk);
+	if (dclk_div > AD7768_MAX_DCLK_DIV)
+		dclk_div = AD7768_MAX_DCLK_DIV;
+	else if (dclk_div > 0 && hweight32(dclk_div) != 1)
+		dclk_div = 1 << (fls(dclk_div) - 1);
+
+	return regmap_update_bits(st->regmap, AD7768_REG_INTERFACE_CFG,
+				  AD7768_INTERFACE_CFG_DCLK_DIV_MSK,
+				  AD7768_INTERFACE_CFG_DCLK_DIV_MODE(dclk_div));
+}
+
+static bool ad7768_freq_supported(const struct ad7768_state *st,
+				  unsigned int mode, unsigned int freq)
+{
+	unsigned int i;
+
+	for (i = 0; i < st->avail_freq[mode].n_freqs; i++) {
+		if (freq == st->avail_freq[mode].freq_cfg[i].freq)
+			return true;
+	}
+
+	return false;
+}
+
+static bool ad7768_freq_supported_in_any_mode(const struct ad7768_state *st,
+					      unsigned int freq)
+{
+	unsigned int mode;
+
+	for (mode = 0; mode < AD7768_NUM_POWER_MODES; mode++) {
+		if (ad7768_freq_supported(st, mode, freq))
+			return true;
+	}
+
+	return false;
+}
+
+static int ad7768_set_lowest_noise_mode(struct ad7768_state *st,
+					const unsigned long *scan_mask)
+{
+	unsigned int channel;
+	unsigned int mode;
+
+	/*
+	 * The output data rate ranges overlap between the power modes. At a
+	 * common ODR, the faster mode has lower noise, so prefer the fastest
+	 * mode that supports every enabled channel.
+	 */
+	for (mode = AD7768_NUM_POWER_MODES; mode-- > 0;) {
+		for (channel = 0; channel < st->chip_info->num_channels; channel++) {
+			if (test_bit(channel, scan_mask) &&
+			    !ad7768_freq_supported(st, mode, st->ch_freq[channel]))
+				break;
+		}
+
+		if (channel == st->chip_info->num_channels)
+			return ad7768_set_power_mode(st, mode);
+	}
+
+	return -EINVAL;
+}
+
+static int ad7768_set_mode_decimation(struct ad7768_state *st,
+				      unsigned int freq, unsigned int mode)
+{
+	struct ad7768_freq_config f_cfg = {};
+	unsigned int i;
+
+	for (i = 0; i < st->avail_freq[st->power_mode].n_freqs; i++) {
+		f_cfg = st->avail_freq[st->power_mode].freq_cfg[i];
+		if (freq == f_cfg.freq)
+			break;
+	}
+
+	if (i == st->avail_freq[st->power_mode].n_freqs)
+		return -EINVAL;
+
+	return regmap_update_bits(st->regmap, AD7768_REG_CH_MODE(mode),
+				  AD7768_CH_MODE_DEC_RATE_MSK,
+				  AD7768_CH_MODE_DEC_RATE_MODE(f_cfg.dec_rate));
+}
+
+static int ad7768_set_sampling_freq(struct iio_dev *indio_dev,
+				    unsigned int freq, unsigned int ch)
+{
+	struct ad7768_state *st = iio_priv(indio_dev);
+
+	if (!freq)
+		return -EINVAL;
+
+	if (!ad7768_freq_supported_in_any_mode(st, freq))
+		return -EINVAL;
+
+	guard(mutex)(&st->lock);
+	st->ch_freq[ch] = freq;
+
+	return 0;
+}
+
+static int ad7768_get_freq_cfg(struct ad7768_state *st, unsigned int freq,
+			       struct ad7768_freq_config *f_cfg)
+{
+	unsigned int i;
+
+	for (i = 0; i < st->avail_freq[st->power_mode].n_freqs; i++) {
+		*f_cfg = st->avail_freq[st->power_mode].freq_cfg[i];
+		if (freq == f_cfg->freq)
+			return 0;
+	}
+
+	return -EINVAL;
+}
+
+static void ad7768_filter_wait(const unsigned int *mode_freq,
+			       const enum ad7768_filter_type *mode_filter,
+			       const bool *mode_used)
+{
+	unsigned long t_settle_us = 0;
+	unsigned int mode;
+
+	for (mode = 0; mode < AD7768_NUM_CHANNEL_MODES; mode++) {
+		unsigned long t_mode_us;
+		unsigned int settling_samples;
+
+		if (!mode_used[mode] || !mode_freq[mode])
+			continue;
+
+		if (mode_filter[mode] == AD7768_FILTER_TYPE_SINC5)
+			settling_samples = AD7768_SINC5_SETTLING_SAMPLES;
+		else
+			settling_samples = AD7768_WIDEBAND_SETTLING_SAMPLES;
+
+		t_mode_us = DIV_ROUND_UP_ULL((u64)settling_samples *
+					     USEC_PER_SEC,
+					     mode_freq[mode]);
+		t_settle_us = max(t_settle_us, t_mode_us);
+	}
+
+	if (t_settle_us)
+		fsleep(t_settle_us);
+}
+
+static int ad7768_get_convdelay_params(struct ad7768_state *st, unsigned int ch,
+				       struct ad7768_convdelay_params *params)
+{
+	struct ad7768_freq_config f_cfg;
+	unsigned int dec_rate;
+	unsigned int mult;
+	u64 mclk;
+	int ret;
+
+	ret = ad7768_get_freq_cfg(st, st->ch_freq[ch], &f_cfg);
+	if (ret)
+		return ret;
+
+	dec_rate = ad7768_dec_rate[f_cfg.dec_rate];
+	switch (dec_rate) {
+	case 32:
+		params->shift = 3;
+		params->max_raw = 31;
+		mult = 1;
+		break;
+	case 64:
+		params->shift = 2;
+		params->max_raw = 63;
+		mult = 1;
+		break;
+	case 128:
+		params->shift = 1;
+		params->max_raw = 127;
+		mult = 1;
+		break;
+	case 256:
+		params->shift = 0;
+		params->max_raw = 255;
+		mult = 1;
+		break;
+	case 512:
+		params->shift = 0;
+		params->max_raw = 255;
+		mult = 2;
+		break;
+	case 1024:
+		params->shift = 0;
+		params->max_raw = 255;
+		mult = 4;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mclk = clk_get_rate(st->mclk);
+	if (!mclk)
+		return -EINVAL;
+
+	params->step_ps = DIV_ROUND_CLOSEST_ULL((u64)mult *
+						AD7768_PICO_PER_SEC *
+						ad7768_mclk_div[st->power_mode],
+						mclk);
+
+	return 0;
+}
+
+static int ad7768_set_channel_convdelay(struct ad7768_state *st,
+					unsigned int ch)
+{
+	struct ad7768_convdelay_params params;
+	u64 delay_ps = st->ch_convdelay_ps[ch];
+	u64 max_delay_ps;
+	u64 raw;
+	int ret;
+
+	ret = ad7768_get_convdelay_params(st, ch, &params);
+	if (ret)
+		return ret;
+
+	max_delay_ps = (u64)params.max_raw * params.step_ps;
+	if (delay_ps > max_delay_ps)
+		return -EINVAL;
+
+	raw = DIV_ROUND_CLOSEST_ULL(delay_ps, params.step_ps);
+	if (raw > params.max_raw)
+		return -EINVAL;
+
+	return regmap_write(st->regmap, ad7768_phase_reg(st, ch),
+			    raw << params.shift);
+}
+
+static int ad7768_find_matching_mode(const bool *mode_used,
+				     const unsigned int *mode_freq,
+				     const enum ad7768_filter_type *mode_filter,
+				     unsigned int freq,
+				     enum ad7768_filter_type filter)
+{
+	unsigned int mode;
+
+	for (mode = 0; mode < AD7768_NUM_CHANNEL_MODES; mode++) {
+		if (!mode_used[mode] ||
+		    (mode_freq[mode] == freq && mode_filter[mode] == filter))
+			return mode;
+	}
+
+	return -EINVAL;
+}
+
+static int ad7768_apply_channel_modes(struct iio_dev *indio_dev,
+				      const unsigned long *scan_mask)
+{
+	struct ad7768_state *st = iio_priv(indio_dev);
+	unsigned int mode_freq[AD7768_NUM_CHANNEL_MODES];
+	enum ad7768_filter_type mode_filter[AD7768_NUM_CHANNEL_MODES];
+	bool mode_used[AD7768_NUM_CHANNEL_MODES] = { };
+	unsigned int channel_mask;
+	unsigned int standby_mask;
+	unsigned int max_freq = 0;
+	unsigned int c;
+	int mode, ret;
+
+	guard(mutex)(&st->lock);
+
+	ret = ad7768_set_lowest_noise_mode(st, scan_mask);
+	if (ret == -EINVAL)
+		return dev_err_probe(&st->spi->dev, ret,
+				     "No power mode supports all enabled channel frequencies\n");
+	if (ret)
+		return ret;
+
+	channel_mask = ad7768_all_channels_mask(st);
+	standby_mask = channel_mask;
+
+	for (c = 0; c < st->chip_info->num_channels; c++) {
+		unsigned int mask;
+
+		if (!test_bit(c, scan_mask))
+			continue;
+
+		standby_mask &= ~ad7768_channel_mask(st, c);
+
+		mode = ad7768_find_matching_mode(mode_used, mode_freq,
+						 mode_filter, st->ch_freq[c],
+						 st->ch_filter[c]);
+		if (mode < 0)
+			return dev_err_probe(&st->spi->dev, -EINVAL,
+				"Enabled channels require more than %d mode profiles\n",
+				AD7768_NUM_CHANNEL_MODES);
+
+		mode_freq[mode] = st->ch_freq[c];
+		mode_filter[mode] = st->ch_filter[c];
+		mode_used[mode] = true;
+		st->chn_mode[c] = mode;
+
+		mask = ad7768_channel_mask(st, c);
+		ret = regmap_update_bits(st->regmap, AD7768_REG_CH_MODE_SEL,
+					 mask, mode ? mask : 0);
+		if (ret)
+			return ret;
+	}
+
+	ret = regmap_update_bits(st->regmap, AD7768_REG_CH_STANDBY,
+				 channel_mask, standby_mask);
+	if (ret)
+		return ret;
+
+	for (mode = 0; mode < AD7768_NUM_CHANNEL_MODES; mode++) {
+		if (!mode_used[mode])
+			continue;
+
+		ret = ad7768_set_mode_decimation(st, mode_freq[mode], mode);
+		if (ret)
+			return ret;
+
+		ret = regmap_update_bits(st->regmap, AD7768_REG_CH_MODE(mode),
+					 AD7768_CH_MODE_FILTER_TYPE_MSK,
+					 AD7768_CH_MODE_FILTER_TYPE_MODE(mode_filter[mode]));
+		if (ret)
+			return ret;
+
+		max_freq = max(max_freq, mode_freq[mode]);
+	}
+
+	for (c = 0; c < st->chip_info->num_channels; c++) {
+		if (!test_bit(c, scan_mask))
+			continue;
+
+		ret = ad7768_set_channel_convdelay(st, c);
+		if (ret == -EINVAL)
+			return dev_err_probe(&st->spi->dev, ret,
+					     "Invalid conversion delay for channel %u\n",
+					     c);
+		if (ret)
+			return ret;
+	}
+
+	ret = ad7768_set_clk_divs(st, max_freq);
+	if (ret)
+		return ret;
+
+	ret = ad7768_sync(st);
+	if (ret)
+		return ret;
+
+	/* Apply a filter settling time (Datasheet table 35 and 36) */
+	ad7768_filter_wait(mode_freq, mode_filter, mode_used);
+
+	return 0;
+}
+
+static int ad7768_set_power_mode(struct ad7768_state *st, unsigned int mode)
+{
+	unsigned int regval;
+	int ret;
+
+	if (mode >= AD7768_NUM_POWER_MODES)
+		return -EINVAL;
+
+	regval = ad7768_map_power_mode_to_regval(mode);
+	ret = regmap_update_bits(st->regmap, AD7768_REG_POWER_MODE,
+				 AD7768_POWER_MODE_POWER_MODE_MSK,
+				 AD7768_POWER_MODE_POWER_MODE(regval));
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(st->regmap, AD7768_REG_POWER_MODE,
+				 AD7768_POWER_MODE_MCLK_DIV_MSK,
+				 FIELD_PREP(AD7768_POWER_MODE_MCLK_DIV_MSK, regval));
+	if (ret)
+		return ret;
+
+	ret = ad7768_sync(st);
+	if (ret)
+		return ret;
+
+	st->power_mode = mode;
+
+	return 0;
+}
+
+static int ad7768_read_raw(struct iio_dev *indio_dev,
+			   const struct iio_chan_spec *chan,
+			   int *val, int *val2, long info)
+{
+	struct ad7768_state *st = iio_priv(indio_dev);
+	unsigned int base_reg;
+	unsigned int calib;
+	int ret;
+
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(&st->spi->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	switch (info) {
+	case IIO_CHAN_INFO_SAMP_FREQ: {
+		guard(mutex)(&st->lock);
+		*val = st->ch_freq[chan->channel];
+		return IIO_VAL_INT;
+	}
+
+	case IIO_CHAN_INFO_CALIBBIAS:
+		base_reg = ad7768_get_calib_reg_base(st, chan, false);
+		ret = ad7768_read_calib_value(st, base_reg, &calib);
+		if (ret)
+			return ret;
+
+		*val = calib;
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_CALIBSCALE:
+		base_reg = ad7768_get_calib_reg_base(st, chan, true);
+		ret = ad7768_read_calib_value(st, base_reg, &calib);
+		if (ret)
+			return ret;
+
+		*val = calib;
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_CONVDELAY: {
+		guard(mutex)(&st->lock);
+		iio_val_s64_decompose(st->ch_convdelay_ps[chan->channel],
+				      val, val2);
+
+		return IIO_VAL_DECIMAL64_PICO;
+	}
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ad7768_write_raw_get_fmt(struct iio_dev *indio_dev,
+				    struct iio_chan_spec const *chan, long info)
+{
+	switch (info) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+	case IIO_CHAN_INFO_CALIBBIAS:
+	case IIO_CHAN_INFO_CALIBSCALE:
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_CONVDELAY:
+		return IIO_VAL_DECIMAL64_PICO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ad7768_write_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int val, int val2, long info)
+{
+	struct ad7768_state *st = iio_priv(indio_dev);
+	s64 delay_ps;
+	unsigned int base_reg;
+	int ret;
+
+	IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+	if (IIO_DEV_ACQUIRE_FAILED(claim))
+		return -EBUSY;
+
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(&st->spi->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	switch (info) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		return ad7768_set_sampling_freq(indio_dev, val, chan->channel);
+
+	case IIO_CHAN_INFO_CALIBBIAS:
+		if (val < 0 || val > AD7768_CALIB_REG_MSK)
+			return -EINVAL;
+
+		base_reg = ad7768_get_calib_reg_base(st, chan, false);
+		return ad7768_write_calib_value(st, base_reg, val);
+
+	case IIO_CHAN_INFO_CALIBSCALE:
+		if (val < 0 || val > AD7768_CALIB_REG_MSK)
+			return -EINVAL;
+
+		base_reg = ad7768_get_calib_reg_base(st, chan, true);
+		return ad7768_write_calib_value(st, base_reg, val);
+
+	case IIO_CHAN_INFO_CONVDELAY: {
+		delay_ps = iio_val_s64_compose(val, val2);
+		if (delay_ps < 0)
+			return -EINVAL;
+
+		guard(mutex)(&st->lock);
+		st->ch_convdelay_ps[chan->channel] = delay_ps;
+		return 0;
+	}
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ad7768_read_avail(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     const int **vals, int *type, int *length,
+			     long info)
+{
+	struct ad7768_state *st = iio_priv(indio_dev);
+
+	if (info != IIO_CHAN_INFO_SAMP_FREQ)
+		return -EINVAL;
+
+	*vals = st->freqs;
+	*type = IIO_VAL_INT;
+	*length = st->n_freqs;
+
+	return IIO_AVAIL_LIST;
+}
+
+static int ad7768_update_scan_mode(struct iio_dev *indio_dev,
+				   const unsigned long *scan_mask)
+{
+	struct ad7768_state *st = iio_priv(indio_dev);
+	unsigned int c;
+	int ret;
+
+	ret = ad7768_apply_channel_modes(indio_dev, scan_mask);
+	if (ret)
+		return ret;
+
+	for (c = 0; c < st->chip_info->num_channels; c++) {
+		if (test_bit(c, scan_mask))
+			ret = iio_backend_chan_enable(st->back, c);
+		else
+			ret = iio_backend_chan_disable(st->back, c);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct ad7768_chip_info ad7768_chip_info = {
+	.name = "ad7768",
+	.num_channels = 8,
+	.regmap_config = &ad7768_regmap_config,
+	.available_datalines = ad7768_available_datalines,
+	.num_datalines = ARRAY_SIZE(ad7768_available_datalines),
+	.chan_map = ad7768_chan_map,
+	.prebuf_split = 8,
+};
+
+static const struct ad7768_chip_info ad7768_4_chip_info = {
+	.name = "ad7768-4",
+	.num_channels = 4,
+	.regmap_config = &ad7768_4_regmap_config,
+	.available_datalines = ad7768_4_available_datalines,
+	.num_datalines = ARRAY_SIZE(ad7768_4_available_datalines),
+	.chan_map = ad7768_4_chan_map,
+	.prebuf_split = 4,
+};
+
+static int ad7768_buffer_preenable(struct iio_dev *indio_dev)
+{
+	struct ad7768_state *st = iio_priv(indio_dev);
+
+	return pm_runtime_resume_and_get(&st->spi->dev);
+}
+
+static int ad7768_buffer_postdisable(struct iio_dev *indio_dev)
+{
+	struct ad7768_state *st = iio_priv(indio_dev);
+
+	pm_runtime_put_autosuspend(&st->spi->dev);
+	return 0;
+}
+
+static const struct iio_buffer_setup_ops ad7768_buffer_ops = {
+	.preenable = ad7768_buffer_preenable,
+	.postdisable = ad7768_buffer_postdisable,
+};
+
+static const struct iio_info ad7768_info = {
+	.debugfs_reg_access = ad7768_reg_access,
+	.read_raw = ad7768_read_raw,
+	.write_raw_get_fmt = ad7768_write_raw_get_fmt,
+	.write_raw = ad7768_write_raw,
+	.read_avail = ad7768_read_avail,
+	.update_scan_mode = ad7768_update_scan_mode,
+};
+
+static void ad7768_set_available_sampl_freq(struct ad7768_state *st)
+{
+	struct ad7768_avail_freq *avail_freq;
+	unsigned int mclk = clk_get_rate(st->mclk);
+	unsigned int mode;
+
+	for (mode = 0; mode < AD7768_NUM_POWER_MODES; mode++) {
+		avail_freq = &st->avail_freq[mode];
+		for (unsigned int dec = ARRAY_SIZE(ad7768_dec_rate); dec > 0; dec--) {
+			struct ad7768_freq_config freq_cfg;
+
+			freq_cfg.dec_rate = dec - 1;
+			freq_cfg.freq = mclk / (ad7768_dec_rate[dec - 1] *
+					ad7768_mclk_div[mode]);
+			avail_freq->freqs[avail_freq->n_freqs] = freq_cfg.freq;
+			avail_freq->freq_cfg[avail_freq->n_freqs++] = freq_cfg;
+		}
+	}
+
+	if (st->datalines == 1 &&
+	    st->chip_info->num_channels == AD7768_MAX_CHANNEL)
+		st->avail_freq[AD7768_FAST_MODE].n_freqs--;
+
+	for (mode = 0; mode < AD7768_NUM_POWER_MODES; mode++) {
+		avail_freq = &st->avail_freq[mode];
+		for (unsigned int i = 0; i < avail_freq->n_freqs; i++) {
+			unsigned int freq = avail_freq->freqs[i];
+
+			if (st->n_freqs && st->freqs[st->n_freqs - 1] >= freq)
+				continue;
+
+			st->freqs[st->n_freqs++] = freq;
+		}
+	}
+}
+
+static int ad7768_gpio_adev_init(struct ad7768_state *st)
+{
+	struct device *dev = &st->spi->dev;
+	struct auxiliary_device *adev;
+	int id;
+
+	if (!device_property_read_bool(dev, "gpio-controller"))
+		return 0;
+
+	/* Use the SPI bus number and chip select to derive a stable per-device ID. */
+	id = (st->spi->controller->bus_num << 8) | spi_get_chipselect(st->spi, 0);
+	adev = __devm_auxiliary_device_create(dev, KBUILD_MODNAME, "gpio",
+					      NULL, id);
+	if (!adev)
+		return dev_err_probe(dev, -ENODEV,
+				     "Failed to create GPIO auxiliary device\n");
+
+	return 0;
+}
+
+static int ad7768_set_filter_mode(struct iio_dev *indio_dev,
+				  const struct iio_chan_spec *chan,
+				  unsigned int mode)
+{
+	struct ad7768_state *st = iio_priv(indio_dev);
+
+	IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+	if (IIO_DEV_ACQUIRE_FAILED(claim))
+		return -EBUSY;
+
+	guard(mutex)(&st->lock);
+	st->ch_filter[chan->channel] = mode;
+	return 0;
+}
+
+static int ad7768_get_filter_mode(struct iio_dev *indio_dev,
+				  const struct iio_chan_spec *chan)
+{
+	struct ad7768_state *st = iio_priv(indio_dev);
+
+	guard(mutex)(&st->lock);
+	return st->ch_filter[chan->channel];
+}
+
+static int ad7768_configure_precharge_buffers(struct iio_dev *indio_dev,
+					      struct ad7768_precharge_config *precharge_cfg)
+{
+	struct ad7768_state *st = iio_priv(indio_dev);
+	u8 prebuf1_val, prebuf2_val;
+	u16 prebuf_mask = 0;
+	u8 refbufp_val = 0;
+	u8 refbufn_val = 0;
+	int ret;
+	u8 ch;
+
+	for (ch = 0; ch < indio_dev->num_channels; ch++) {
+		u8 channel = indio_dev->channels[ch].channel;
+
+		if (precharge_cfg[channel].prebufp_en)
+			prebuf_mask |= AD7768_PREBUF_POS_EN(channel);
+
+		if (precharge_cfg[channel].prebufn_en)
+			prebuf_mask |= AD7768_PREBUF_NEG_EN(channel);
+
+		if (precharge_cfg[channel].refbufp)
+			refbufp_val |= ad7768_channel_mask(st, channel);
+
+		if (precharge_cfg[channel].refbufn)
+			refbufn_val |= ad7768_channel_mask(st, channel);
+	}
+
+	prebuf1_val = ad7768_precharge_buf1_mask(st, ~prebuf_mask);
+	prebuf2_val = ad7768_precharge_buf2_mask(st, ~prebuf_mask);
+
+	ret = regmap_write(st->regmap, AD7768_REG_PRECHARGE_BUF1, prebuf1_val);
+	if (ret)
+		return ret;
+
+	ret = regmap_write(st->regmap, AD7768_REG_PRECHARGE_BUF2, prebuf2_val);
+	if (ret)
+		return ret;
+
+	ret = regmap_write(st->regmap, AD7768_REG_REFP_BUF, refbufp_val);
+	if (ret)
+		return ret;
+
+	return regmap_write(st->regmap, AD7768_REG_REFN_BUF, refbufn_val);
+}
+
+static const char *const ad7768_filter_types[] = {
+	[AD7768_FILTER_TYPE_WIDEBAND] = "wideband",
+	[AD7768_FILTER_TYPE_SINC5] = "sinc5",
+};
+
+static const struct iio_enum ad7768_filter_types_enum = {
+	.items = ad7768_filter_types,
+	.num_items = ARRAY_SIZE(ad7768_filter_types),
+	.set = ad7768_set_filter_mode,
+	.get = ad7768_get_filter_mode,
+};
+
+static struct iio_chan_spec_ext_info ad7768_ext_info[] = {
+	IIO_ENUM("filter_type", IIO_SEPARATE,
+		 &ad7768_filter_types_enum),
+	IIO_ENUM_AVAILABLE("filter_type", IIO_SEPARATE, &ad7768_filter_types_enum),
+	{}
+};
+
+static int ad7768_parse_config(struct iio_dev *indio_dev,
+			       struct device *dev)
+{
+	struct ad7768_state *st = iio_priv(indio_dev);
+	const struct ad7768_avail_freq *avail_freq;
+	const unsigned int *available_datalines;
+	struct ad7768_precharge_config precharge_cfg[AD7768_MAX_CHANNEL] = { };
+	struct iio_chan_spec *chan;
+	unsigned int num_channels;
+	unsigned int channel;
+	unsigned int i, len;
+	unsigned int default_freq;
+	int chan_idx = 0;
+	int ret;
+
+	num_channels = 0;
+	device_for_each_child_node_scoped(dev, child) {
+		if (!fwnode_property_present(child, "reg"))
+			continue;
+
+		num_channels++;
+	}
+
+	if (!num_channels || num_channels > st->chip_info->num_channels)
+		return dev_err_probe(dev, -EINVAL, "Invalid number of channels\n");
+
+	chan = devm_kcalloc(indio_dev->dev.parent, num_channels,
+			    sizeof(*chan), GFP_KERNEL);
+	if (!chan)
+		return -ENOMEM;
+
+	indio_dev->channels = chan;
+	indio_dev->num_channels = num_channels;
+
+	ret = regmap_write(st->regmap, AD7768_REG_CH_STANDBY,
+			   ad7768_all_channels_mask(st));
+	if (ret)
+		return ret;
+
+	device_for_each_child_node_scoped(dev, child) {
+		if (!fwnode_property_present(child, "reg"))
+			continue;
+
+		ret = fwnode_property_read_u32(child, "reg", &channel);
+		if (ret)
+			return dev_err_probe(dev, ret,
+					     "Failed to parse reg property of %pfwP\n",
+					     child);
+
+		if (channel >= st->chip_info->num_channels)
+			return dev_err_probe(dev, -EINVAL,
+					     "Invalid channel number %d from firmware\n",
+					     channel);
+
+		ret = regmap_update_bits(st->regmap, AD7768_REG_CH_STANDBY,
+					 ad7768_channel_mask(st, channel), 0);
+		if (ret)
+			return ret;
+
+		if (fwnode_property_read_bool(child, "adi,prechargebuf-pos-enable"))
+			precharge_cfg[channel].prebufp_en = true;
+
+		if (fwnode_property_read_bool(child, "adi,prechargebuf-neg-enable"))
+			precharge_cfg[channel].prebufn_en = true;
+
+		if (fwnode_property_read_bool(child, "adi,refbuf-pos-enable"))
+			precharge_cfg[channel].refbufp = true;
+
+		if (fwnode_property_read_bool(child, "adi,refbuf-neg-enable"))
+			precharge_cfg[channel].refbufn = true;
+
+		chan[chan_idx] = (struct iio_chan_spec) {
+			.type = IIO_VOLTAGE,
+			.info_mask_separate = BIT(IIO_CHAN_INFO_CALIBBIAS) |
+					      BIT(IIO_CHAN_INFO_CALIBSCALE) |
+					      BIT(IIO_CHAN_INFO_CONVDELAY) |
+					      BIT(IIO_CHAN_INFO_SAMP_FREQ),
+			.info_mask_separate_available =
+				BIT(IIO_CHAN_INFO_SAMP_FREQ),
+			.indexed = 1,
+			.address = channel,
+			.channel = channel,
+			.scan_index = channel,
+			.scan_type = {
+				.sign = 's',
+				.realbits = 24,
+				.storagebits = 32,
+			},
+			.ext_info = ad7768_ext_info,
+		};
+		chan_idx++;
+	}
+
+	ret = ad7768_configure_precharge_buffers(indio_dev, precharge_cfg);
+	if (ret)
+		return ret;
+
+	st->datalines = st->chip_info->available_datalines[st->chip_info->num_datalines - 1];
+	ret = device_property_read_u32(dev, "adi,data-lines-number",
+				       &st->datalines);
+	if (ret && ret != -EINVAL)
+		return dev_err_probe(dev, ret,
+				     "Invalid \"adi,data-lines-number\" property\n");
+
+	ad7768_set_available_sampl_freq(st);
+
+	/* Start in fast mode; capture setup may select another compatible mode. */
+	scoped_guard(mutex, &st->lock) {
+		ret = ad7768_set_power_mode(st, AD7768_FAST_MODE);
+	}
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to set power mode\n");
+
+	avail_freq = &st->avail_freq[AD7768_FAST_MODE];
+	default_freq = avail_freq->freq_cfg[avail_freq->n_freqs - 1].freq;
+	for (i = 0; i < st->chip_info->num_channels; i++) {
+		st->ch_freq[i] = default_freq;
+		st->ch_filter[i] = AD7768_FILTER_TYPE_WIDEBAND;
+	}
+
+	available_datalines = st->chip_info->available_datalines;
+	len = st->chip_info->num_datalines;
+
+	for (i = 0; i < len; i++) {
+		if (available_datalines[i] == st->datalines)
+			break;
+	}
+
+	if (i == len)
+		return dev_err_probe(dev, -EINVAL,
+				     "Invalid data-lines-number %d for %s\n",
+				     st->datalines, st->chip_info->name);
+
+	return 0;
+}
+
+static int ad7768_reset(struct ad7768_state *st)
+{
+	struct reset_control *reset_ctrl;
+	unsigned long reset_low_us;
+	unsigned long mclk;
+	int ret;
+
+	reset_ctrl = devm_reset_control_get_optional_exclusive(&st->spi->dev, NULL);
+	if (IS_ERR(reset_ctrl))
+		return PTR_ERR(reset_ctrl);
+
+	if (reset_ctrl) {
+		mclk = clk_get_rate(st->mclk);
+		if (!mclk)
+			return -EINVAL;
+
+		/* Minimum RESET low pulse width: 2 x tMCLK (datasheet Table 1). */
+		reset_low_us = DIV_ROUND_UP_ULL(2ULL * USEC_PER_SEC, mclk);
+
+		ret = reset_control_assert(reset_ctrl);
+		if (ret)
+			return ret;
+
+		fsleep(max_t(unsigned long, 1, reset_low_us));
+
+		ret = reset_control_deassert(reset_ctrl);
+		if (ret)
+			return ret;
+	} else {
+		ret = regmap_write(st->regmap, AD7768_REG_DATA_CONTROL,
+				   AD7768_DATA_CONTROL_SPI_RESET_1);
+		if (ret)
+			return ret;
+
+		ret = regmap_write(st->regmap, AD7768_REG_DATA_CONTROL,
+				   AD7768_DATA_CONTROL_SPI_RESET_2);
+		if (ret)
+			return ret;
+	}
+
+	/* ADC start-up time after reset: 1.66 ms max (datasheet Table 1) */
+	fsleep(2000);
+
+	return 0;
+}
+
+static int ad7768_probe(struct spi_device *spi)
+{
+	struct device *dev = &spi->dev;
+	unsigned int spi_readback, rev_id;
+	struct iio_dev *indio_dev;
+	struct ad7768_state *st;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	st = iio_priv(indio_dev);
+	st->spi = spi;
+	spi_set_drvdata(spi, st);
+
+	ret = devm_mutex_init(dev, &st->lock);
+	if (ret)
+		return ret;
+
+	st->chip_info = spi_get_device_match_data(spi);
+
+	ret = devm_regulator_get_enable_read_voltage(dev, "avdd1");
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to enable AVDD1 supply\n");
+
+	st->avdd1_uv = ret;
+
+	ret = devm_regulator_bulk_get_enable(dev,
+					     ARRAY_SIZE(ad7768_supply_names),
+					     ad7768_supply_names);
+	if (ret)
+		return ret;
+
+	st->mclk = devm_clk_get_enabled(dev, NULL);
+	if (IS_ERR(st->mclk))
+		return PTR_ERR(st->mclk);
+
+	st->regmap = devm_regmap_init(dev, &ad7768_regmap_bus, spi,
+				      st->chip_info->regmap_config);
+	if (IS_ERR(st->regmap))
+		return PTR_ERR(st->regmap);
+
+	ret = regmap_attach_dev(dev, st->regmap, st->chip_info->regmap_config);
+	if (ret)
+		return ret;
+
+	ret = ad7768_reset(st);
+	if (ret)
+		return ret;
+
+	/* Dummy SPI register read to discard the Reset response from the chip */
+	ret = regmap_read(st->regmap, AD7768_REG_REV_ID, &spi_readback);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(st->regmap, AD7768_REG_REV_ID, &rev_id);
+	if (ret)
+		return ret;
+
+	if (rev_id != AD7768_REV_ID_VAL)
+		dev_warn(dev, "Unexpected revision ID 0x%02x\n", rev_id);
+
+	ret = ad7768_parse_config(indio_dev, dev);
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(st->regmap, AD7768_REG_INTERFACE_CFG,
+				 AD7768_INTERFACE_CFG_CRC_SELECT_MSK,
+				 AD7768_INTERFACE_CFG_CRC_SELECT);
+	if (ret)
+		return ret;
+
+	indio_dev->name = st->chip_info->name;
+	indio_dev->info = &ad7768_info;
+
+	st->back = devm_iio_backend_get(dev, NULL);
+	if (IS_ERR(st->back))
+		return PTR_ERR(st->back);
+
+	ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
+	if (ret)
+		return ret;
+
+	ret = iio_backend_num_lanes_set(st->back, st->datalines);
+	if (ret)
+		return ret;
+
+	ret = iio_backend_crc_enable(st->back);
+	if (ret)
+		return ret;
+
+	ret = devm_iio_backend_enable(dev, st->back);
+	if (ret)
+		return ret;
+
+	pm_runtime_set_autosuspend_delay(dev, 2000);
+	pm_runtime_use_autosuspend(dev);
+	ret = devm_pm_runtime_set_active_enabled(dev);
+	if (ret)
+		return ret;
+
+	ret = ad7768_register_vcm_regulator(dev, st);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to register VCM regulator\n");
+
+	indio_dev->setup_ops = &ad7768_buffer_ops;
+
+	ret = ad7768_gpio_adev_init(st);
+	if (ret)
+		return ret;
+
+	ret = devm_iio_device_register(dev, indio_dev);
+	if (ret)
+		return ret;
+
+	ret = pm_request_autosuspend(dev);
+	if (ret < 0 && ret != -EAGAIN)
+		return dev_err_probe(dev, ret,
+				     "Failed to request initial autosuspend\n");
+
+	return 0;
+}
+
+static int ad7768_runtime_suspend(struct device *dev)
+{
+	struct ad7768_state *st = dev_get_drvdata(dev);
+
+	return regmap_set_bits(st->regmap, AD7768_REG_POWER_MODE,
+			       AD7768_SLEEP_MODE_MSK);
+}
+
+static int ad7768_runtime_resume(struct device *dev)
+{
+	struct ad7768_state *st = dev_get_drvdata(dev);
+	int ret;
+
+	ret = regmap_clear_bits(st->regmap, AD7768_REG_POWER_MODE,
+				AD7768_SLEEP_MODE_MSK);
+	if (ret)
+		return ret;
+
+	/* Empirically determined delay to re-enable ADC and digital clocks.*/
+	fsleep(20000);
+
+	return 0;
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(ad7768_pm_ops, ad7768_runtime_suspend,
+	ad7768_runtime_resume, NULL);
+
+static const struct of_device_id ad7768_of_match[]  = {
+	{ .compatible = "adi,ad7768", .data = &ad7768_chip_info },
+	{ .compatible = "adi,ad7768-4", .data = &ad7768_4_chip_info },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ad7768_of_match);
+
+static const struct spi_device_id ad7768_spi_id[] = {
+	{"ad7768", (kernel_ulong_t)&ad7768_chip_info},
+	{"ad7768-4", (kernel_ulong_t)&ad7768_4_chip_info},
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, ad7768_spi_id);
+
+static struct spi_driver ad7768_driver = {
+	.probe = ad7768_probe,
+	.driver = {
+		.name = "ad7768",
+		.of_match_table = ad7768_of_match,
+		.pm = pm_ptr(&ad7768_pm_ops),
+	},
+	.id_table = ad7768_spi_id,
+};
+module_spi_driver(ad7768_driver);
+
+MODULE_AUTHOR("Stefan Popa <[email protected]>");
+MODULE_AUTHOR("Janani Sunil <[email protected]>");
+MODULE_DESCRIPTION("Analog Devices AD7768 ADC driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_BACKEND");

-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.