162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5625, AD5625R,
462306a36Sopenharmony_ci * AD5627, AD5627R, AD5628, AD5629R, AD5645R, AD5647R, AD5648, AD5665, AD5665R,
562306a36Sopenharmony_ci * AD5666, AD5667, AD5667R, AD5668, AD5669R, LTC2606, LTC2607, LTC2609, LTC2616,
662306a36Sopenharmony_ci * LTC2617, LTC2619, LTC2626, LTC2627, LTC2629, LTC2631, LTC2633, LTC2635
762306a36Sopenharmony_ci * Digital to analog converters driver
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Copyright 2011 Analog Devices Inc.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/device.h>
1362306a36Sopenharmony_ci#include <linux/err.h>
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci#include <linux/kernel.h>
1662306a36Sopenharmony_ci#include <linux/spi/spi.h>
1762306a36Sopenharmony_ci#include <linux/i2c.h>
1862306a36Sopenharmony_ci#include <linux/slab.h>
1962306a36Sopenharmony_ci#include <linux/sysfs.h>
2062306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
2162306a36Sopenharmony_ci#include <asm/unaligned.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#include <linux/iio/iio.h>
2462306a36Sopenharmony_ci#include <linux/iio/sysfs.h>
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define AD5064_MAX_DAC_CHANNELS			8
2762306a36Sopenharmony_ci#define AD5064_MAX_VREFS			4
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define AD5064_ADDR(x)				((x) << 20)
3062306a36Sopenharmony_ci#define AD5064_CMD(x)				((x) << 24)
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#define AD5064_ADDR_ALL_DAC			0xF
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define AD5064_CMD_WRITE_INPUT_N		0x0
3562306a36Sopenharmony_ci#define AD5064_CMD_UPDATE_DAC_N			0x1
3662306a36Sopenharmony_ci#define AD5064_CMD_WRITE_INPUT_N_UPDATE_ALL	0x2
3762306a36Sopenharmony_ci#define AD5064_CMD_WRITE_INPUT_N_UPDATE_N	0x3
3862306a36Sopenharmony_ci#define AD5064_CMD_POWERDOWN_DAC		0x4
3962306a36Sopenharmony_ci#define AD5064_CMD_CLEAR			0x5
4062306a36Sopenharmony_ci#define AD5064_CMD_LDAC_MASK			0x6
4162306a36Sopenharmony_ci#define AD5064_CMD_RESET			0x7
4262306a36Sopenharmony_ci#define AD5064_CMD_CONFIG			0x8
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#define AD5064_CMD_RESET_V2			0x5
4562306a36Sopenharmony_ci#define AD5064_CMD_CONFIG_V2			0x7
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define AD5064_CONFIG_DAISY_CHAIN_ENABLE	BIT(1)
4862306a36Sopenharmony_ci#define AD5064_CONFIG_INT_VREF_ENABLE		BIT(0)
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#define AD5064_LDAC_PWRDN_NONE			0x0
5162306a36Sopenharmony_ci#define AD5064_LDAC_PWRDN_1K			0x1
5262306a36Sopenharmony_ci#define AD5064_LDAC_PWRDN_100K			0x2
5362306a36Sopenharmony_ci#define AD5064_LDAC_PWRDN_3STATE		0x3
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/**
5662306a36Sopenharmony_ci * enum ad5064_regmap_type - Register layout variant
5762306a36Sopenharmony_ci * @AD5064_REGMAP_ADI: Old Analog Devices register map layout
5862306a36Sopenharmony_ci * @AD5064_REGMAP_ADI2: New Analog Devices register map layout
5962306a36Sopenharmony_ci * @AD5064_REGMAP_LTC: LTC register map layout
6062306a36Sopenharmony_ci */
6162306a36Sopenharmony_cienum ad5064_regmap_type {
6262306a36Sopenharmony_ci	AD5064_REGMAP_ADI,
6362306a36Sopenharmony_ci	AD5064_REGMAP_ADI2,
6462306a36Sopenharmony_ci	AD5064_REGMAP_LTC,
6562306a36Sopenharmony_ci};
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci/**
6862306a36Sopenharmony_ci * struct ad5064_chip_info - chip specific information
6962306a36Sopenharmony_ci * @shared_vref:	whether the vref supply is shared between channels
7062306a36Sopenharmony_ci * @internal_vref:	internal reference voltage. 0 if the chip has no
7162306a36Sopenharmony_ci *			internal vref.
7262306a36Sopenharmony_ci * @channels:		channel specification
7362306a36Sopenharmony_ci * @num_channels:	number of channels
7462306a36Sopenharmony_ci * @regmap_type:	register map layout variant
7562306a36Sopenharmony_ci */
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistruct ad5064_chip_info {
7862306a36Sopenharmony_ci	bool shared_vref;
7962306a36Sopenharmony_ci	unsigned long internal_vref;
8062306a36Sopenharmony_ci	const struct iio_chan_spec *channels;
8162306a36Sopenharmony_ci	unsigned int num_channels;
8262306a36Sopenharmony_ci	enum ad5064_regmap_type regmap_type;
8362306a36Sopenharmony_ci};
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistruct ad5064_state;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_citypedef int (*ad5064_write_func)(struct ad5064_state *st, unsigned int cmd,
8862306a36Sopenharmony_ci		unsigned int addr, unsigned int val);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/**
9162306a36Sopenharmony_ci * struct ad5064_state - driver instance specific data
9262306a36Sopenharmony_ci * @dev:		the device for this driver instance
9362306a36Sopenharmony_ci * @chip_info:		chip model specific constants, available modes etc
9462306a36Sopenharmony_ci * @vref_reg:		vref supply regulators
9562306a36Sopenharmony_ci * @pwr_down:		whether channel is powered down
9662306a36Sopenharmony_ci * @pwr_down_mode:	channel's current power down mode
9762306a36Sopenharmony_ci * @dac_cache:		current DAC raw value (chip does not support readback)
9862306a36Sopenharmony_ci * @use_internal_vref:	set to true if the internal reference voltage should be
9962306a36Sopenharmony_ci *			used.
10062306a36Sopenharmony_ci * @write:		register write callback
10162306a36Sopenharmony_ci * @lock:		maintain consistency between cached and dev state
10262306a36Sopenharmony_ci * @data:		i2c/spi transfer buffers
10362306a36Sopenharmony_ci */
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistruct ad5064_state {
10662306a36Sopenharmony_ci	struct device			*dev;
10762306a36Sopenharmony_ci	const struct ad5064_chip_info	*chip_info;
10862306a36Sopenharmony_ci	struct regulator_bulk_data	vref_reg[AD5064_MAX_VREFS];
10962306a36Sopenharmony_ci	bool				pwr_down[AD5064_MAX_DAC_CHANNELS];
11062306a36Sopenharmony_ci	u8				pwr_down_mode[AD5064_MAX_DAC_CHANNELS];
11162306a36Sopenharmony_ci	unsigned int			dac_cache[AD5064_MAX_DAC_CHANNELS];
11262306a36Sopenharmony_ci	bool				use_internal_vref;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	ad5064_write_func		write;
11562306a36Sopenharmony_ci	struct mutex lock;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	/*
11862306a36Sopenharmony_ci	 * DMA (thus cache coherency maintenance) may require the
11962306a36Sopenharmony_ci	 * transfer buffers to live in their own cache lines.
12062306a36Sopenharmony_ci	 */
12162306a36Sopenharmony_ci	union {
12262306a36Sopenharmony_ci		u8 i2c[3];
12362306a36Sopenharmony_ci		__be32 spi;
12462306a36Sopenharmony_ci	} data __aligned(IIO_DMA_MINALIGN);
12562306a36Sopenharmony_ci};
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cienum ad5064_type {
12862306a36Sopenharmony_ci	ID_AD5024,
12962306a36Sopenharmony_ci	ID_AD5025,
13062306a36Sopenharmony_ci	ID_AD5044,
13162306a36Sopenharmony_ci	ID_AD5045,
13262306a36Sopenharmony_ci	ID_AD5064,
13362306a36Sopenharmony_ci	ID_AD5064_1,
13462306a36Sopenharmony_ci	ID_AD5065,
13562306a36Sopenharmony_ci	ID_AD5625,
13662306a36Sopenharmony_ci	ID_AD5625R_1V25,
13762306a36Sopenharmony_ci	ID_AD5625R_2V5,
13862306a36Sopenharmony_ci	ID_AD5627,
13962306a36Sopenharmony_ci	ID_AD5627R_1V25,
14062306a36Sopenharmony_ci	ID_AD5627R_2V5,
14162306a36Sopenharmony_ci	ID_AD5628_1,
14262306a36Sopenharmony_ci	ID_AD5628_2,
14362306a36Sopenharmony_ci	ID_AD5629_1,
14462306a36Sopenharmony_ci	ID_AD5629_2,
14562306a36Sopenharmony_ci	ID_AD5645R_1V25,
14662306a36Sopenharmony_ci	ID_AD5645R_2V5,
14762306a36Sopenharmony_ci	ID_AD5647R_1V25,
14862306a36Sopenharmony_ci	ID_AD5647R_2V5,
14962306a36Sopenharmony_ci	ID_AD5648_1,
15062306a36Sopenharmony_ci	ID_AD5648_2,
15162306a36Sopenharmony_ci	ID_AD5665,
15262306a36Sopenharmony_ci	ID_AD5665R_1V25,
15362306a36Sopenharmony_ci	ID_AD5665R_2V5,
15462306a36Sopenharmony_ci	ID_AD5666_1,
15562306a36Sopenharmony_ci	ID_AD5666_2,
15662306a36Sopenharmony_ci	ID_AD5667,
15762306a36Sopenharmony_ci	ID_AD5667R_1V25,
15862306a36Sopenharmony_ci	ID_AD5667R_2V5,
15962306a36Sopenharmony_ci	ID_AD5668_1,
16062306a36Sopenharmony_ci	ID_AD5668_2,
16162306a36Sopenharmony_ci	ID_AD5669_1,
16262306a36Sopenharmony_ci	ID_AD5669_2,
16362306a36Sopenharmony_ci	ID_LTC2606,
16462306a36Sopenharmony_ci	ID_LTC2607,
16562306a36Sopenharmony_ci	ID_LTC2609,
16662306a36Sopenharmony_ci	ID_LTC2616,
16762306a36Sopenharmony_ci	ID_LTC2617,
16862306a36Sopenharmony_ci	ID_LTC2619,
16962306a36Sopenharmony_ci	ID_LTC2626,
17062306a36Sopenharmony_ci	ID_LTC2627,
17162306a36Sopenharmony_ci	ID_LTC2629,
17262306a36Sopenharmony_ci	ID_LTC2631_L12,
17362306a36Sopenharmony_ci	ID_LTC2631_H12,
17462306a36Sopenharmony_ci	ID_LTC2631_L10,
17562306a36Sopenharmony_ci	ID_LTC2631_H10,
17662306a36Sopenharmony_ci	ID_LTC2631_L8,
17762306a36Sopenharmony_ci	ID_LTC2631_H8,
17862306a36Sopenharmony_ci	ID_LTC2633_L12,
17962306a36Sopenharmony_ci	ID_LTC2633_H12,
18062306a36Sopenharmony_ci	ID_LTC2633_L10,
18162306a36Sopenharmony_ci	ID_LTC2633_H10,
18262306a36Sopenharmony_ci	ID_LTC2633_L8,
18362306a36Sopenharmony_ci	ID_LTC2633_H8,
18462306a36Sopenharmony_ci	ID_LTC2635_L12,
18562306a36Sopenharmony_ci	ID_LTC2635_H12,
18662306a36Sopenharmony_ci	ID_LTC2635_L10,
18762306a36Sopenharmony_ci	ID_LTC2635_H10,
18862306a36Sopenharmony_ci	ID_LTC2635_L8,
18962306a36Sopenharmony_ci	ID_LTC2635_H8,
19062306a36Sopenharmony_ci};
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_cistatic int ad5064_write(struct ad5064_state *st, unsigned int cmd,
19362306a36Sopenharmony_ci	unsigned int addr, unsigned int val, unsigned int shift)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	val <<= shift;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	return st->write(st, cmd, addr, val);
19862306a36Sopenharmony_ci}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_cistatic int ad5064_sync_powerdown_mode(struct ad5064_state *st,
20162306a36Sopenharmony_ci	const struct iio_chan_spec *chan)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	unsigned int val, address;
20462306a36Sopenharmony_ci	unsigned int shift;
20562306a36Sopenharmony_ci	int ret;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	if (st->chip_info->regmap_type == AD5064_REGMAP_LTC) {
20862306a36Sopenharmony_ci		val = 0;
20962306a36Sopenharmony_ci		address = chan->address;
21062306a36Sopenharmony_ci	} else {
21162306a36Sopenharmony_ci		if (st->chip_info->regmap_type == AD5064_REGMAP_ADI2)
21262306a36Sopenharmony_ci			shift = 4;
21362306a36Sopenharmony_ci		else
21462306a36Sopenharmony_ci			shift = 8;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci		val = (0x1 << chan->address);
21762306a36Sopenharmony_ci		address = 0;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci		if (st->pwr_down[chan->channel])
22062306a36Sopenharmony_ci			val |= st->pwr_down_mode[chan->channel] << shift;
22162306a36Sopenharmony_ci	}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, address, val, 0);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	return ret;
22662306a36Sopenharmony_ci}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistatic const char * const ad5064_powerdown_modes[] = {
22962306a36Sopenharmony_ci	"1kohm_to_gnd",
23062306a36Sopenharmony_ci	"100kohm_to_gnd",
23162306a36Sopenharmony_ci	"three_state",
23262306a36Sopenharmony_ci};
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cistatic const char * const ltc2617_powerdown_modes[] = {
23562306a36Sopenharmony_ci	"90kohm_to_gnd",
23662306a36Sopenharmony_ci};
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistatic int ad5064_get_powerdown_mode(struct iio_dev *indio_dev,
23962306a36Sopenharmony_ci	const struct iio_chan_spec *chan)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	struct ad5064_state *st = iio_priv(indio_dev);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	return st->pwr_down_mode[chan->channel] - 1;
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic int ad5064_set_powerdown_mode(struct iio_dev *indio_dev,
24762306a36Sopenharmony_ci	const struct iio_chan_spec *chan, unsigned int mode)
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	struct ad5064_state *st = iio_priv(indio_dev);
25062306a36Sopenharmony_ci	int ret;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	mutex_lock(&st->lock);
25362306a36Sopenharmony_ci	st->pwr_down_mode[chan->channel] = mode + 1;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	ret = ad5064_sync_powerdown_mode(st, chan);
25662306a36Sopenharmony_ci	mutex_unlock(&st->lock);
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	return ret;
25962306a36Sopenharmony_ci}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_cistatic const struct iio_enum ad5064_powerdown_mode_enum = {
26262306a36Sopenharmony_ci	.items = ad5064_powerdown_modes,
26362306a36Sopenharmony_ci	.num_items = ARRAY_SIZE(ad5064_powerdown_modes),
26462306a36Sopenharmony_ci	.get = ad5064_get_powerdown_mode,
26562306a36Sopenharmony_ci	.set = ad5064_set_powerdown_mode,
26662306a36Sopenharmony_ci};
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_cistatic const struct iio_enum ltc2617_powerdown_mode_enum = {
26962306a36Sopenharmony_ci	.items = ltc2617_powerdown_modes,
27062306a36Sopenharmony_ci	.num_items = ARRAY_SIZE(ltc2617_powerdown_modes),
27162306a36Sopenharmony_ci	.get = ad5064_get_powerdown_mode,
27262306a36Sopenharmony_ci	.set = ad5064_set_powerdown_mode,
27362306a36Sopenharmony_ci};
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cistatic ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev,
27662306a36Sopenharmony_ci	uintptr_t private, const struct iio_chan_spec *chan, char *buf)
27762306a36Sopenharmony_ci{
27862306a36Sopenharmony_ci	struct ad5064_state *st = iio_priv(indio_dev);
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	return sysfs_emit(buf, "%d\n", st->pwr_down[chan->channel]);
28162306a36Sopenharmony_ci}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_cistatic ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev,
28462306a36Sopenharmony_ci	 uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
28562306a36Sopenharmony_ci	 size_t len)
28662306a36Sopenharmony_ci{
28762306a36Sopenharmony_ci	struct ad5064_state *st = iio_priv(indio_dev);
28862306a36Sopenharmony_ci	bool pwr_down;
28962306a36Sopenharmony_ci	int ret;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	ret = kstrtobool(buf, &pwr_down);
29262306a36Sopenharmony_ci	if (ret)
29362306a36Sopenharmony_ci		return ret;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	mutex_lock(&st->lock);
29662306a36Sopenharmony_ci	st->pwr_down[chan->channel] = pwr_down;
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	ret = ad5064_sync_powerdown_mode(st, chan);
29962306a36Sopenharmony_ci	mutex_unlock(&st->lock);
30062306a36Sopenharmony_ci	return ret ? ret : len;
30162306a36Sopenharmony_ci}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_cistatic int ad5064_get_vref(struct ad5064_state *st,
30462306a36Sopenharmony_ci	struct iio_chan_spec const *chan)
30562306a36Sopenharmony_ci{
30662306a36Sopenharmony_ci	unsigned int i;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	if (st->use_internal_vref)
30962306a36Sopenharmony_ci		return st->chip_info->internal_vref;
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	i = st->chip_info->shared_vref ? 0 : chan->channel;
31262306a36Sopenharmony_ci	return regulator_get_voltage(st->vref_reg[i].consumer);
31362306a36Sopenharmony_ci}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistatic int ad5064_read_raw(struct iio_dev *indio_dev,
31662306a36Sopenharmony_ci			   struct iio_chan_spec const *chan,
31762306a36Sopenharmony_ci			   int *val,
31862306a36Sopenharmony_ci			   int *val2,
31962306a36Sopenharmony_ci			   long m)
32062306a36Sopenharmony_ci{
32162306a36Sopenharmony_ci	struct ad5064_state *st = iio_priv(indio_dev);
32262306a36Sopenharmony_ci	int scale_uv;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	switch (m) {
32562306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
32662306a36Sopenharmony_ci		*val = st->dac_cache[chan->channel];
32762306a36Sopenharmony_ci		return IIO_VAL_INT;
32862306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
32962306a36Sopenharmony_ci		scale_uv = ad5064_get_vref(st, chan);
33062306a36Sopenharmony_ci		if (scale_uv < 0)
33162306a36Sopenharmony_ci			return scale_uv;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci		*val = scale_uv / 1000;
33462306a36Sopenharmony_ci		*val2 = chan->scan_type.realbits;
33562306a36Sopenharmony_ci		return IIO_VAL_FRACTIONAL_LOG2;
33662306a36Sopenharmony_ci	default:
33762306a36Sopenharmony_ci		break;
33862306a36Sopenharmony_ci	}
33962306a36Sopenharmony_ci	return -EINVAL;
34062306a36Sopenharmony_ci}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_cistatic int ad5064_write_raw(struct iio_dev *indio_dev,
34362306a36Sopenharmony_ci	struct iio_chan_spec const *chan, int val, int val2, long mask)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci	struct ad5064_state *st = iio_priv(indio_dev);
34662306a36Sopenharmony_ci	int ret;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	switch (mask) {
34962306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
35062306a36Sopenharmony_ci		if (val >= (1 << chan->scan_type.realbits) || val < 0)
35162306a36Sopenharmony_ci			return -EINVAL;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci		mutex_lock(&st->lock);
35462306a36Sopenharmony_ci		ret = ad5064_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N,
35562306a36Sopenharmony_ci				chan->address, val, chan->scan_type.shift);
35662306a36Sopenharmony_ci		if (ret == 0)
35762306a36Sopenharmony_ci			st->dac_cache[chan->channel] = val;
35862306a36Sopenharmony_ci		mutex_unlock(&st->lock);
35962306a36Sopenharmony_ci		break;
36062306a36Sopenharmony_ci	default:
36162306a36Sopenharmony_ci		ret = -EINVAL;
36262306a36Sopenharmony_ci	}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	return ret;
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic const struct iio_info ad5064_info = {
36862306a36Sopenharmony_ci	.read_raw = ad5064_read_raw,
36962306a36Sopenharmony_ci	.write_raw = ad5064_write_raw,
37062306a36Sopenharmony_ci};
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_cistatic const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
37362306a36Sopenharmony_ci	{
37462306a36Sopenharmony_ci		.name = "powerdown",
37562306a36Sopenharmony_ci		.read = ad5064_read_dac_powerdown,
37662306a36Sopenharmony_ci		.write = ad5064_write_dac_powerdown,
37762306a36Sopenharmony_ci		.shared = IIO_SEPARATE,
37862306a36Sopenharmony_ci	},
37962306a36Sopenharmony_ci	IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5064_powerdown_mode_enum),
38062306a36Sopenharmony_ci	IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5064_powerdown_mode_enum),
38162306a36Sopenharmony_ci	{ },
38262306a36Sopenharmony_ci};
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_cistatic const struct iio_chan_spec_ext_info ltc2617_ext_info[] = {
38562306a36Sopenharmony_ci	{
38662306a36Sopenharmony_ci		.name = "powerdown",
38762306a36Sopenharmony_ci		.read = ad5064_read_dac_powerdown,
38862306a36Sopenharmony_ci		.write = ad5064_write_dac_powerdown,
38962306a36Sopenharmony_ci		.shared = IIO_SEPARATE,
39062306a36Sopenharmony_ci	},
39162306a36Sopenharmony_ci	IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ltc2617_powerdown_mode_enum),
39262306a36Sopenharmony_ci	IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ltc2617_powerdown_mode_enum),
39362306a36Sopenharmony_ci	{ },
39462306a36Sopenharmony_ci};
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci#define AD5064_CHANNEL(chan, addr, bits, _shift, _ext_info) {		\
39762306a36Sopenharmony_ci	.type = IIO_VOLTAGE,					\
39862306a36Sopenharmony_ci	.indexed = 1,						\
39962306a36Sopenharmony_ci	.output = 1,						\
40062306a36Sopenharmony_ci	.channel = (chan),					\
40162306a36Sopenharmony_ci	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
40262306a36Sopenharmony_ci	BIT(IIO_CHAN_INFO_SCALE),					\
40362306a36Sopenharmony_ci	.address = addr,					\
40462306a36Sopenharmony_ci	.scan_type = {						\
40562306a36Sopenharmony_ci		.sign = 'u',					\
40662306a36Sopenharmony_ci		.realbits = (bits),				\
40762306a36Sopenharmony_ci		.storagebits = 16,				\
40862306a36Sopenharmony_ci		.shift = (_shift),				\
40962306a36Sopenharmony_ci	},							\
41062306a36Sopenharmony_ci	.ext_info = (_ext_info),				\
41162306a36Sopenharmony_ci}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci#define DECLARE_AD5064_CHANNELS(name, bits, shift, ext_info) \
41462306a36Sopenharmony_ciconst struct iio_chan_spec name[] = { \
41562306a36Sopenharmony_ci	AD5064_CHANNEL(0, 0, bits, shift, ext_info), \
41662306a36Sopenharmony_ci	AD5064_CHANNEL(1, 1, bits, shift, ext_info), \
41762306a36Sopenharmony_ci	AD5064_CHANNEL(2, 2, bits, shift, ext_info), \
41862306a36Sopenharmony_ci	AD5064_CHANNEL(3, 3, bits, shift, ext_info), \
41962306a36Sopenharmony_ci	AD5064_CHANNEL(4, 4, bits, shift, ext_info), \
42062306a36Sopenharmony_ci	AD5064_CHANNEL(5, 5, bits, shift, ext_info), \
42162306a36Sopenharmony_ci	AD5064_CHANNEL(6, 6, bits, shift, ext_info), \
42262306a36Sopenharmony_ci	AD5064_CHANNEL(7, 7, bits, shift, ext_info), \
42362306a36Sopenharmony_ci}
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci#define DECLARE_AD5065_CHANNELS(name, bits, shift, ext_info) \
42662306a36Sopenharmony_ciconst struct iio_chan_spec name[] = { \
42762306a36Sopenharmony_ci	AD5064_CHANNEL(0, 0, bits, shift, ext_info), \
42862306a36Sopenharmony_ci	AD5064_CHANNEL(1, 3, bits, shift, ext_info), \
42962306a36Sopenharmony_ci}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5024_channels, 12, 8, ad5064_ext_info);
43262306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5044_channels, 14, 6, ad5064_ext_info);
43362306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5064_channels, 16, 4, ad5064_ext_info);
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_cistatic DECLARE_AD5065_CHANNELS(ad5025_channels, 12, 8, ad5064_ext_info);
43662306a36Sopenharmony_cistatic DECLARE_AD5065_CHANNELS(ad5045_channels, 14, 6, ad5064_ext_info);
43762306a36Sopenharmony_cistatic DECLARE_AD5065_CHANNELS(ad5065_channels, 16, 4, ad5064_ext_info);
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5629_channels, 12, 4, ad5064_ext_info);
44062306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5645_channels, 14, 2, ad5064_ext_info);
44162306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5669_channels, 16, 0, ad5064_ext_info);
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2607_channels, 16, 0, ltc2617_ext_info);
44462306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2617_channels, 14, 2, ltc2617_ext_info);
44562306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2627_channels, 12, 4, ltc2617_ext_info);
44662306a36Sopenharmony_ci#define ltc2631_12_channels ltc2627_channels
44762306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2631_10_channels, 10, 6, ltc2617_ext_info);
44862306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2631_8_channels, 8, 8, ltc2617_ext_info);
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci#define LTC2631_INFO(vref, pchannels, nchannels)	\
45162306a36Sopenharmony_ci	{						\
45262306a36Sopenharmony_ci		.shared_vref = true,			\
45362306a36Sopenharmony_ci		.internal_vref = vref,			\
45462306a36Sopenharmony_ci		.channels = pchannels,			\
45562306a36Sopenharmony_ci		.num_channels = nchannels,		\
45662306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,	\
45762306a36Sopenharmony_ci	}
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_cistatic const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
46162306a36Sopenharmony_ci	[ID_AD5024] = {
46262306a36Sopenharmony_ci		.shared_vref = false,
46362306a36Sopenharmony_ci		.channels = ad5024_channels,
46462306a36Sopenharmony_ci		.num_channels = 4,
46562306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
46662306a36Sopenharmony_ci	},
46762306a36Sopenharmony_ci	[ID_AD5025] = {
46862306a36Sopenharmony_ci		.shared_vref = false,
46962306a36Sopenharmony_ci		.channels = ad5025_channels,
47062306a36Sopenharmony_ci		.num_channels = 2,
47162306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
47262306a36Sopenharmony_ci	},
47362306a36Sopenharmony_ci	[ID_AD5044] = {
47462306a36Sopenharmony_ci		.shared_vref = false,
47562306a36Sopenharmony_ci		.channels = ad5044_channels,
47662306a36Sopenharmony_ci		.num_channels = 4,
47762306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
47862306a36Sopenharmony_ci	},
47962306a36Sopenharmony_ci	[ID_AD5045] = {
48062306a36Sopenharmony_ci		.shared_vref = false,
48162306a36Sopenharmony_ci		.channels = ad5045_channels,
48262306a36Sopenharmony_ci		.num_channels = 2,
48362306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
48462306a36Sopenharmony_ci	},
48562306a36Sopenharmony_ci	[ID_AD5064] = {
48662306a36Sopenharmony_ci		.shared_vref = false,
48762306a36Sopenharmony_ci		.channels = ad5064_channels,
48862306a36Sopenharmony_ci		.num_channels = 4,
48962306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
49062306a36Sopenharmony_ci	},
49162306a36Sopenharmony_ci	[ID_AD5064_1] = {
49262306a36Sopenharmony_ci		.shared_vref = true,
49362306a36Sopenharmony_ci		.channels = ad5064_channels,
49462306a36Sopenharmony_ci		.num_channels = 4,
49562306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
49662306a36Sopenharmony_ci	},
49762306a36Sopenharmony_ci	[ID_AD5065] = {
49862306a36Sopenharmony_ci		.shared_vref = false,
49962306a36Sopenharmony_ci		.channels = ad5065_channels,
50062306a36Sopenharmony_ci		.num_channels = 2,
50162306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
50262306a36Sopenharmony_ci	},
50362306a36Sopenharmony_ci	[ID_AD5625] = {
50462306a36Sopenharmony_ci		.shared_vref = true,
50562306a36Sopenharmony_ci		.channels = ad5629_channels,
50662306a36Sopenharmony_ci		.num_channels = 4,
50762306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
50862306a36Sopenharmony_ci	},
50962306a36Sopenharmony_ci	[ID_AD5625R_1V25] = {
51062306a36Sopenharmony_ci		.shared_vref = true,
51162306a36Sopenharmony_ci		.internal_vref = 1250000,
51262306a36Sopenharmony_ci		.channels = ad5629_channels,
51362306a36Sopenharmony_ci		.num_channels = 4,
51462306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
51562306a36Sopenharmony_ci	},
51662306a36Sopenharmony_ci	[ID_AD5625R_2V5] = {
51762306a36Sopenharmony_ci		.shared_vref = true,
51862306a36Sopenharmony_ci		.internal_vref = 2500000,
51962306a36Sopenharmony_ci		.channels = ad5629_channels,
52062306a36Sopenharmony_ci		.num_channels = 4,
52162306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
52262306a36Sopenharmony_ci	},
52362306a36Sopenharmony_ci	[ID_AD5627] = {
52462306a36Sopenharmony_ci		.shared_vref = true,
52562306a36Sopenharmony_ci		.channels = ad5629_channels,
52662306a36Sopenharmony_ci		.num_channels = 2,
52762306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
52862306a36Sopenharmony_ci	},
52962306a36Sopenharmony_ci	[ID_AD5627R_1V25] = {
53062306a36Sopenharmony_ci		.shared_vref = true,
53162306a36Sopenharmony_ci		.internal_vref = 1250000,
53262306a36Sopenharmony_ci		.channels = ad5629_channels,
53362306a36Sopenharmony_ci		.num_channels = 2,
53462306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
53562306a36Sopenharmony_ci	},
53662306a36Sopenharmony_ci	[ID_AD5627R_2V5] = {
53762306a36Sopenharmony_ci		.shared_vref = true,
53862306a36Sopenharmony_ci		.internal_vref = 2500000,
53962306a36Sopenharmony_ci		.channels = ad5629_channels,
54062306a36Sopenharmony_ci		.num_channels = 2,
54162306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
54262306a36Sopenharmony_ci	},
54362306a36Sopenharmony_ci	[ID_AD5628_1] = {
54462306a36Sopenharmony_ci		.shared_vref = true,
54562306a36Sopenharmony_ci		.internal_vref = 2500000,
54662306a36Sopenharmony_ci		.channels = ad5024_channels,
54762306a36Sopenharmony_ci		.num_channels = 8,
54862306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
54962306a36Sopenharmony_ci	},
55062306a36Sopenharmony_ci	[ID_AD5628_2] = {
55162306a36Sopenharmony_ci		.shared_vref = true,
55262306a36Sopenharmony_ci		.internal_vref = 5000000,
55362306a36Sopenharmony_ci		.channels = ad5024_channels,
55462306a36Sopenharmony_ci		.num_channels = 8,
55562306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
55662306a36Sopenharmony_ci	},
55762306a36Sopenharmony_ci	[ID_AD5629_1] = {
55862306a36Sopenharmony_ci		.shared_vref = true,
55962306a36Sopenharmony_ci		.internal_vref = 2500000,
56062306a36Sopenharmony_ci		.channels = ad5629_channels,
56162306a36Sopenharmony_ci		.num_channels = 8,
56262306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
56362306a36Sopenharmony_ci	},
56462306a36Sopenharmony_ci	[ID_AD5629_2] = {
56562306a36Sopenharmony_ci		.shared_vref = true,
56662306a36Sopenharmony_ci		.internal_vref = 5000000,
56762306a36Sopenharmony_ci		.channels = ad5629_channels,
56862306a36Sopenharmony_ci		.num_channels = 8,
56962306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
57062306a36Sopenharmony_ci	},
57162306a36Sopenharmony_ci	[ID_AD5645R_1V25] = {
57262306a36Sopenharmony_ci		.shared_vref = true,
57362306a36Sopenharmony_ci		.internal_vref = 1250000,
57462306a36Sopenharmony_ci		.channels = ad5645_channels,
57562306a36Sopenharmony_ci		.num_channels = 4,
57662306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
57762306a36Sopenharmony_ci	},
57862306a36Sopenharmony_ci	[ID_AD5645R_2V5] = {
57962306a36Sopenharmony_ci		.shared_vref = true,
58062306a36Sopenharmony_ci		.internal_vref = 2500000,
58162306a36Sopenharmony_ci		.channels = ad5645_channels,
58262306a36Sopenharmony_ci		.num_channels = 4,
58362306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
58462306a36Sopenharmony_ci	},
58562306a36Sopenharmony_ci	[ID_AD5647R_1V25] = {
58662306a36Sopenharmony_ci		.shared_vref = true,
58762306a36Sopenharmony_ci		.internal_vref = 1250000,
58862306a36Sopenharmony_ci		.channels = ad5645_channels,
58962306a36Sopenharmony_ci		.num_channels = 2,
59062306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
59162306a36Sopenharmony_ci	},
59262306a36Sopenharmony_ci	[ID_AD5647R_2V5] = {
59362306a36Sopenharmony_ci		.shared_vref = true,
59462306a36Sopenharmony_ci		.internal_vref = 2500000,
59562306a36Sopenharmony_ci		.channels = ad5645_channels,
59662306a36Sopenharmony_ci		.num_channels = 2,
59762306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
59862306a36Sopenharmony_ci	},
59962306a36Sopenharmony_ci	[ID_AD5648_1] = {
60062306a36Sopenharmony_ci		.shared_vref = true,
60162306a36Sopenharmony_ci		.internal_vref = 2500000,
60262306a36Sopenharmony_ci		.channels = ad5044_channels,
60362306a36Sopenharmony_ci		.num_channels = 8,
60462306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
60562306a36Sopenharmony_ci	},
60662306a36Sopenharmony_ci	[ID_AD5648_2] = {
60762306a36Sopenharmony_ci		.shared_vref = true,
60862306a36Sopenharmony_ci		.internal_vref = 5000000,
60962306a36Sopenharmony_ci		.channels = ad5044_channels,
61062306a36Sopenharmony_ci		.num_channels = 8,
61162306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
61262306a36Sopenharmony_ci	},
61362306a36Sopenharmony_ci	[ID_AD5665] = {
61462306a36Sopenharmony_ci		.shared_vref = true,
61562306a36Sopenharmony_ci		.channels = ad5669_channels,
61662306a36Sopenharmony_ci		.num_channels = 4,
61762306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
61862306a36Sopenharmony_ci	},
61962306a36Sopenharmony_ci	[ID_AD5665R_1V25] = {
62062306a36Sopenharmony_ci		.shared_vref = true,
62162306a36Sopenharmony_ci		.internal_vref = 1250000,
62262306a36Sopenharmony_ci		.channels = ad5669_channels,
62362306a36Sopenharmony_ci		.num_channels = 4,
62462306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
62562306a36Sopenharmony_ci	},
62662306a36Sopenharmony_ci	[ID_AD5665R_2V5] = {
62762306a36Sopenharmony_ci		.shared_vref = true,
62862306a36Sopenharmony_ci		.internal_vref = 2500000,
62962306a36Sopenharmony_ci		.channels = ad5669_channels,
63062306a36Sopenharmony_ci		.num_channels = 4,
63162306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
63262306a36Sopenharmony_ci	},
63362306a36Sopenharmony_ci	[ID_AD5666_1] = {
63462306a36Sopenharmony_ci		.shared_vref = true,
63562306a36Sopenharmony_ci		.internal_vref = 2500000,
63662306a36Sopenharmony_ci		.channels = ad5064_channels,
63762306a36Sopenharmony_ci		.num_channels = 4,
63862306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
63962306a36Sopenharmony_ci	},
64062306a36Sopenharmony_ci	[ID_AD5666_2] = {
64162306a36Sopenharmony_ci		.shared_vref = true,
64262306a36Sopenharmony_ci		.internal_vref = 5000000,
64362306a36Sopenharmony_ci		.channels = ad5064_channels,
64462306a36Sopenharmony_ci		.num_channels = 4,
64562306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
64662306a36Sopenharmony_ci	},
64762306a36Sopenharmony_ci	[ID_AD5667] = {
64862306a36Sopenharmony_ci		.shared_vref = true,
64962306a36Sopenharmony_ci		.channels = ad5669_channels,
65062306a36Sopenharmony_ci		.num_channels = 2,
65162306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
65262306a36Sopenharmony_ci	},
65362306a36Sopenharmony_ci	[ID_AD5667R_1V25] = {
65462306a36Sopenharmony_ci		.shared_vref = true,
65562306a36Sopenharmony_ci		.internal_vref = 1250000,
65662306a36Sopenharmony_ci		.channels = ad5669_channels,
65762306a36Sopenharmony_ci		.num_channels = 2,
65862306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
65962306a36Sopenharmony_ci	},
66062306a36Sopenharmony_ci	[ID_AD5667R_2V5] = {
66162306a36Sopenharmony_ci		.shared_vref = true,
66262306a36Sopenharmony_ci		.internal_vref = 2500000,
66362306a36Sopenharmony_ci		.channels = ad5669_channels,
66462306a36Sopenharmony_ci		.num_channels = 2,
66562306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
66662306a36Sopenharmony_ci	},
66762306a36Sopenharmony_ci	[ID_AD5668_1] = {
66862306a36Sopenharmony_ci		.shared_vref = true,
66962306a36Sopenharmony_ci		.internal_vref = 2500000,
67062306a36Sopenharmony_ci		.channels = ad5064_channels,
67162306a36Sopenharmony_ci		.num_channels = 8,
67262306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
67362306a36Sopenharmony_ci	},
67462306a36Sopenharmony_ci	[ID_AD5668_2] = {
67562306a36Sopenharmony_ci		.shared_vref = true,
67662306a36Sopenharmony_ci		.internal_vref = 5000000,
67762306a36Sopenharmony_ci		.channels = ad5064_channels,
67862306a36Sopenharmony_ci		.num_channels = 8,
67962306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
68062306a36Sopenharmony_ci	},
68162306a36Sopenharmony_ci	[ID_AD5669_1] = {
68262306a36Sopenharmony_ci		.shared_vref = true,
68362306a36Sopenharmony_ci		.internal_vref = 2500000,
68462306a36Sopenharmony_ci		.channels = ad5669_channels,
68562306a36Sopenharmony_ci		.num_channels = 8,
68662306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
68762306a36Sopenharmony_ci	},
68862306a36Sopenharmony_ci	[ID_AD5669_2] = {
68962306a36Sopenharmony_ci		.shared_vref = true,
69062306a36Sopenharmony_ci		.internal_vref = 5000000,
69162306a36Sopenharmony_ci		.channels = ad5669_channels,
69262306a36Sopenharmony_ci		.num_channels = 8,
69362306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
69462306a36Sopenharmony_ci	},
69562306a36Sopenharmony_ci	[ID_LTC2606] = {
69662306a36Sopenharmony_ci		.shared_vref = true,
69762306a36Sopenharmony_ci		.internal_vref = 0,
69862306a36Sopenharmony_ci		.channels = ltc2607_channels,
69962306a36Sopenharmony_ci		.num_channels = 1,
70062306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
70162306a36Sopenharmony_ci	},
70262306a36Sopenharmony_ci	[ID_LTC2607] = {
70362306a36Sopenharmony_ci		.shared_vref = true,
70462306a36Sopenharmony_ci		.internal_vref = 0,
70562306a36Sopenharmony_ci		.channels = ltc2607_channels,
70662306a36Sopenharmony_ci		.num_channels = 2,
70762306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
70862306a36Sopenharmony_ci	},
70962306a36Sopenharmony_ci	[ID_LTC2609] = {
71062306a36Sopenharmony_ci		.shared_vref = false,
71162306a36Sopenharmony_ci		.internal_vref = 0,
71262306a36Sopenharmony_ci		.channels = ltc2607_channels,
71362306a36Sopenharmony_ci		.num_channels = 4,
71462306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
71562306a36Sopenharmony_ci	},
71662306a36Sopenharmony_ci	[ID_LTC2616] = {
71762306a36Sopenharmony_ci		.shared_vref = true,
71862306a36Sopenharmony_ci		.internal_vref = 0,
71962306a36Sopenharmony_ci		.channels = ltc2617_channels,
72062306a36Sopenharmony_ci		.num_channels = 1,
72162306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
72262306a36Sopenharmony_ci	},
72362306a36Sopenharmony_ci	[ID_LTC2617] = {
72462306a36Sopenharmony_ci		.shared_vref = true,
72562306a36Sopenharmony_ci		.internal_vref = 0,
72662306a36Sopenharmony_ci		.channels = ltc2617_channels,
72762306a36Sopenharmony_ci		.num_channels = 2,
72862306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
72962306a36Sopenharmony_ci	},
73062306a36Sopenharmony_ci	[ID_LTC2619] = {
73162306a36Sopenharmony_ci		.shared_vref = false,
73262306a36Sopenharmony_ci		.internal_vref = 0,
73362306a36Sopenharmony_ci		.channels = ltc2617_channels,
73462306a36Sopenharmony_ci		.num_channels = 4,
73562306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
73662306a36Sopenharmony_ci	},
73762306a36Sopenharmony_ci	[ID_LTC2626] = {
73862306a36Sopenharmony_ci		.shared_vref = true,
73962306a36Sopenharmony_ci		.internal_vref = 0,
74062306a36Sopenharmony_ci		.channels = ltc2627_channels,
74162306a36Sopenharmony_ci		.num_channels = 1,
74262306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
74362306a36Sopenharmony_ci	},
74462306a36Sopenharmony_ci	[ID_LTC2627] = {
74562306a36Sopenharmony_ci		.shared_vref = true,
74662306a36Sopenharmony_ci		.internal_vref = 0,
74762306a36Sopenharmony_ci		.channels = ltc2627_channels,
74862306a36Sopenharmony_ci		.num_channels = 2,
74962306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
75062306a36Sopenharmony_ci	},
75162306a36Sopenharmony_ci	[ID_LTC2629] = {
75262306a36Sopenharmony_ci		.shared_vref = false,
75362306a36Sopenharmony_ci		.internal_vref = 0,
75462306a36Sopenharmony_ci		.channels = ltc2627_channels,
75562306a36Sopenharmony_ci		.num_channels = 4,
75662306a36Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
75762306a36Sopenharmony_ci	},
75862306a36Sopenharmony_ci	[ID_LTC2631_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 1),
75962306a36Sopenharmony_ci	[ID_LTC2631_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 1),
76062306a36Sopenharmony_ci	[ID_LTC2631_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 1),
76162306a36Sopenharmony_ci	[ID_LTC2631_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 1),
76262306a36Sopenharmony_ci	[ID_LTC2631_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 1),
76362306a36Sopenharmony_ci	[ID_LTC2631_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 1),
76462306a36Sopenharmony_ci	[ID_LTC2633_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 2),
76562306a36Sopenharmony_ci	[ID_LTC2633_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 2),
76662306a36Sopenharmony_ci	[ID_LTC2633_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 2),
76762306a36Sopenharmony_ci	[ID_LTC2633_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 2),
76862306a36Sopenharmony_ci	[ID_LTC2633_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 2),
76962306a36Sopenharmony_ci	[ID_LTC2633_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 2),
77062306a36Sopenharmony_ci	[ID_LTC2635_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 4),
77162306a36Sopenharmony_ci	[ID_LTC2635_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 4),
77262306a36Sopenharmony_ci	[ID_LTC2635_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 4),
77362306a36Sopenharmony_ci	[ID_LTC2635_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 4),
77462306a36Sopenharmony_ci	[ID_LTC2635_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 4),
77562306a36Sopenharmony_ci	[ID_LTC2635_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 4),
77662306a36Sopenharmony_ci};
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_cistatic inline unsigned int ad5064_num_vref(struct ad5064_state *st)
77962306a36Sopenharmony_ci{
78062306a36Sopenharmony_ci	return st->chip_info->shared_vref ? 1 : st->chip_info->num_channels;
78162306a36Sopenharmony_ci}
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_cistatic const char * const ad5064_vref_names[] = {
78462306a36Sopenharmony_ci	"vrefA",
78562306a36Sopenharmony_ci	"vrefB",
78662306a36Sopenharmony_ci	"vrefC",
78762306a36Sopenharmony_ci	"vrefD",
78862306a36Sopenharmony_ci};
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_cistatic const char *ad5064_vref_name(struct ad5064_state *st,
79162306a36Sopenharmony_ci	unsigned int vref)
79262306a36Sopenharmony_ci{
79362306a36Sopenharmony_ci	return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref];
79462306a36Sopenharmony_ci}
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_cistatic int ad5064_set_config(struct ad5064_state *st, unsigned int val)
79762306a36Sopenharmony_ci{
79862306a36Sopenharmony_ci	unsigned int cmd;
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	switch (st->chip_info->regmap_type) {
80162306a36Sopenharmony_ci	case AD5064_REGMAP_ADI2:
80262306a36Sopenharmony_ci		cmd = AD5064_CMD_CONFIG_V2;
80362306a36Sopenharmony_ci		break;
80462306a36Sopenharmony_ci	default:
80562306a36Sopenharmony_ci		cmd = AD5064_CMD_CONFIG;
80662306a36Sopenharmony_ci		break;
80762306a36Sopenharmony_ci	}
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	return ad5064_write(st, cmd, 0, val, 0);
81062306a36Sopenharmony_ci}
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_cistatic int ad5064_request_vref(struct ad5064_state *st, struct device *dev)
81362306a36Sopenharmony_ci{
81462306a36Sopenharmony_ci	unsigned int i;
81562306a36Sopenharmony_ci	int ret;
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	for (i = 0; i < ad5064_num_vref(st); ++i)
81862306a36Sopenharmony_ci		st->vref_reg[i].supply = ad5064_vref_name(st, i);
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci	if (!st->chip_info->internal_vref)
82162306a36Sopenharmony_ci		return devm_regulator_bulk_get(dev, ad5064_num_vref(st),
82262306a36Sopenharmony_ci					       st->vref_reg);
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	/*
82562306a36Sopenharmony_ci	 * This assumes that when the regulator has an internal VREF
82662306a36Sopenharmony_ci	 * there is only one external VREF connection, which is
82762306a36Sopenharmony_ci	 * currently the case for all supported devices.
82862306a36Sopenharmony_ci	 */
82962306a36Sopenharmony_ci	st->vref_reg[0].consumer = devm_regulator_get_optional(dev, "vref");
83062306a36Sopenharmony_ci	if (!IS_ERR(st->vref_reg[0].consumer))
83162306a36Sopenharmony_ci		return 0;
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	ret = PTR_ERR(st->vref_reg[0].consumer);
83462306a36Sopenharmony_ci	if (ret != -ENODEV)
83562306a36Sopenharmony_ci		return ret;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	/* If no external regulator was supplied use the internal VREF */
83862306a36Sopenharmony_ci	st->use_internal_vref = true;
83962306a36Sopenharmony_ci	ret = ad5064_set_config(st, AD5064_CONFIG_INT_VREF_ENABLE);
84062306a36Sopenharmony_ci	if (ret)
84162306a36Sopenharmony_ci		dev_err(dev, "Failed to enable internal vref: %d\n", ret);
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	return ret;
84462306a36Sopenharmony_ci}
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_cistatic void ad5064_bulk_reg_disable(void *data)
84762306a36Sopenharmony_ci{
84862306a36Sopenharmony_ci	struct ad5064_state *st = data;
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg);
85162306a36Sopenharmony_ci}
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_cistatic int ad5064_probe(struct device *dev, enum ad5064_type type,
85462306a36Sopenharmony_ci			const char *name, ad5064_write_func write)
85562306a36Sopenharmony_ci{
85662306a36Sopenharmony_ci	struct iio_dev *indio_dev;
85762306a36Sopenharmony_ci	struct ad5064_state *st;
85862306a36Sopenharmony_ci	unsigned int midscale;
85962306a36Sopenharmony_ci	unsigned int i;
86062306a36Sopenharmony_ci	int ret;
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
86362306a36Sopenharmony_ci	if (indio_dev == NULL)
86462306a36Sopenharmony_ci		return  -ENOMEM;
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	st = iio_priv(indio_dev);
86762306a36Sopenharmony_ci	mutex_init(&st->lock);
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	st->chip_info = &ad5064_chip_info_tbl[type];
87062306a36Sopenharmony_ci	st->dev = dev;
87162306a36Sopenharmony_ci	st->write = write;
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	ret = ad5064_request_vref(st, dev);
87462306a36Sopenharmony_ci	if (ret)
87562306a36Sopenharmony_ci		return ret;
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	if (!st->use_internal_vref) {
87862306a36Sopenharmony_ci		ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg);
87962306a36Sopenharmony_ci		if (ret)
88062306a36Sopenharmony_ci			return ret;
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci		ret = devm_add_action_or_reset(dev, ad5064_bulk_reg_disable, st);
88362306a36Sopenharmony_ci		if (ret)
88462306a36Sopenharmony_ci			return ret;
88562306a36Sopenharmony_ci	}
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	indio_dev->name = name;
88862306a36Sopenharmony_ci	indio_dev->info = &ad5064_info;
88962306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
89062306a36Sopenharmony_ci	indio_dev->channels = st->chip_info->channels;
89162306a36Sopenharmony_ci	indio_dev->num_channels = st->chip_info->num_channels;
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	midscale = (1 << indio_dev->channels[0].scan_type.realbits) /  2;
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	for (i = 0; i < st->chip_info->num_channels; ++i) {
89662306a36Sopenharmony_ci		st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K;
89762306a36Sopenharmony_ci		st->dac_cache[i] = midscale;
89862306a36Sopenharmony_ci	}
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	return devm_iio_device_register(dev, indio_dev);
90162306a36Sopenharmony_ci}
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SPI_MASTER)
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_cistatic int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd,
90662306a36Sopenharmony_ci	unsigned int addr, unsigned int val)
90762306a36Sopenharmony_ci{
90862306a36Sopenharmony_ci	struct spi_device *spi = to_spi_device(st->dev);
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	st->data.spi = cpu_to_be32(AD5064_CMD(cmd) | AD5064_ADDR(addr) | val);
91162306a36Sopenharmony_ci	return spi_write(spi, &st->data.spi, sizeof(st->data.spi));
91262306a36Sopenharmony_ci}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_cistatic int ad5064_spi_probe(struct spi_device *spi)
91562306a36Sopenharmony_ci{
91662306a36Sopenharmony_ci	const struct spi_device_id *id = spi_get_device_id(spi);
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci	return ad5064_probe(&spi->dev, id->driver_data, id->name,
91962306a36Sopenharmony_ci				ad5064_spi_write);
92062306a36Sopenharmony_ci}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_cistatic const struct spi_device_id ad5064_spi_ids[] = {
92362306a36Sopenharmony_ci	{"ad5024", ID_AD5024},
92462306a36Sopenharmony_ci	{"ad5025", ID_AD5025},
92562306a36Sopenharmony_ci	{"ad5044", ID_AD5044},
92662306a36Sopenharmony_ci	{"ad5045", ID_AD5045},
92762306a36Sopenharmony_ci	{"ad5064", ID_AD5064},
92862306a36Sopenharmony_ci	{"ad5064-1", ID_AD5064_1},
92962306a36Sopenharmony_ci	{"ad5065", ID_AD5065},
93062306a36Sopenharmony_ci	{"ad5628-1", ID_AD5628_1},
93162306a36Sopenharmony_ci	{"ad5628-2", ID_AD5628_2},
93262306a36Sopenharmony_ci	{"ad5648-1", ID_AD5648_1},
93362306a36Sopenharmony_ci	{"ad5648-2", ID_AD5648_2},
93462306a36Sopenharmony_ci	{"ad5666-1", ID_AD5666_1},
93562306a36Sopenharmony_ci	{"ad5666-2", ID_AD5666_2},
93662306a36Sopenharmony_ci	{"ad5668-1", ID_AD5668_1},
93762306a36Sopenharmony_ci	{"ad5668-2", ID_AD5668_2},
93862306a36Sopenharmony_ci	{"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */
93962306a36Sopenharmony_ci	{}
94062306a36Sopenharmony_ci};
94162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad5064_spi_ids);
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_cistatic struct spi_driver ad5064_spi_driver = {
94462306a36Sopenharmony_ci	.driver = {
94562306a36Sopenharmony_ci		   .name = "ad5064",
94662306a36Sopenharmony_ci	},
94762306a36Sopenharmony_ci	.probe = ad5064_spi_probe,
94862306a36Sopenharmony_ci	.id_table = ad5064_spi_ids,
94962306a36Sopenharmony_ci};
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_cistatic int __init ad5064_spi_register_driver(void)
95262306a36Sopenharmony_ci{
95362306a36Sopenharmony_ci	return spi_register_driver(&ad5064_spi_driver);
95462306a36Sopenharmony_ci}
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_cistatic void ad5064_spi_unregister_driver(void)
95762306a36Sopenharmony_ci{
95862306a36Sopenharmony_ci	spi_unregister_driver(&ad5064_spi_driver);
95962306a36Sopenharmony_ci}
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci#else
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_cistatic inline int ad5064_spi_register_driver(void) { return 0; }
96462306a36Sopenharmony_cistatic inline void ad5064_spi_unregister_driver(void) { }
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci#endif
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C)
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_cistatic int ad5064_i2c_write(struct ad5064_state *st, unsigned int cmd,
97162306a36Sopenharmony_ci	unsigned int addr, unsigned int val)
97262306a36Sopenharmony_ci{
97362306a36Sopenharmony_ci	struct i2c_client *i2c = to_i2c_client(st->dev);
97462306a36Sopenharmony_ci	unsigned int cmd_shift;
97562306a36Sopenharmony_ci	int ret;
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	switch (st->chip_info->regmap_type) {
97862306a36Sopenharmony_ci	case AD5064_REGMAP_ADI2:
97962306a36Sopenharmony_ci		cmd_shift = 3;
98062306a36Sopenharmony_ci		break;
98162306a36Sopenharmony_ci	default:
98262306a36Sopenharmony_ci		cmd_shift = 4;
98362306a36Sopenharmony_ci		break;
98462306a36Sopenharmony_ci	}
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	st->data.i2c[0] = (cmd << cmd_shift) | addr;
98762306a36Sopenharmony_ci	put_unaligned_be16(val, &st->data.i2c[1]);
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	ret = i2c_master_send(i2c, st->data.i2c, 3);
99062306a36Sopenharmony_ci	if (ret < 0)
99162306a36Sopenharmony_ci		return ret;
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	return 0;
99462306a36Sopenharmony_ci}
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_cistatic int ad5064_i2c_probe(struct i2c_client *i2c)
99762306a36Sopenharmony_ci{
99862306a36Sopenharmony_ci	const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
99962306a36Sopenharmony_ci	return ad5064_probe(&i2c->dev, id->driver_data, id->name,
100062306a36Sopenharmony_ci						ad5064_i2c_write);
100162306a36Sopenharmony_ci}
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_cistatic const struct i2c_device_id ad5064_i2c_ids[] = {
100462306a36Sopenharmony_ci	{"ad5625", ID_AD5625 },
100562306a36Sopenharmony_ci	{"ad5625r-1v25", ID_AD5625R_1V25 },
100662306a36Sopenharmony_ci	{"ad5625r-2v5", ID_AD5625R_2V5 },
100762306a36Sopenharmony_ci	{"ad5627", ID_AD5627 },
100862306a36Sopenharmony_ci	{"ad5627r-1v25", ID_AD5627R_1V25 },
100962306a36Sopenharmony_ci	{"ad5627r-2v5", ID_AD5627R_2V5 },
101062306a36Sopenharmony_ci	{"ad5629-1", ID_AD5629_1},
101162306a36Sopenharmony_ci	{"ad5629-2", ID_AD5629_2},
101262306a36Sopenharmony_ci	{"ad5629-3", ID_AD5629_2}, /* similar enough to ad5629-2 */
101362306a36Sopenharmony_ci	{"ad5645r-1v25", ID_AD5645R_1V25 },
101462306a36Sopenharmony_ci	{"ad5645r-2v5", ID_AD5645R_2V5 },
101562306a36Sopenharmony_ci	{"ad5665", ID_AD5665 },
101662306a36Sopenharmony_ci	{"ad5665r-1v25", ID_AD5665R_1V25 },
101762306a36Sopenharmony_ci	{"ad5665r-2v5", ID_AD5665R_2V5 },
101862306a36Sopenharmony_ci	{"ad5667", ID_AD5667 },
101962306a36Sopenharmony_ci	{"ad5667r-1v25", ID_AD5667R_1V25 },
102062306a36Sopenharmony_ci	{"ad5667r-2v5", ID_AD5667R_2V5 },
102162306a36Sopenharmony_ci	{"ad5669-1", ID_AD5669_1},
102262306a36Sopenharmony_ci	{"ad5669-2", ID_AD5669_2},
102362306a36Sopenharmony_ci	{"ad5669-3", ID_AD5669_2}, /* similar enough to ad5669-2 */
102462306a36Sopenharmony_ci	{"ltc2606", ID_LTC2606},
102562306a36Sopenharmony_ci	{"ltc2607", ID_LTC2607},
102662306a36Sopenharmony_ci	{"ltc2609", ID_LTC2609},
102762306a36Sopenharmony_ci	{"ltc2616", ID_LTC2616},
102862306a36Sopenharmony_ci	{"ltc2617", ID_LTC2617},
102962306a36Sopenharmony_ci	{"ltc2619", ID_LTC2619},
103062306a36Sopenharmony_ci	{"ltc2626", ID_LTC2626},
103162306a36Sopenharmony_ci	{"ltc2627", ID_LTC2627},
103262306a36Sopenharmony_ci	{"ltc2629", ID_LTC2629},
103362306a36Sopenharmony_ci	{"ltc2631-l12", ID_LTC2631_L12},
103462306a36Sopenharmony_ci	{"ltc2631-h12", ID_LTC2631_H12},
103562306a36Sopenharmony_ci	{"ltc2631-l10", ID_LTC2631_L10},
103662306a36Sopenharmony_ci	{"ltc2631-h10", ID_LTC2631_H10},
103762306a36Sopenharmony_ci	{"ltc2631-l8", ID_LTC2631_L8},
103862306a36Sopenharmony_ci	{"ltc2631-h8", ID_LTC2631_H8},
103962306a36Sopenharmony_ci	{"ltc2633-l12", ID_LTC2633_L12},
104062306a36Sopenharmony_ci	{"ltc2633-h12", ID_LTC2633_H12},
104162306a36Sopenharmony_ci	{"ltc2633-l10", ID_LTC2633_L10},
104262306a36Sopenharmony_ci	{"ltc2633-h10", ID_LTC2633_H10},
104362306a36Sopenharmony_ci	{"ltc2633-l8", ID_LTC2633_L8},
104462306a36Sopenharmony_ci	{"ltc2633-h8", ID_LTC2633_H8},
104562306a36Sopenharmony_ci	{"ltc2635-l12", ID_LTC2635_L12},
104662306a36Sopenharmony_ci	{"ltc2635-h12", ID_LTC2635_H12},
104762306a36Sopenharmony_ci	{"ltc2635-l10", ID_LTC2635_L10},
104862306a36Sopenharmony_ci	{"ltc2635-h10", ID_LTC2635_H10},
104962306a36Sopenharmony_ci	{"ltc2635-l8", ID_LTC2635_L8},
105062306a36Sopenharmony_ci	{"ltc2635-h8", ID_LTC2635_H8},
105162306a36Sopenharmony_ci	{}
105262306a36Sopenharmony_ci};
105362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids);
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_cistatic struct i2c_driver ad5064_i2c_driver = {
105662306a36Sopenharmony_ci	.driver = {
105762306a36Sopenharmony_ci		   .name = "ad5064",
105862306a36Sopenharmony_ci	},
105962306a36Sopenharmony_ci	.probe = ad5064_i2c_probe,
106062306a36Sopenharmony_ci	.id_table = ad5064_i2c_ids,
106162306a36Sopenharmony_ci};
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_cistatic int __init ad5064_i2c_register_driver(void)
106462306a36Sopenharmony_ci{
106562306a36Sopenharmony_ci	return i2c_add_driver(&ad5064_i2c_driver);
106662306a36Sopenharmony_ci}
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_cistatic void __exit ad5064_i2c_unregister_driver(void)
106962306a36Sopenharmony_ci{
107062306a36Sopenharmony_ci	i2c_del_driver(&ad5064_i2c_driver);
107162306a36Sopenharmony_ci}
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci#else
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_cistatic inline int ad5064_i2c_register_driver(void) { return 0; }
107662306a36Sopenharmony_cistatic inline void ad5064_i2c_unregister_driver(void) { }
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci#endif
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_cistatic int __init ad5064_init(void)
108162306a36Sopenharmony_ci{
108262306a36Sopenharmony_ci	int ret;
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	ret = ad5064_spi_register_driver();
108562306a36Sopenharmony_ci	if (ret)
108662306a36Sopenharmony_ci		return ret;
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	ret = ad5064_i2c_register_driver();
108962306a36Sopenharmony_ci	if (ret) {
109062306a36Sopenharmony_ci		ad5064_spi_unregister_driver();
109162306a36Sopenharmony_ci		return ret;
109262306a36Sopenharmony_ci	}
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci	return 0;
109562306a36Sopenharmony_ci}
109662306a36Sopenharmony_cimodule_init(ad5064_init);
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_cistatic void __exit ad5064_exit(void)
109962306a36Sopenharmony_ci{
110062306a36Sopenharmony_ci	ad5064_i2c_unregister_driver();
110162306a36Sopenharmony_ci	ad5064_spi_unregister_driver();
110262306a36Sopenharmony_ci}
110362306a36Sopenharmony_cimodule_exit(ad5064_exit);
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ciMODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
110662306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD5024 and similar multi-channel DACs");
110762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
1108